Revert "temp revert rk change"
author黄涛 <huangtao@rock-chips.com>
Fri, 4 Nov 2011 09:43:18 +0000 (17:43 +0800)
committer黄涛 <huangtao@rock-chips.com>
Fri, 4 Nov 2011 09:43:18 +0000 (17:43 +0800)
This reverts commit 15f7fabcb88e67792e49279de0b28d70fcfca0cd.

Conflicts:

.gitignore
arch/arm/boot/compressed/head.S
arch/arm/common/gic.c
arch/arm/kernel/Makefile
arch/arm/mm/proc-v7.S
arch/arm/tools/mach-types
arch/arm/vfp/vfphw.S
drivers/Kconfig
drivers/Makefile
drivers/char/Makefile
drivers/cpufreq/cpufreq_ondemand.c
drivers/gpio/gpiolib.c
drivers/gpio/tps65910-gpio.c
drivers/input/Makefile
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/touchscreen/Kconfig
drivers/media/video/Makefile
drivers/media/video/ov2640.c
drivers/media/video/soc_camera.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/v4l2-ioctl.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-i2c.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm831x-spi.c
drivers/mfd/wm8994-core.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/pmem.c
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/host/Makefile
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/bcm4329/bcmsdh_linux.c
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/wl_iw.c
drivers/net/wireless/bcm4329/wl_iw.h
drivers/power/wm831x_power.c
drivers/regulator/Makefile
drivers/regulator/core.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/usb/Makefile
drivers/usb/gadget/Kconfig
drivers/usb/gadget/android.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/serial/option.c
drivers/video/backlight/wm831x_bl.c
fs/fat/dir.c
fs/fat/fatent.c
fs/fat/inode.c
fs/yaffs2/yaffs_fs.c
fs/yaffs2/yaffs_mtdif2.c
include/linux/i2c.h
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm831x/pdata.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/pdata.h
include/linux/regulator/consumer.h
include/media/v4l2-chip-ident.h
kernel/power/earlysuspend.c
kernel/power/wakelock.c
kernel/sys.c
mm/page_alloc.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm_hubs.c
sound/soc/soc-cache.c

144 files changed:
.gitignore
arch/arm/Kconfig
arch/arm/boot/compressed/head.S
arch/arm/common/gic.c
arch/arm/kernel/Makefile
arch/arm/kernel/head.S
arch/arm/mach-rk29/Makefile
arch/arm/mach-rk29/board-rk29-ddr3sdk.c
arch/arm/mach-rk29/clock.c
arch/arm/mach-rk29/devices.c
arch/arm/mach-rk29/gpio.c [deleted file]
arch/arm/mach-rk29/include/mach/board.h
arch/arm/mach-rk29/include/mach/debug-macro.S
arch/arm/mach-rk29/include/mach/gpio.h
arch/arm/mach-rk29/vpu_service.c
arch/arm/mm/proc-v7.S
arch/arm/tools/mach-types
arch/arm/vfp/vfphw.S
drivers/Kconfig
drivers/Makefile
drivers/base/power/main.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-rk29.c [new file with mode: 0755]
drivers/gpio/gpiolib.c
drivers/i2c/i2c-core.c
drivers/input/Makefile
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/tps65910-pwrbutton.c [deleted file]
drivers/input/touchscreen/Kconfig
drivers/media/video/Makefile
drivers/media/video/ov2640.c
drivers/media/video/soc_camera.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/v4l2-ioctl.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/tps65910-core.c [deleted file]
drivers/mfd/wm831x-core.c
drivers/mfd/wm831x-i2c.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm831x-spi.c
drivers/mfd/wm8994-core.c [changed mode: 0755->0644]
drivers/misc/Kconfig [changed mode: 0755->0644]
drivers/misc/Makefile [changed mode: 0755->0644]
drivers/misc/apanic.c
drivers/misc/pmem.c
drivers/mmc/card/block.c
drivers/mmc/core/core.c
drivers/mmc/core/mmc.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/host/Makefile
drivers/mmc/host/rk29_sdmmc.c
drivers/mmc/host/rk29_sdmmc_old.c
drivers/mtd/rknand/rknand_base_ko.c
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/bcm4329/Kconfig
drivers/net/wireless/bcm4329/Makefile [changed mode: 0644->0755]
drivers/net/wireless/bcm4329/bcmsdh_linux.c
drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c
drivers/net/wireless/bcm4329/bcmspibrcm.c [new file with mode: 0644]
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_cdc.c
drivers/net/wireless/bcm4329/dhd_common.c
drivers/net/wireless/bcm4329/dhd_custom_gpio.c
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/dhd_sdio.c
drivers/net/wireless/bcm4329/include/epivers.h
drivers/net/wireless/bcm4329/include/wlioctl.h
drivers/net/wireless/bcm4329/linux_osl.c
drivers/net/wireless/bcm4329/wl_iw.c
drivers/net/wireless/bcm4329/wl_iw.h
drivers/power/wm831x_power.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/core.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/alarm.c
drivers/rtc/rtc-HYM8563.c
drivers/rtc/rtc-tps65910.c [deleted file]
drivers/serial/rk2818_serial.h [deleted file]
drivers/serial/rk29_serial.c [deleted file]
drivers/serial/rk_serial.c [deleted file]
drivers/serial/sc8800.c [deleted file]
drivers/serial/sc8800.h [deleted file]
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/timed_gpio.c
drivers/staging/android/timed_gpio.h
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_debug.c
drivers/staging/rk29/vivante/hal/os/linux/kernel/gc_hal_kernel_os.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/rk2818_serial.h [new file with mode: 0644]
drivers/tty/serial/rk_serial.c [new file with mode: 0644]
drivers/tty/serial/sc8800.c [new file with mode: 0755]
drivers/tty/serial/sc8800.h [new file with mode: 0755]
drivers/usb/Makefile
drivers/usb/core/usb.c [changed mode: 0755->0644]
drivers/usb/dwc_otg/dwc_otg_hcd.c
drivers/usb/dwc_otg/dwc_otg_pcd.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/android.c
drivers/usb/gadget/f_adb.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/storage_common.c
drivers/usb/serial/option.c
drivers/usb/storage/usb.c [changed mode: 0755->0644]
drivers/video/backlight/rk29_backlight.c
drivers/video/backlight/wm831x_bl.c
fs/fat/dir.c
fs/fat/fatent.c
fs/fat/inode.c
fs/yaffs2/yaffs_mtdif2.c
fs/yaffs2/yaffs_vfs.c
include/linux/gfp.h
include/linux/i2c.h [changed mode: 0755->0644]
include/linux/i2c/tps65910.h [deleted file]
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm831x/pdata.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/pdata.h
include/linux/mmc/host.h
include/linux/regulator/consumer.h [changed mode: 0755->0644]
include/linux/wakelock.h
include/media/v4l2-chip-ident.h
kernel/power/earlysuspend.c
kernel/power/process.c
kernel/power/wakelock.c
kernel/sys.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/wm8900.c
sound/soc/soc-cache.c

index 9dacde0a4b2dcec4ce33013354b6c46738daaef7..43c7ee06e0978b7e46bc1fa24f166ec4307c5eb7 100644 (file)
@@ -32,6 +32,7 @@ modules.builtin
 *.lzo
 *.patch
 *.gcno
+Untitled Project.*
 
 #
 # Top-level generic files
@@ -44,6 +45,7 @@ modules.builtin
 /System.map
 /Module.markers
 /Module.symvers
+/kernel.img
 
 #
 # git files that we don't want to ignore even it they are dot-files
index 38d4c961e5aff8ea510fe9711196cc4552214203..413834f6b7bc1a91e4365ce807d50a9d118a48da 100644 (file)
@@ -862,6 +862,7 @@ config ARCH_RK29
        bool "Rockchip Soc Rk29"
        select CPU_V7
        select HAVE_CLK
+       select CLKDEV_LOOKUP
        select COMMON_CLKDEV
        select HAVE_SCHED_CLOCK
        select ARCH_HAS_CPUFREQ
index e58603b00060032c625bcc4ce11613ca96344732..7140c2e648da52106dfde7f550fecb0ebc87cd6e 100644 (file)
@@ -177,6 +177,10 @@ not_angel:
 #endif
 
                bl      cache_on
+#ifdef CONFIG_ARCH_RK29
+               bl      cache_off
+               bl      cache_on
+#endif
 
 restart:       adr     r0, LC0
                ldmia   r0, {r1, r2, r3, r6, r10, r11, r12}
index 4ddd0a6ac7ff3d9db4f55b165c172ec144e90a51..9e74d12057f11fbbfbda417a13c54854c1c2ccbc 100755 (executable)
@@ -92,6 +92,9 @@ static void gic_mask_irq(struct irq_data *d)
        writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
        if (gic_arch_extn.irq_mask)
                gic_arch_extn.irq_mask(d);
+#ifdef CONFIG_ARCH_RK29
+       dsb();
+#endif
        spin_unlock(&irq_controller_lock);
 }
 
@@ -103,6 +106,9 @@ static void gic_unmask_irq(struct irq_data *d)
        if (gic_arch_extn.irq_unmask)
                gic_arch_extn.irq_unmask(d);
        writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
+#ifdef CONFIG_ARCH_RK29
+       dsb();
+#endif
        spin_unlock(&irq_controller_lock);
 }
 
@@ -115,6 +121,9 @@ static void gic_eoi_irq(struct irq_data *d)
        }
 
        writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
+#ifdef CONFIG_ARCH_RK29
+       dsb();
+#endif
 }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -203,6 +212,9 @@ static int gic_set_wake(struct irq_data *d, unsigned int on)
 {
        int ret = -ENXIO;
 
+#ifdef CONFIG_ARCH_RK29
+       return 0;
+#endif
        if (gic_arch_extn.irq_set_wake)
                ret = gic_arch_extn.irq_set_wake(d, on);
 
@@ -278,8 +290,13 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
         * Find out how many interrupts are supported.
         * The GIC only supports up to 1020 interrupt sources.
         */
+#ifdef CONFIG_ARCH_RK29
+       /* rk29 read GIC_DIST_CTR is 2, why? */
+       gic_irqs = NR_AIC_IRQS;
+#else
        gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
        gic_irqs = (gic_irqs + 1) * 32;
+#endif
        if (gic_irqs > 1020)
                gic_irqs = 1020;
 
index a5b31af5c2b81717bc98a6851a8daf2ec2b04d7a..64f12bdc46db2f294a444d13d26cdc6c7a8800f2 100644 (file)
@@ -15,7 +15,7 @@ CFLAGS_REMOVE_return_address.o = -pg
 
 obj-y          := elf.o entry-armv.o entry-common.o irq.o \
                   process.o ptrace.o return_address.o setup.o signal.o \
-                  sys_arm.o stacktrace.o time.o traps.o
+                  sys_arm.o stacktrace.o time.o traps.o dma.o
 
 obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o
 
index 278c1b0ebb2ee340fcb0e4f4b010c80e535c9308..d9d6533da09b2ce21ebf249900125c866c84dcda 100644 (file)
        .equ    swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
 
        .macro  pgtbl, rd, phys
+#ifdef CONFIG_ARCH_RK29
+       add     \rd, \phys, #((TEXT_OFFSET - 0x4000) & 0xffff0000)
+       add     \rd, \rd,   #((TEXT_OFFSET - 0x4000) & 0x0000ffff)
+#else
        add     \rd, \phys, #TEXT_OFFSET - 0x4000
+#endif
        .endm
 
 #ifdef CONFIG_XIP_KERNEL
index e36d1e4d2bd384a19d3cca48f031a37c353d22d6..11fbfae0c21d6064585ae73b7f54809efc591d8f 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o gpio.o ddr.o sram.o memcpy_dma.o reset.o
+obj-y += timer.o io.o devices.o iomux.o clock.o rk29-pl330.o dma.o ddr.o sram.o memcpy_dma.o reset.o
 obj-y += tests.o memtester.o
 obj-y += early_printk.o
 ifndef CONFIG_DEBUG_LL
index 08742acf002128e7a476e29fcdf99e6d28f76501..8ca56212d521eb758379f07fa02a887804941b5c 100755 (executable)
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/skbuff.h>
 #include <linux/spi/spi.h>
 #include <linux/mmc/host.h>
 #include <linux/android_pmem.h>
+#ifdef CONFIG_USB_ANDROID
 #include <linux/usb/android_composite.h>
+#endif
 
 #include <mach/hardware.h>
 #include <asm/setup.h>
@@ -2935,8 +2938,12 @@ static struct spi_board_info board_spi_devices[] = {
 
 static void __init rk29_gic_init_irq(void)
 {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
+       gic_init(0, 32, (void __iomem *)RK29_GICPERI_BASE, (void __iomem *)RK29_GICCPU_BASE);
+#else
        gic_dist_init(0, (void __iomem *)RK29_GICPERI_BASE, 32);
        gic_cpu_init(0, (void __iomem *)RK29_GICCPU_BASE);
+#endif
 }
 
 static void __init machine_rk29_init_irq(void)
@@ -3016,9 +3023,11 @@ static void __init machine_rk29_mapio(void)
 }
 
 MACHINE_START(RK29, "RK29board")
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37))
        /* UART for LL DEBUG */
        .phys_io        = RK29_UART1_PHYS & 0xfff00000,
        .io_pg_offst    = ((RK29_UART1_BASE) >> 18) & 0xfffc,
+#endif
        .boot_params    = RK29_SDRAM_PHYS + 0x88000,
        .fixup          = machine_rk29_fixup,
        .map_io         = machine_rk29_mapio,
index 327a321bfdcfb0696c9c260ccae71e7d698314a3..501fafe58b95ad2cba545af1b49bcea1e4f45321 100755 (executable)
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/version.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+#include <linux/clkdev.h>
+#else
 #include <asm/clkdev.h>
+#endif
 #include <mach/rk29_iomap.h>
 #include <mach/cru.h>
 #include <mach/pmu.h>
index 9c51f9b870898ce0ab5f0a6bf113bd1a8e3f7a02..6e20d9290ab3355a0f93da22bf3f31333172a192 100644 (file)
@@ -16,7 +16,9 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#ifdef CONFIG_USB_ANDROID
 #include <linux/usb/android_composite.h>
+#endif
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <asm/pmu.h>
@@ -746,7 +748,7 @@ struct platform_device usb_mass_storage_device = {
 };
 #endif
 
-
+#ifdef CONFIG_USB_ANDROID_RNDIS
 static struct usb_ether_platform_data rndis_pdata = {
        /* ethaddr is filled by board_serialno_setup */
        .ethaddr    = {0xf0, 0xde, 0xf1, 0x42, 0xe8, 0x10},
@@ -761,6 +763,7 @@ struct platform_device rk29_device_rndis = {
                .platform_data = &rndis_pdata,
        },
 };
+#endif
 
 #ifdef CONFIG_USB11_HOST
 static struct resource usb11_host_resource[] = {
diff --git a/arch/arm/mach-rk29/gpio.c b/arch/arm/mach-rk29/gpio.c
deleted file mode 100755 (executable)
index d37040a..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-/* arch/arm/mach-rk29/gpio.c
- *
- * Copyright (C) 2010 ROCKCHIP, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/rk29_iomap.h>
-#include <mach/iomux.h>
-#include <asm/gpio.h>
-
-
-#define to_rk29_gpio_chip(c) container_of(c, struct rk29_gpio_chip, chip)
-
-struct rk29_gpio_chip {
-       struct gpio_chip        chip;
-       unsigned short id;
-       short irq;
-       unsigned char  __iomem  *regbase;       /* Base of register bank */
-       struct clk *clk;
-       u32 suspend_wakeup;
-       u32 saved_wakeup;
-};
-
-static struct lock_class_key gpio_lock_class;
-
-static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
-static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
-static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset);
-static int rk29_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset, int val);
-static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset);
-static int rk29_gpiolib_PullUpDown(struct gpio_chip *chip, unsigned offset, unsigned enable);
-static int rk29_gpiolib_to_irq(struct gpio_chip *chip,unsigned offset);
-
-#define RK29_GPIO_CHIP(ID)                     \
-       {                                                               \
-               .chip = {                                               \
-                       .label            = "gpio" #ID,                 \
-                       .direction_input  = rk29_gpiolib_direction_input, \
-                       .direction_output = rk29_gpiolib_direction_output, \
-                       .get              = rk29_gpiolib_get,           \
-                       .set              = rk29_gpiolib_set,           \
-                       .pull_updown      = rk29_gpiolib_PullUpDown,    \
-                       .dbg_show         = rk29_gpiolib_dbg_show,      \
-                       .to_irq           = rk29_gpiolib_to_irq,        \
-                       .base             = PIN_BASE + ID*NUM_GROUP,    \
-                       .ngpio            = NUM_GROUP,                  \
-               },                                                      \
-               .id = ID, \
-               .irq = IRQ_GPIO##ID, \
-               .regbase = (unsigned char __iomem *) RK29_GPIO##ID##_BASE, \
-       }
-
-static struct rk29_gpio_chip rk29gpio_chip[] = {
-       RK29_GPIO_CHIP(0),
-       RK29_GPIO_CHIP(1),
-       RK29_GPIO_CHIP(2),
-       RK29_GPIO_CHIP(3),
-       RK29_GPIO_CHIP(4),
-       RK29_GPIO_CHIP(5),
-       RK29_GPIO_CHIP(6),
-};
-
-static inline void rk29_gpio_write(unsigned char  __iomem      *regbase, unsigned int regOff,unsigned int val)
-{
-       __raw_writel(val,regbase + regOff);
-}
-
-static inline unsigned int rk29_gpio_read(unsigned char  __iomem       *regbase, unsigned int regOff)
-{
-       return __raw_readl(regbase + regOff);
-}
-
-static inline void rk29_gpio_bitOp(unsigned char  __iomem      *regbase, unsigned int regOff,unsigned int mask,unsigned char opFlag)
-{
-       unsigned int valTemp = 0;
-       
-       if(opFlag == 0)//¶Ô¼Ä´æÆ÷ÏàӦλ½øÐÐÓë0²Ù×÷
-       {
-               valTemp = rk29_gpio_read(regbase,regOff);  
-               valTemp &= (~mask);;
-               rk29_gpio_write(regbase,regOff,valTemp);
-       }
-       else if(opFlag == 1)//¶Ô¼Ä´æÆ÷ÏàӦλ½øÐлò1²Ù×÷
-       {
-               valTemp = rk29_gpio_read(regbase,regOff);
-               valTemp |= mask;
-               rk29_gpio_write(regbase,regOff,valTemp);
-       }
-}
-
-static inline  struct gpio_chip *pin_to_gpioChip(unsigned pin)
-{
-       if(pin < PIN_BASE)
-               return NULL;
-       
-       pin -= PIN_BASE;
-       pin /= NUM_GROUP;
-       if (likely(pin < MAX_BANK))
-               return &(rk29gpio_chip[pin].chip);
-       return NULL;
-}
-
-static inline unsigned  pin_to_mask(unsigned pin)
-{
-       if(pin < PIN_BASE)
-               return 0;
-       pin -= PIN_BASE;
-       return 1ul << (pin % NUM_GROUP);
-}
-
-static inline unsigned  offset_to_mask(unsigned offset)
-{
-       return 1ul << (offset % NUM_GROUP);
-}
-
-static int GPIOSetPinLevel(struct gpio_chip *chip, unsigned int mask,eGPIOPinLevel_t level)
-{
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem  *gpioRegBase = rk29_gpio->regbase;
-       unsigned long flags;
-
-       if(!rk29_gpio || !gpioRegBase)
-       {
-               return -1;
-       }
-
-       local_irq_save(flags);
-       rk29_gpio_bitOp(gpioRegBase,GPIO_SWPORT_DDR,mask,1);
-       rk29_gpio_bitOp(gpioRegBase,GPIO_SWPORT_DR,mask,level);
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-static int GPIOGetPinLevel(struct gpio_chip *chip, unsigned int mask)
-{
-       unsigned int valTemp;
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem  *gpioRegBase = rk29_gpio->regbase;
-
-       if(!rk29_gpio || !gpioRegBase)
-       {
-               return -1;
-       }
-       
-       valTemp = rk29_gpio_read(gpioRegBase,GPIO_EXT_PORT);
-       return ((valTemp & mask) != 0);
-}
-
-static int GPIOSetPinDirection(struct gpio_chip *chip, unsigned int mask,eGPIOPinDirection_t direction)
-{
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem  *gpioRegBase = rk29_gpio->regbase;
-       unsigned long flags;
-
-       if(!rk29_gpio || !gpioRegBase)
-       {
-               return -1;
-       }
-
-       local_irq_save(flags);
-       rk29_gpio_bitOp(gpioRegBase,GPIO_SWPORT_DDR,mask,direction);
-       /* Enable debounce may halt cpu on wfi, disable it by default */
-       //rk29_gpio_bitOp(gpioRegBase,GPIO_DEBOUNCE,mask,1);
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-static int GPIOEnableIntr(struct gpio_chip *chip, unsigned int mask)
-{
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem  *gpioRegBase = rk29_gpio->regbase;
-
-       if(!rk29_gpio || !gpioRegBase)
-       {
-               return -1;
-       }
-       
-       rk29_gpio_bitOp(gpioRegBase,GPIO_INTEN,mask,1);
-
-       return 0;
-}
-
-static int GPIODisableIntr(struct gpio_chip *chip, unsigned int mask)
-{
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem  *gpioRegBase = rk29_gpio->regbase;
-
-       if(!rk29_gpio || !gpioRegBase)
-       {
-               return -1;
-       }
-
-       rk29_gpio_bitOp(gpioRegBase,GPIO_INTEN,mask,0);
-
-       return 0;
-}
-
-static int GPIOSetIntrType(struct gpio_chip *chip, unsigned int mask, eGPIOIntType_t IntType)
-{
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem  *gpioRegBase = rk29_gpio->regbase;
-
-       if(!rk29_gpio || !gpioRegBase)
-       {
-               return -1;
-       }
-       
-       switch ( IntType )
-       {
-           case GPIOLevelLow:
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,0);  
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,0); 
-                       break;
-           case GPIOLevelHigh:
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,0); 
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,1);  
-                       break;
-           case GPIOEdgelFalling:
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,1); 
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,0);  
-                       break;
-           case GPIOEdgelRising:
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INTTYPE_LEVEL,mask,1); 
-                       rk29_gpio_bitOp(gpioRegBase,GPIO_INT_POLARITY,mask,1);  
-                       break;
-               default:
-                       return(-1);
-       }
-        return(0);
-}
-
-static int gpio_irq_set_wake(unsigned int irq, unsigned int on)
-{
-       unsigned int pin = irq_to_gpio(irq);
-       unsigned bank = (pin - PIN_BASE) / NUM_GROUP;
-       struct rk29_gpio_chip *rk29_gpio;
-       unsigned mask = pin_to_mask(pin);
-
-       if (unlikely(bank >= MAX_BANK))
-               return -EINVAL;
-
-       rk29_gpio = &rk29gpio_chip[bank];
-       if (on)
-               rk29_gpio->suspend_wakeup |= mask;
-       else
-               rk29_gpio->suspend_wakeup &= ~mask;
-
-       set_irq_wake(rk29_gpio->irq, on);
-
-       return 0;
-}
-
-static int gpio_irq_type(unsigned irq, unsigned type)
-{
-       unsigned int pin = irq_to_gpio(irq);
-       struct gpio_chip *chip = pin_to_gpioChip(pin);
-       unsigned        mask = pin_to_mask(pin);
-       
-       if(!chip || !mask)
-               return -EINVAL;
-       //ÉèÖÃΪÖжÏ֮ǰ£¬±ØÐëÏÈÉèÖÃΪÊäÈë״̬
-       GPIOSetPinDirection(chip,mask,GPIO_IN);
-       
-       switch (type) {
-               case IRQ_TYPE_NONE:
-                       break;
-               case IRQ_TYPE_EDGE_RISING:
-                       GPIOSetIntrType(chip,mask,GPIOEdgelRising);
-                       break;
-               case IRQ_TYPE_EDGE_FALLING:
-                       GPIOSetIntrType(chip,mask,GPIOEdgelFalling);
-                       break;
-               case IRQ_TYPE_EDGE_BOTH:
-                       break;
-               case IRQ_TYPE_LEVEL_HIGH:
-                       GPIOSetIntrType(chip,mask,GPIOLevelHigh);
-                       break;
-               case IRQ_TYPE_LEVEL_LOW:
-                       GPIOSetIntrType(chip,mask,GPIOLevelLow);
-                       break;
-               default:
-                       return -EINVAL;
-       }
-
-       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-               __set_irq_handler_unlocked(irq, handle_level_irq);
-       else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-               __set_irq_handler_unlocked(irq, handle_edge_irq);
-
-       return 0;
-}
-
-static int GPIOAckIntr(struct gpio_chip *chip, unsigned int mask)
-{
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem  *gpioRegBase = rk29_gpio->regbase;
-
-       if(!rk29_gpio || !gpioRegBase)
-       {
-               return -1;
-       }
-       
-       rk29_gpio_bitOp(gpioRegBase,GPIO_PORTS_EOI,mask,1);
-       return 0;
-}
-
-static void gpio_irq_unmask(unsigned irq)
-{
-       unsigned int pin = irq_to_gpio(irq);
-       struct gpio_chip *chip = pin_to_gpioChip(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if(chip && mask)
-               GPIOEnableIntr(chip,mask);
-}
-
-static void gpio_irq_mask(unsigned irq)
-{
-       unsigned int pin = irq_to_gpio(irq);
-       struct gpio_chip *chip = pin_to_gpioChip(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if(chip && mask)
-               GPIODisableIntr(chip,mask);
-}
-
-static void gpio_ack_irq(u32 irq)
-{
-       unsigned int pin = irq_to_gpio(irq);
-       struct gpio_chip *chip = pin_to_gpioChip(pin);
-       unsigned        mask = pin_to_mask(pin);
-
-       if(chip && mask)
-               GPIOAckIntr(chip,mask);
-}
-
-static int GPIOPullUpDown(struct gpio_chip *chip, unsigned int offset, unsigned enable)
-{
-       unsigned int temp = 0;
-       struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-       unsigned char  __iomem *pGrfRegBase = (unsigned char  __iomem *)RK29_GRF_BASE;
-       unsigned long flags;
-
-       if(!rk29_gpio || !pGrfRegBase)
-       {
-               return -1;
-       }
-       
-       if(offset >= 32)
-       {
-               return -1;
-       }
-
-       local_irq_save(flags);
-       temp = __raw_readl(pGrfRegBase + 0x78 +(rk29_gpio->id)*4);
-       if(!enable)
-               temp |= 1<<offset;
-       else
-               temp &= ~(1<<offset);
-
-       __raw_writel(temp,pGrfRegBase + 0x78 +(rk29_gpio->id)*4);
-       local_irq_restore(flags);
-
-       return 0;
-}
-
-
-static int rk29_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset, int val)
-{
-       unsigned        mask = offset_to_mask(offset);
-       
-       if(GPIOSetPinDirection(chip,mask,GPIO_OUT) == 0)
-       {
-               return GPIOSetPinLevel(chip,mask,val);
-       }
-       else
-       {
-               return -1;
-       }
-}
-
-static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset)
-{
-       unsigned        mask = offset_to_mask(offset);
-       
-       return GPIOSetPinDirection(chip,mask,GPIO_IN);
-}
-
-
-static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset)
-{
-       unsigned        mask = offset_to_mask(offset);
-       
-       return GPIOGetPinLevel(chip,mask);
-}
-
-static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
-{
-       unsigned        mask = offset_to_mask(offset);
-       
-       GPIOSetPinLevel(chip,mask,val);
-}
-
-static int rk29_gpiolib_PullUpDown(struct gpio_chip *chip, unsigned offset, unsigned enable)
-{
-       return GPIOPullUpDown(chip, offset, enable);
-}
-
-static int rk29_gpiolib_to_irq(struct gpio_chip *chip,
-                                               unsigned offset)
-{
-    struct rk29_gpio_chip *rk29_gpio = to_rk29_gpio_chip(chip);
-
-    if(!rk29_gpio)
-    {
-        return -1;
-    }
-
-    return offset + NR_IRQS;
-}
-
-static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
-{
-
-       int i;
-
-       for (i = 0; i < chip->ngpio; i++) {
-               unsigned pin = chip->base + i;
-               struct gpio_chip *chip = pin_to_gpioChip(pin);
-               unsigned mask = pin_to_mask(pin);
-               const char *gpio_label;
-               
-               if(!chip ||!mask)
-                       return;
-               
-               gpio_label = gpiochip_is_requested(chip, i);
-               if (gpio_label) {
-                       seq_printf(s, "[%s] GPIO%s%d: ",
-                                  gpio_label, chip->label, i);
-                       
-                       if (!chip || !mask)
-                       {
-                               seq_printf(s, "!chip || !mask\t");
-                               return;
-                       }
-                               
-                       GPIOSetPinDirection(chip,mask,GPIO_IN);
-                       seq_printf(s, "pin=%d,level=%d\t", pin,GPIOGetPinLevel(chip,mask));
-                       seq_printf(s, "\t");
-               }
-       }
-}
-
-static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
-{
-       unsigned gpio_irq;
-       struct rk29_gpio_chip *rk29_gpio;
-       u32 isr;
-
-       rk29_gpio = get_irq_chip_data(irq+13);
-
-       // temporarily mask parent IRQ
-       desc->chip->mask(irq);
-       if(desc->chip->ack)
-               desc->chip->ack(irq);
-
-       isr = rk29_gpio_read(rk29_gpio->regbase, GPIO_INT_STATUS);
-
-       gpio_irq = gpio_to_irq(rk29_gpio->chip.base);
-
-       while (isr) {
-               int irqoffset = fls(isr) - 1;
-               generic_handle_irq(gpio_irq + irqoffset);
-               isr &= ~(1 << irqoffset);
-       }
-
-       desc->chip->unmask(irq);
-       /* now it may re-trigger */
-}
-
-static struct irq_chip rk29gpio_irqchip = {
-       .name           = "GPIO",
-       .ack            = gpio_ack_irq,
-       .disable        = gpio_irq_mask,
-       .mask           = gpio_irq_mask,
-       .unmask         = gpio_irq_unmask,
-       .set_type       = gpio_irq_type,
-       .set_wake       = gpio_irq_set_wake,
-};
-
-static void __init rk29_gpio_irq_setup(void)
-{
-       unsigned int i, j, pin;
-       struct rk29_gpio_chip *this;
-
-       this = rk29gpio_chip;
-       pin = NR_AIC_IRQS;
-       for (i = 0; i < MAX_BANK; i++) {
-               rk29_gpio_write(this->regbase,GPIO_INTEN,0);
-               for (j = 0; j < 32; j++) {
-                       lockdep_set_class(&irq_desc[pin+j].lock, &gpio_lock_class);
-                       set_irq_chip(pin+j, &rk29gpio_irqchip);
-                       set_irq_handler(pin+j, handle_level_irq);
-                       set_irq_flags(pin+j, IRQF_VALID);
-               }
-
-               set_irq_chip_data(NR_AIC_IRQS + this->id, this);
-               set_irq_chained_handler(this->irq, gpio_irq_handler);
-               this += 1; 
-               pin += 32;
-       }
-       printk("rk29_gpio_irq_setup: %d gpio irqs in 7 banks\n", pin - PIN_BASE);
-}
-
-void __init rk29_gpio_init(void)
-{
-       unsigned i;
-       struct rk29_gpio_chip *rk29_gpio;
-
-       for (i = 0; i < MAX_BANK; i++) {
-               rk29_gpio = &rk29gpio_chip[i];
-               rk29_gpio->clk = clk_get(NULL, rk29_gpio->chip.label);
-               clk_enable(rk29_gpio->clk);
-               gpiochip_add(&rk29_gpio->chip);
-       }
-       rk29_gpio_irq_setup();
-}
-
-__weak void rk29_setgpio_suspend_board(void)
-{
-}
-
-__weak void rk29_setgpio_resume_board(void)
-{
-}
-
-#ifdef CONFIG_PM
-static int rk29_gpio_suspend(struct sys_device *dev, pm_message_t mesg)
-{
-       unsigned i;
-       
-       rk29_setgpio_suspend_board();
-       
-       for (i = 0; i < MAX_BANK; i++) {
-               struct rk29_gpio_chip *rk29_gpio = &rk29gpio_chip[i];
-
-               rk29_gpio->saved_wakeup = rk29_gpio_read(rk29_gpio->regbase, GPIO_INTEN);
-               rk29_gpio_write(rk29_gpio->regbase, GPIO_INTEN, rk29_gpio->suspend_wakeup);
-
-               if (!rk29_gpio->suspend_wakeup)
-                       clk_disable(rk29_gpio->clk);
-       }
-
-       return 0;
-}
-
-static int rk29_gpio_resume(struct sys_device *dev)
-{
-       unsigned i;
-       for (i = 0; i < MAX_BANK; i++) {
-               struct rk29_gpio_chip *rk29_gpio = &rk29gpio_chip[i];
-
-               if (!rk29_gpio->suspend_wakeup)
-                       clk_enable(rk29_gpio->clk);
-
-               /* keep enable for resume irq */
-               rk29_gpio_write(rk29_gpio->regbase, GPIO_INTEN, rk29_gpio->saved_wakeup | (rk29_gpio->suspend_wakeup & rk29_gpio_read(rk29_gpio->regbase, GPIO_INT_STATUS)));
-       }
-       rk29_setgpio_resume_board();
-       return 0;
-}
-
-static struct sysdev_class rk29_gpio_sysclass = {
-        .name           = "gpio",
-        .suspend        = rk29_gpio_suspend,
-        .resume         = rk29_gpio_resume,
-};
-
-static struct sys_device rk29_gpio_device = {
-        .cls            = &rk29_gpio_sysclass,
-};
-
-static int __init rk29_gpio_sysinit(void)
-{
-        int ret = sysdev_class_register(&rk29_gpio_sysclass);
-        if (ret == 0)
-                ret = sysdev_register(&rk29_gpio_device);
-        return ret;
-}
-
-arch_initcall(rk29_gpio_sysinit);
-#endif
index 7cec44db21f5fab5052a14becd312d9dd91637d4..d56c42310dba35379f686cc570158b2e1b6883bd 100755 (executable)
@@ -124,6 +124,7 @@ struct rk29_bl_info{
        unsigned int delay_ms;  /* in milliseconds */
 };
 
+#ifndef _LINUX_WLAN_PLAT_H_
 struct wifi_platform_data {
         int (*set_power)(int val);
         int (*set_reset)(int val);
@@ -131,6 +132,7 @@ struct wifi_platform_data {
         void *(*mem_prealloc)(int section, unsigned long size);
         int (*get_mac_addr)(unsigned char *buf);
 };
+#endif
 
 struct rk29_sdmmc_platform_data {
        unsigned int host_caps;
index 9c86875157c79c56296d4774882c8ea183146e01..a58b1399e13cc8f65abe48fd5e57491ee8263083 100644 (file)
 #include <linux/version.h>
 #include <mach/rk29_iomap.h>
 
-       /* note, for the boot process to work we have to keep the UART
-        * virtual address aligned to an 1MiB boundary for the L1
-        * mapping the head code makes. We keep the UART virtual address
-        * aligned and add in the offset when we load the value here.
-        */
-
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       .macro addruart, rp, rv
+               ldr     \rp, = RK29_UART1_PHYS
+               ldr     \rv, = RK29_UART1_BASE
+       .endm
+#else
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34))
        .macro addruart, rx, tmp
 #else
@@ -34,6 +34,7 @@
                ldreq   \rx, = RK29_UART1_PHYS
                ldrne   \rx, = RK29_UART1_BASE
        .endm
+#endif
 
 #define UART_SHIFT     2
 #include <asm/hardware/debug-8250.S>
index 1efd3f0ce0b48cb265aa286de264c1641b2c5a9f..a0f0309cbe8fdee3ec4a9489f56574c73f76596b 100755 (executable)
@@ -14,7 +14,8 @@
  */
 #ifndef __ARCH_ARM_MACH_RK29_GPIO_H
 #define __ARCH_ARM_MACH_RK29_GPIO_H
-#include <asm/irq.h>
+
+#include <mach/irqs.h>
  
 typedef enum eGPIOPinLevel
 {
@@ -67,7 +68,7 @@ typedef enum GPIOIntType {
 #define RK29_ID_GPIO6                  6
 
 #define NUM_GROUP                              32
-#define PIN_BASE                               0
+#define PIN_BASE                               NR_AIC_IRQS
 #define MAX_BANK                               7
 
 #define RK29_TOTOL_GPIO_NUM    (NUM_GROUP*MAX_BANK)
@@ -105,7 +106,7 @@ typedef enum GPIOIntType {
 #endif
 
 //¶¨ÒåGPIOµÄPIN¿Ú×î´óÊýÄ¿¡£CONFIG_SPI_FPGA_GPIO_NUM±íʾFPGAµÄPIN½ÅÊý¡£
-#define ARCH_NR_GPIOS  (RK29_TOTOL_GPIO_NUM + TCA6424_TOTOL_GPIO_NUM + WM831X_TOTOL_GPIO_NUM + CONFIG_SPI_FPGA_GPIO_NUM+CONFIG_GPIO_WM8994_NUM)
+#define ARCH_NR_GPIOS  (PIN_BASE + RK29_TOTOL_GPIO_NUM + TCA6424_TOTOL_GPIO_NUM + WM831X_TOTOL_GPIO_NUM + CONFIG_SPI_FPGA_GPIO_NUM+CONFIG_GPIO_WM8994_NUM)
 
 
 #define        RK29_PIN0_PA0           (0*NUM_GROUP + PIN_BASE + 0)
@@ -506,7 +507,6 @@ extern void __init rk29_gpio_init(void);
 
 #include <asm/errno.h>
 #include <asm-generic/gpio.h>          /* cansleep wrappers */
-#include <mach/irqs.h>
 
 #define gpio_get_value __gpio_get_value
 #define gpio_set_value __gpio_set_value
@@ -514,15 +514,14 @@ extern void __init rk29_gpio_init(void);
 
 static inline int gpio_to_irq(unsigned gpio)
 {
-       return (gpio + NR_AIC_IRQS);
+       return gpio - PIN_BASE + NR_AIC_IRQS;
 }
 
 static inline int irq_to_gpio(unsigned irq)
 {
-       return (irq - NR_AIC_IRQS);       
+       return irq - NR_AIC_IRQS + PIN_BASE;
 }
 
-#endif /* __ASSEMBLY__ */     
-                                                                                                                                                             
-#endif                                                                                              
-                                                                                 
+#endif /* __ASSEMBLY__ */
+
+#endif
index b3242e0e9dce026783b02986ad39b52f3e8b4c70..eb1eda5a835848ca83babdb11b11c3605b45b90f 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/mm.h>
 #include <linux/poll.h>
 #include <linux/platform_device.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 
index 089c0b5e454fccbdbc63a4d4e9d72d15baa7075a..628198281cea1ee48314ff613ff922fe255ee06d 100644 (file)
@@ -375,6 +375,16 @@ __v7_setup:
        ALT_SMP(orr     r8, r8, #TTB_FLAGS_SMP)
        ALT_UP(orr      r8, r8, #TTB_FLAGS_UP)
        mcr     p15, 0, r8, c2, c0, 1           @ load TTB1
+#ifdef CONFIG_ARCH_RK29
+       /* Setup L2 cache */
+       mrc     p15, 1, r5, c9, c0, 2
+       bic     r5, r5, #1 << 29                @ L2 data RAM read multiplexer select: 0 = two cycles
+       bic     r5, r5, #7 << 6
+       bic     r5, r5, #15
+       orr     r5, r5, #2 << 6                 @ Tag RAM latency: b010 = 3 cycles
+       orr     r5, r5, #3                      @ Data RAM latency: b0011 = 4 cycles
+       mcr     p15, 1, r5, c9, c0, 2
+#endif
        ldr     r5, =PRRR                       @ PRRR
        ldr     r6, =NMRR                       @ NMRR
        mcr     p15, 0, r5, c10, c2, 0          @ write PRRR
index 3b3776d0a1a764e5edfd2a57a01f5a7fbd644bc0..9afa8404fd7973926a7c7e8ea2234b264d266153 100644 (file)
@@ -569,7 +569,8 @@ smdkv310            MACH_SMDKV310           SMDKV310                2925
 siemens_l0             MACH_SIEMENS_L0         SIEMENS_L0              2926
 ventana                        MACH_VENTANA            VENTANA                 2927
 wm8505_7in_netbook     MACH_WM8505_7IN_NETBOOK WM8505_7IN_NETBOOK      2928
-ec4350sdb              MACH_EC4350SDB          EC4350SDB               2929
+rk29                   MACH_RK29               RK29                    2929
+#ec4350sdb             MACH_EC4350SDB          EC4350SDB               2929
 mimas                  MACH_MIMAS              MIMAS                   2930
 titan                  MACH_TITAN              TITAN                   2931
 craneboard             MACH_CRANEBOARD         CRANEBOARD              2932
index 9897dcfc16d67a0e104552814adaad8ec1230e32..f879b7ac2a4e983981a8e92909e81cc2d14ee8e7 100644 (file)
@@ -206,6 +206,25 @@ ENTRY(vfp_save_state)
        mov     pc, lr
 ENDPROC(vfp_save_state)
 
+#ifdef CONFIG_ARCH_RK29
+ENTRY(vfp_load_state)
+       @ Save the current VFP state
+       @ r0 - save location
+       @ r1 - FPEXC
+       DBGSTR1 "save VFP state %p", r0
+       VFPFLDMIA r0, r2                @ save the working registers
+       ldmia   r0, {r1,r2,r3,r12}
+       tst     r1, #FPEXC_EX           @ is there additional state to save?
+       beq     1f
+       tst     r1, #FPEXC_FP2V         @ is there an FPINST2 to read?
+       beq     1f
+1:
+       VFPFMXR FPSCR, r2
+       VFPFMXR FPEXC, r1
+       mov     pc, lr
+ENDPROC(vfp_load_state)
+#endif
+
        .align
 last_VFP_context_address:
        .word   last_VFP_context
index d0258eb26d8b81c5b0aa54a4d946d01094aec5c1..a95047a6fe0a34880f15ab353bef8dbea187805d 100755 (executable)
@@ -52,6 +52,10 @@ source "drivers/i2c/Kconfig"
 
 source "drivers/spi/Kconfig"
 
+source "drivers/adc/Kconfig"
+
+source "drivers/headset_observe/Kconfig"
+
 source "drivers/pps/Kconfig"
 
 source "drivers/ptp/Kconfig"
@@ -128,4 +132,12 @@ source "drivers/hwspinlock/Kconfig"
 
 source "drivers/clocksource/Kconfig"
 
+source "drivers/cmmb/Kconfig"
+
+source "drivers/testcode/Kconfig"
+
+source "drivers/smc/Kconfig"
+
+source "drivers/cir/Kconfig"
+
 endmenu
index 4ea4ac9e57af34b6cc7e78ec3c2af75ceb4d3546..8e593d120cab0ca410675177f51200c39664d453 100755 (executable)
@@ -51,6 +51,7 @@ obj-$(CONFIG_ATA)             += ata/
 obj-$(CONFIG_TARGET_CORE)      += target/
 obj-$(CONFIG_MTD)              += mtd/
 obj-$(CONFIG_SPI)              += spi/
+obj-y                          += headset_observe/
 obj-y                          += net/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_FUSION)           += message/
@@ -77,6 +78,7 @@ obj-$(CONFIG_INPUT)           += input/
 obj-$(CONFIG_I2O)              += message/
 obj-$(CONFIG_RTC_LIB)          += rtc/
 obj-y                          += i2c/ media/
+obj-y                          += adc/
 obj-$(CONFIG_PPS)              += pps/
 obj-$(CONFIG_PTP_1588_CLOCK)   += ptp/
 obj-$(CONFIG_W1)               += w1/
@@ -123,3 +125,8 @@ obj-y                               += ieee802154/
 obj-y                          += clk/
 
 obj-$(CONFIG_HWSPINLOCK)       += hwspinlock/
+obj-$(CONFIG_CMMB)             += cmmb/
+obj-$(CONFIG_TEST_CODE)                += testcode/
+obj-y                          += smc/
+obj-y                          += cir/
+obj-y                          += dbg/
index 4282d442d35231c83c74dab5cbc5ee3bf4a696ef..0a02634fb0f187cf2b8846264fa40bf63ace569d 100644 (file)
@@ -28,6 +28,9 @@
 #include <linux/async.h>
 #include <linux/suspend.h>
 #include <linux/timer.h>
+#ifdef CONFIG_ARCH_RK29
+#include <linux/console.h>
+#endif
 
 #include "../base.h"
 #include "power.h"
@@ -608,6 +611,9 @@ static void dpm_drv_timeout(unsigned long data)
        printk(KERN_EMERG "**** DPM device timeout: %s (%s)\n", dev_name(dev),
               (dev->driver ? dev->driver->name : "no driver"));
 
+#ifdef CONFIG_ARCH_RK29
+       resume_console();
+#endif
        printk(KERN_EMERG "dpm suspend stack:\n");
        show_stack(tsk, NULL);
 
index 891360edecdd218fcd200e5c1e47f28f3ff07d52..ce0b7a41f73c611f0cb1dd609a4263517c306ede 100644 (file)
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
 #define DEF_SAMPLING_DOWN_FACTOR               (1)
 #define MAX_SAMPLING_DOWN_FACTOR               (100000)
+#ifdef CONFIG_ARCH_RK29
+#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL      (10)
+#define MICRO_FREQUENCY_UP_THRESHOLD           (80)
+#else
 #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL      (3)
 #define MICRO_FREQUENCY_UP_THRESHOLD           (95)
+#endif
 #define MICRO_FREQUENCY_MIN_SAMPLE_RATE                (10000)
 #define MIN_FREQUENCY_UP_THRESHOLD             (11)
 #define MAX_FREQUENCY_UP_THRESHOLD             (100)
index 9fed5e895514a30bbd5dfbe05893fe314698d2d5..3b8f6043bf0c4436e1ce47da74bc4f33e73b92d8 100755 (executable)
@@ -268,13 +268,6 @@ config GPIO_TWL4030
          Say yes here to access the GPIO signals of various multi-function
          power management chips from Texas Instruments.
 
-config GPIO_TPS65910
-       bool "TPS65910 GPIOs"
-       depends on TPS65910_CORE
-       help
-         Say yes here to access the GPIO signal of TPS65910x multi-function
-         power management chips from Texas Instruments.
-
 config GPIO_WM831X
        tristate "WM831x GPIOs"
        depends on MFD_WM831X
index 862b7b266897953c1dd5e6fbb69d1ba771e2eff6..c579c8bf5dc8d36e4ace84c4a367b876a862697a 100755 (executable)
@@ -29,7 +29,6 @@ obj-$(CONFIG_GPIO_STMPE)      += stmpe-gpio.o
 obj-$(CONFIG_GPIO_TC3589X)     += tc3589x-gpio.o
 obj-$(CONFIG_GPIO_TIMBERDALE)  += timbgpio.o
 obj-$(CONFIG_GPIO_TWL4030)     += twl4030-gpio.o
-obj-$(CONFIG_GPIO_TPS65910)    += tps65910-gpio.o
 obj-$(CONFIG_GPIO_UCB1400)     += ucb1400_gpio.o
 obj-$(CONFIG_GPIO_XILINX)      += xilinx_gpio.o
 obj-$(CONFIG_GPIO_CS5535)      += cs5535-gpio.o
@@ -46,6 +45,7 @@ obj-$(CONFIG_GPIO_SCH)                += sch_gpio.o
 obj-$(CONFIG_MACH_U300)                += gpio-u300.o
 obj-$(CONFIG_PLAT_NOMADIK)     += gpio-nomadik.o
 obj-$(CONFIG_GPIO_RDC321X)     += rdc321x-gpio.o
+obj-$(CONFIG_ARCH_RK29)                += gpio-rk29.o
 obj-$(CONFIG_GPIO_JANZ_TTL)    += janz-ttl.o
 obj-$(CONFIG_GPIO_SX150X)      += sx150x.o
 obj-$(CONFIG_GPIO_VX855)       += vx855_gpio.o
diff --git a/drivers/gpio/gpio-rk29.c b/drivers/gpio/gpio-rk29.c
new file mode 100755 (executable)
index 0000000..9609618
--- /dev/null
@@ -0,0 +1,484 @@
+/* arch/arm/mach-rk29/gpio.c
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/syscore_ops.h>
+
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/rk29_iomap.h>
+#include <mach/iomux.h>
+#include <asm/gpio.h>
+#include <asm/mach/irq.h>
+
+#define MAX_PIN        RK29_PIN6_PD7
+
+#define to_rk29_gpio_bank(c) container_of(c, struct rk29_gpio_bank, chip)
+
+struct rk29_gpio_bank {
+       struct gpio_chip chip;
+       unsigned short id;
+       short irq;
+       void __iomem *regbase;  /* Base of register bank */
+       struct clk *clk;
+       u32 suspend_wakeup;
+       u32 saved_wakeup;
+       spinlock_t lock;
+};
+
+static struct lock_class_key gpio_lock_class;
+
+static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip);
+static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val);
+static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset);
+static int rk29_gpiolib_direction_output(struct gpio_chip *chip,unsigned offset, int val);
+static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset);
+static int rk29_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable);
+static int rk29_gpiolib_to_irq(struct gpio_chip *chip,unsigned offset);
+
+#define RK29_GPIO_BANK(ID)                     \
+       {                                                               \
+               .chip = {                                               \
+                       .label            = "gpio" #ID,                 \
+                       .direction_input  = rk29_gpiolib_direction_input, \
+                       .direction_output = rk29_gpiolib_direction_output, \
+                       .get              = rk29_gpiolib_get,           \
+                       .set              = rk29_gpiolib_set,           \
+                       .pull_updown      = rk29_gpiolib_pull_updown,   \
+                       .dbg_show         = rk29_gpiolib_dbg_show,      \
+                       .to_irq           = rk29_gpiolib_to_irq,        \
+                       .base             = PIN_BASE + ID*NUM_GROUP,    \
+                       .ngpio            = NUM_GROUP,                  \
+               },                                                      \
+               .id = ID, \
+               .irq = IRQ_GPIO##ID, \
+               .regbase = (unsigned char __iomem *) RK29_GPIO##ID##_BASE, \
+       }
+
+static struct rk29_gpio_bank rk29_gpio_banks[] = {
+       RK29_GPIO_BANK(0),
+       RK29_GPIO_BANK(1),
+       RK29_GPIO_BANK(2),
+       RK29_GPIO_BANK(3),
+       RK29_GPIO_BANK(4),
+       RK29_GPIO_BANK(5),
+       RK29_GPIO_BANK(6),
+};
+
+static inline void rk29_gpio_bit_op(void __iomem *regbase, unsigned int offset, u32 bit, unsigned char flag)
+{
+       u32 val = __raw_readl(regbase + offset);
+       if (flag)
+               val |= bit;
+       else
+               val &= ~bit;
+       __raw_writel(val, regbase + offset);
+}
+
+static inline struct gpio_chip *pin_to_gpio_chip(unsigned pin)
+{
+       if (pin < PIN_BASE || pin > MAX_PIN)
+               return NULL;
+
+       pin -= PIN_BASE;
+       pin /= NUM_GROUP;
+       if (likely(pin < ARRAY_SIZE(rk29_gpio_banks)))
+               return &(rk29_gpio_banks[pin].chip);
+       return NULL;
+}
+
+static inline unsigned gpio_to_bit(unsigned gpio)
+{
+       gpio -= PIN_BASE;
+       return 1u << (gpio % NUM_GROUP);
+}
+
+static inline unsigned offset_to_bit(unsigned offset)
+{
+       return 1u << offset;
+}
+
+static void GPIOSetPinLevel(void __iomem *regbase, unsigned int bit, eGPIOPinLevel_t level)
+{
+       rk29_gpio_bit_op(regbase, GPIO_SWPORT_DDR, bit, 1);
+       rk29_gpio_bit_op(regbase, GPIO_SWPORT_DR, bit, level);
+}
+
+static int GPIOGetPinLevel(void __iomem *regbase, unsigned int bit)
+{
+       return ((__raw_readl(regbase + GPIO_EXT_PORT) & bit) != 0);
+}
+
+static void GPIOSetPinDirection(void __iomem *regbase, unsigned int bit, eGPIOPinDirection_t direction)
+{
+       rk29_gpio_bit_op(regbase, GPIO_SWPORT_DDR, bit, direction);
+       /* Enable debounce may halt cpu on wfi, disable it by default */
+       //rk29_gpio_bit_op(regbase, GPIO_DEBOUNCE, bit, 1);
+}
+
+static void GPIOEnableIntr(void __iomem *regbase, unsigned int bit)
+{
+       rk29_gpio_bit_op(regbase, GPIO_INTEN, bit, 1);
+}
+
+static void GPIODisableIntr(void __iomem *regbase, unsigned int bit)
+{
+       rk29_gpio_bit_op(regbase, GPIO_INTEN, bit, 0);
+}
+
+static void GPIOAckIntr(void __iomem *regbase, unsigned int bit)
+{
+       rk29_gpio_bit_op(regbase, GPIO_PORTS_EOI, bit, 1);
+}
+
+static void GPIOSetIntrType(void __iomem *regbase, unsigned int bit, eGPIOIntType_t type)
+{
+       switch (type) {
+       case GPIOLevelLow:
+               rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
+               rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
+               break;
+       case GPIOLevelHigh:
+               rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 0);
+               rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
+               break;
+       case GPIOEdgelFalling:
+               rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
+               rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 0);
+               break;
+       case GPIOEdgelRising:
+               rk29_gpio_bit_op(regbase, GPIO_INTTYPE_LEVEL, bit, 1);
+               rk29_gpio_bit_op(regbase, GPIO_INT_POLARITY, bit, 1);
+               break;
+       }
+}
+
+static int rk29_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       eGPIOIntType_t int_type;
+       unsigned long flags;
+
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+               int_type = GPIOEdgelRising;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               int_type = GPIOEdgelFalling;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               int_type = GPIOLevelHigh;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               int_type = GPIOLevelLow;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&bank->lock, flags);
+       //ÉèÖÃΪÖжÏ֮ǰ£¬±ØÐëÏÈÉèÖÃΪÊäÈë״̬
+       GPIOSetPinDirection(bank->regbase, bit, GPIO_IN);
+       GPIOSetIntrType(bank->regbase, bit, int_type);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+               __irq_set_handler_locked(d->irq, handle_level_irq);
+       else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+               __irq_set_handler_locked(d->irq, handle_edge_irq);
+
+       return 0;
+}
+
+static int rk29_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       if (on)
+               bank->suspend_wakeup |= bit;
+       else
+               bank->suspend_wakeup &= ~bit;
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static void rk29_gpio_irq_unmask(struct irq_data *d)
+{
+       struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOEnableIntr(bank->regbase, bit);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void rk29_gpio_irq_mask(struct irq_data *d)
+{
+       struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIODisableIntr(bank->regbase, bit);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static void rk29_gpio_irq_ack(struct irq_data *d)
+{
+       struct rk29_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       u32 bit = gpio_to_bit(irq_to_gpio(d->irq));
+
+       GPIOAckIntr(bank->regbase, bit);
+}
+
+static int rk29_gpiolib_direction_output(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
+       u32 bit = offset_to_bit(offset);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOSetPinDirection(bank->regbase, bit, GPIO_OUT);
+       GPIOSetPinLevel(bank->regbase, bit, val);
+       spin_unlock_irqrestore(&bank->lock, flags);
+       return 0;
+}
+
+static int rk29_gpiolib_direction_input(struct gpio_chip *chip,unsigned offset)
+{
+       struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOSetPinDirection(bank->regbase, offset_to_bit(offset), GPIO_IN);
+       spin_unlock_irqrestore(&bank->lock, flags);
+       return 0;
+}
+
+
+static int rk29_gpiolib_get(struct gpio_chip *chip, unsigned offset)
+{
+       return GPIOGetPinLevel(to_rk29_gpio_bank(chip)->regbase, offset_to_bit(offset));
+}
+
+static void rk29_gpiolib_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+       struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       GPIOSetPinLevel(bank->regbase, offset_to_bit(offset), val);
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int rk29_gpiolib_pull_updown(struct gpio_chip *chip, unsigned offset, unsigned enable)
+{
+       struct rk29_gpio_bank *bank = to_rk29_gpio_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+       rk29_gpio_bit_op((void *__iomem) RK29_GRF_BASE, 0x78 + bank->id * 4, offset_to_bit(offset), !enable);
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static int rk29_gpiolib_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       return chip->base + offset;
+}
+
+static void rk29_gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+#if 0
+       int i;
+
+       for (i = 0; i < chip->ngpio; i++) {
+               unsigned pin = chip->base + i;
+               struct gpio_chip *chip = pin_to_gpioChip(pin);
+               u32 bit = pin_to_bit(pin);
+               const char *gpio_label;
+               
+               if(!chip ||!bit)
+                       return;
+               
+               gpio_label = gpiochip_is_requested(chip, i);
+               if (gpio_label) {
+                       seq_printf(s, "[%s] GPIO%s%d: ",
+                                  gpio_label, chip->label, i);
+                       
+                       if (!chip || !bit)
+                       {
+                               seq_printf(s, "!chip || !bit\t");
+                               return;
+                       }
+                               
+                       GPIOSetPinDirection(chip,bit,GPIO_IN);
+                       seq_printf(s, "pin=%d,level=%d\t", pin,GPIOGetPinLevel(chip,bit));
+                       seq_printf(s, "\t");
+               }
+       }
+#endif
+}
+
+static void rk29_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct rk29_gpio_bank *bank = irq_get_handler_data(irq);
+       struct irq_chip *chip = irq_desc_get_chip(desc);
+       unsigned gpio_irq;
+       u32 isr, ilr;
+       unsigned pin;
+       unsigned unmasked = 0;
+
+       chained_irq_enter(chip, desc);
+
+       isr = __raw_readl(bank->regbase + GPIO_INT_STATUS);
+       ilr = __raw_readl(bank->regbase + GPIO_INTTYPE_LEVEL);
+
+       gpio_irq = gpio_to_irq(bank->chip.base);
+
+       while (isr) {
+               pin = fls(isr) - 1;
+               /* if gpio is edge triggered, clear condition
+                * before executing the hander so that we don't
+                * miss edges
+                 */
+               if (ilr & (1 << pin)) {
+                       unmasked = 1;
+                       chained_irq_exit(chip, desc);
+               }
+
+               generic_handle_irq(gpio_irq + pin);
+               isr &= ~(1 << pin);
+       }
+
+       if (!unmasked)
+               chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip rk29_gpio_irq_chip = {
+       .name           = "GPIO",
+       .irq_ack        = rk29_gpio_irq_ack,
+       .irq_disable    = rk29_gpio_irq_mask,
+       .irq_mask       = rk29_gpio_irq_mask,
+       .irq_unmask     = rk29_gpio_irq_unmask,
+       .irq_set_type   = rk29_gpio_irq_set_type,
+       .irq_set_wake   = rk29_gpio_irq_set_wake,
+};
+
+void __init rk29_gpio_init(void)
+{
+       unsigned int i, j, pin;
+       struct rk29_gpio_bank *bank;
+
+       bank = rk29_gpio_banks;
+       pin = PIN_BASE;
+
+       for (i = 0; i < ARRAY_SIZE(rk29_gpio_banks); i++, bank++, pin += 32) {
+               spin_lock_init(&bank->lock);
+               bank->clk = clk_get(NULL, bank->chip.label);
+               clk_enable(bank->clk);
+               gpiochip_add(&bank->chip);
+
+               __raw_writel(0, bank->regbase + GPIO_INTEN);
+               for (j = 0; j < 32; j++) {
+                       unsigned int irq = gpio_to_irq(pin + j);
+                       irq_set_lockdep_class(irq, &gpio_lock_class);
+                       irq_set_chip_data(irq, bank);
+                       irq_set_chip_and_handler(irq, &rk29_gpio_irq_chip, handle_level_irq);
+                       set_irq_flags(irq, IRQF_VALID);
+               }
+
+               irq_set_handler_data(bank->irq, bank);
+               irq_set_chained_handler(bank->irq, rk29_gpio_irq_handler);
+       }
+       printk("%s: %d gpio irqs in %d banks\n", __func__, pin - PIN_BASE, ARRAY_SIZE(rk29_gpio_banks));
+}
+
+#ifdef CONFIG_PM
+__weak void rk29_setgpio_suspend_board(void)
+{
+}
+
+__weak void rk29_setgpio_resume_board(void)
+{
+}
+
+static int rk29_gpio_suspend(void)
+{
+       unsigned i;
+       
+       rk29_setgpio_suspend_board();
+
+       for (i = 0; i < ARRAY_SIZE(rk29_gpio_banks); i++) {
+               struct rk29_gpio_bank *bank = &rk29_gpio_banks[i];
+
+               bank->saved_wakeup = __raw_readl(bank->regbase + GPIO_INTEN);
+               __raw_writel(bank->suspend_wakeup, bank->regbase + GPIO_INTEN);
+
+               if (!bank->suspend_wakeup)
+                       clk_disable(bank->clk);
+       }
+
+       return 0;
+}
+
+static void rk29_gpio_resume(void)
+{
+       unsigned i;
+
+       for (i = 0; i < ARRAY_SIZE(rk29_gpio_banks); i++) {
+               struct rk29_gpio_bank *bank = &rk29_gpio_banks[i];
+               u32 isr;
+
+               if (!bank->suspend_wakeup)
+                       clk_enable(bank->clk);
+
+               /* keep enable for resume irq */
+               isr = __raw_readl(bank->regbase + GPIO_INT_STATUS);
+               __raw_writel(bank->saved_wakeup | (bank->suspend_wakeup & isr), bank->regbase + GPIO_INTEN);
+       }
+
+       rk29_setgpio_resume_board();
+}
+
+static struct syscore_ops rk29_gpio_syscore_ops = {
+       .suspend        = rk29_gpio_suspend,
+       .resume         = rk29_gpio_resume,
+};
+
+static int __init rk29_gpio_sysinit(void)
+{
+       register_syscore_ops(&rk29_gpio_syscore_ops);
+        return 0;
+}
+
+arch_initcall(rk29_gpio_sysinit);
+#endif
index a971e3d043ba0535ed0539146b5530443cd8af17..05c523cd26944075cf88c770ee0f9c8ba0728013 100644 (file)
@@ -1429,6 +1429,8 @@ int gpio_direction_output(unsigned gpio, int value)
 
        spin_lock_irqsave(&gpio_lock, flags);
 
+       if (value !=0 && value !=1)
+               goto fail;
        if (!gpio_is_valid(gpio))
                goto fail;
        chip = desc->chip;
@@ -1475,6 +1477,67 @@ fail:
 }
 EXPORT_SYMBOL_GPL(gpio_direction_output);
 
+/* 
+gpio pull up or pull down
+value = 0, normal
+value = 1, pull up
+value = 2, pull down
+*/
+int gpio_pull_updown(unsigned gpio, unsigned value)
+{
+       unsigned long           flags;
+       struct gpio_chip        *chip;
+       struct gpio_desc        *desc = &gpio_desc[gpio];
+       int                     status = -EINVAL;
+
+       spin_lock_irqsave(&gpio_lock, flags);
+       
+       if (value >3)
+               goto fail;
+       if (!gpio_is_valid(gpio))
+               goto fail;
+       chip = desc->chip;
+       if (!chip || !chip->get || !chip->pull_updown)
+               goto fail;
+       gpio -= chip->base;
+       if (gpio >= chip->ngpio)
+               goto fail;
+       status = gpio_ensure_requested(desc, gpio);
+       if (status < 0)
+               goto fail;
+
+       /* now we know the gpio is valid and chip won't vanish */
+
+       spin_unlock_irqrestore(&gpio_lock, flags);
+
+       might_sleep_if(extra_checks && chip->can_sleep);
+
+       if (status) {
+               status = chip->request(chip, gpio);
+               if (status < 0) {
+                       pr_debug("GPIO-%d: chip request fail, %d\n",
+                               chip->base + gpio, status);
+                       /* and it's not available to anyone else ...
+                        * gpio_request() is the fully clean solution.
+                        */
+                       goto lose;
+               }
+       }
+       status = chip->pull_updown(chip, gpio,value);
+       if (status == 0)
+               clear_bit(FLAG_IS_OUT, &desc->flags);
+       
+lose:
+       return status;
+fail:
+       spin_unlock_irqrestore(&gpio_lock, flags);
+       if (status)
+               pr_debug("%s: gpio-%d status %d\n",
+                       __func__, gpio, status);
+       return status;
+}
+EXPORT_SYMBOL_GPL(gpio_pull_updown);
+
 /**
  * gpio_set_debounce - sets @debounce time for a @gpio
  * @gpio: the gpio to set debounce time
@@ -1555,6 +1618,8 @@ int __gpio_get_value(unsigned gpio)
        struct gpio_chip        *chip;
        int value;
 
+       if (!gpio_is_valid(gpio))
+               return -1;
        chip = gpio_to_chip(gpio);
        WARN_ON(chip->can_sleep);
        value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
@@ -1576,6 +1641,10 @@ void __gpio_set_value(unsigned gpio, int value)
 {
        struct gpio_chip        *chip;
 
+       if(value !=0 && value !=1)
+               return;
+       if (!gpio_is_valid(gpio))
+                return;
        chip = gpio_to_chip(gpio);
        WARN_ON(chip->can_sleep);
        trace_gpio_value(gpio, 0, value);
@@ -1614,9 +1683,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);
 int __gpio_to_irq(unsigned gpio)
 {
        struct gpio_chip        *chip;
-
+       
+       if (!gpio_is_valid(gpio))
+                return -1;
+       
        chip = gpio_to_chip(gpio);
-       return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -ENXIO;
+       
+       return chip->to_irq ? chip->to_irq(chip, gpio - chip->base) : -1;
 }
 EXPORT_SYMBOL_GPL(__gpio_to_irq);
 
index be7a00c60e551500ec4f1309db82894c5ee51287..45b2c77ca6c8d9a9de4eeaa788a5c8752e3b4323 100755 (executable)
@@ -1426,8 +1426,9 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
        }
 }
 EXPORT_SYMBOL(i2c_transfer);
+
 #if defined (CONFIG_I2C_RK2818) || defined(CONFIG_I2C_RK29)
-int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
+int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
 {
        int ret;
        struct i2c_adapter *adap=client->adapter;
@@ -1445,7 +1446,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
 }
 EXPORT_SYMBOL(i2c_master_send);
 
-int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
+int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
 {
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
@@ -1464,7 +1465,7 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
 }
 EXPORT_SYMBOL(i2c_master_recv);
 
-int i2c_master_normal_send(struct i2c_client *client,const char *buf ,int count, int scl_rate)
+int i2c_master_normal_send(const struct i2c_client *client, const char *buf, int count, int scl_rate)
 {
        int ret;
        struct i2c_adapter *adap=client->adapter;
@@ -1482,7 +1483,7 @@ int i2c_master_normal_send(struct i2c_client *client,const char *buf ,int count,
 }
 EXPORT_SYMBOL(i2c_master_normal_send);
 
-int i2c_master_normal_recv(struct i2c_client *client, char *buf ,int count, int scl_rate)
+int i2c_master_normal_recv(const struct i2c_client *client, char *buf, int count, int scl_rate)
 {
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
@@ -1501,7 +1502,7 @@ int i2c_master_normal_recv(struct i2c_client *client, char *buf ,int count, int
 }
 EXPORT_SYMBOL(i2c_master_normal_recv);
 
-int i2c_master_reg8_send(struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
+int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
 {
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
@@ -1526,7 +1527,7 @@ int i2c_master_reg8_send(struct i2c_client *client, const char reg, const char *
 }
 EXPORT_SYMBOL(i2c_master_reg8_send);
 
-int i2c_master_reg8_recv(struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
+int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
 {
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msgs[2];
@@ -1554,13 +1555,13 @@ int i2c_master_reg8_recv(struct i2c_client *client, const char reg, char *buf, i
 
 EXPORT_SYMBOL(i2c_master_reg8_recv);
 
-int i2c_master_reg8_direct_send(struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
+int i2c_master_reg8_direct_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
 {
        return i2c_master_reg8_send(client, reg, buf, count, scl_rate);
 }
 EXPORT_SYMBOL(i2c_master_reg8_direct_send);
 
-int i2c_master_reg8_direct_recv(struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
+int i2c_master_reg8_direct_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
 {
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
@@ -1581,7 +1582,7 @@ int i2c_master_reg8_direct_recv(struct i2c_client *client, const char reg, char
 }
 EXPORT_SYMBOL(i2c_master_reg8_direct_recv);
 
-int i2c_master_reg16_send(struct i2c_client *client, const short regs, const short *buf, int count, int scl_rate)
+int i2c_master_reg16_send(const struct i2c_client *client, const short regs, const short *buf, int count, int scl_rate)
 {
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
@@ -1605,7 +1606,7 @@ int i2c_master_reg16_send(struct i2c_client *client, const short regs, const sho
 }
 EXPORT_SYMBOL(i2c_master_reg16_send);
 
-int i2c_master_reg16_recv(struct i2c_client *client, const short regs, short *buf, int count, int scl_rate)
+int i2c_master_reg16_recv(const struct i2c_client *client, const short regs, short *buf, int count, int scl_rate)
 {
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msgs[2];
index 5d4593d3101d099fd0e5957e7f0561c37cfbccd7..7b058fb4b7f402dae2d730aff28fcc68f2940c7d 100755 (executable)
@@ -22,6 +22,11 @@ obj-$(CONFIG_INPUT_JOYSTICK) += joystick/
 obj-$(CONFIG_INPUT_TABLET)     += tablet/
 obj-$(CONFIG_INPUT_TOUCHSCREEN)        += touchscreen/
 obj-$(CONFIG_INPUT_MISC)       += misc/
+obj-$(CONFIG_G_SENSOR_DEVICE)  += gsensor/
+obj-$(CONFIG_GYRO_SENSOR_DEVICE)       += gyroscope/
+obj-$(CONFIG_INPUT_JOGBALL)    += jogball/
+obj-$(CONFIG_LIGHT_SENSOR_DEVICE) += lightsensor/
+obj-$(CONFIG_MAG_SENSORS)      += magnetometer/
 
 obj-$(CONFIG_INPUT_APMPOWER)   += apm-power.o
 obj-$(CONFIG_INPUT_KEYRESET)   += keyreset.o
index b4dee9d5a0555ff76dabb1b85b7e23c92db63222..05ab0606bcd62d406b0b28e4b78270cfe1841cfb 100644 (file)
@@ -12,6 +12,25 @@ menuconfig INPUT_KEYBOARD
 
 if INPUT_KEYBOARD
 
+config KEYS_RK29
+       tristate "rk29 keyboard"
+       depends on ARCH_RK29
+       default y
+       help
+         rk29 keyboard drivers(gpio and adc)
+
+config KEYS_RK29_NEWTON
+       tristate "rk29 newton keyboard"
+       depends on ARCH_RK29
+       help
+               rk29 newton keyboard drivers(gpio and adc)
+
+config SYNAPTICS_SO340010
+       tristate "Synaptics So340010 TouchPad KEY"
+       depends on I2C
+       help
+         Synaptics So340010 Touch Key (I2C) driver
+
 config KEYBOARD_ADP5520
        tristate "Keypad Support for ADP5520 PMIC"
        depends on PMIC_ADP5520
@@ -203,6 +222,21 @@ config KEYBOARD_GPIO_POLLED
          To compile this driver as a module, choose M here: the
          module will be called gpio_keys_polled.
 
+config KEYBOARD_WM831X_GPIO
+       tristate "WM831X_GPIO Buttons"
+       depends on GENERIC_GPIO
+       help
+         This driver implements support for buttons connected
+         to GPIO pins of various CPUs (and some other chips).
+
+         Say Y here if your device has buttons connected
+         directly to such GPIO pins.  Your board-specific
+         setup logic must also provide a platform device,
+         with configuration data saying which GPIOs are used.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm831x_gpio_keys.
+
 config KEYBOARD_TCA6416
        tristate "TCA6416/TCA6408A Keypad Support"
        depends on I2C
index ddde0fd476f744c2aa2cd250362f809c4469310b..b90ddded626d84922bfae7b8fb3896621e5339c8 100644 (file)
@@ -4,6 +4,8 @@
 
 # Each configuration option enables a list of files.
 
+obj-$(CONFIG_KEYS_RK29)                        += rk29_keys.o
+obj-$(CONFIG_KEYS_RK29_NEWTON)         += rk29_newton_keys.o
 obj-$(CONFIG_KEYBOARD_ADP5520)         += adp5520-keys.o
 obj-$(CONFIG_KEYBOARD_ADP5588)         += adp5588-keys.o
 obj-$(CONFIG_KEYBOARD_ADP5589)         += adp5589-keys.o
@@ -15,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_DAVINCI)                += davinci_keyscan.o
 obj-$(CONFIG_KEYBOARD_EP93XX)          += ep93xx_keypad.o
 obj-$(CONFIG_KEYBOARD_GPIO)            += gpio_keys.o
 obj-$(CONFIG_KEYBOARD_GPIO_POLLED)     += gpio_keys_polled.o
+obj-$(CONFIG_KEYBOARD_WM831X_GPIO)     += wm831x_gpio_keys.o
 obj-$(CONFIG_KEYBOARD_TCA6416)         += tca6416-keypad.o
 obj-$(CONFIG_KEYBOARD_HIL)             += hil_kbd.o
 obj-$(CONFIG_KEYBOARD_HIL_OLD)         += hilkbd.o
@@ -51,3 +54,4 @@ obj-$(CONFIG_KEYBOARD_TNETV107X)      += tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)         += twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)           += xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)         += w90p910_keypad.o
+obj-$(CONFIG_SYNAPTICS_SO340010)        += synaptics_so340010.o
index 7ce1e96726331216d55b95eb9d37ee260b7291c0..46651a24969522877b48b62236f455eb1ca38163 100755 (executable)
@@ -271,16 +271,6 @@ config INPUT_CM109
          To compile this driver as a module, choose M here: the module will be
          called cm109.
 
-config INPUT_TPS65910_PWRBUTTON
-       tristate "TPS65910 Power button Driver"
-       depends on TPS65910_CORE
-       help
-         Say Y here if you want to enable power key reporting via the
-         TPS65910 family of chips.
-
-         To compile this driver as a module, choose M here. The module will
-         be called tps65910_pwrbutton.
-
 config INPUT_TWL4030_PWRBUTTON
        tristate "TWL4030 Power button Driver"
        depends on TWL4030_CORE
index 41136b497844145215d72c05056e363384a15ffd..d17fcab89d6196bf2e23d40bcfc9ab7225d3f160 100755 (executable)
@@ -42,7 +42,6 @@ obj-$(CONFIG_INPUT_RB532_BUTTON)      += rb532_button.o
 obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER)        += rotary_encoder.o
 obj-$(CONFIG_INPUT_SGI_BTNS)           += sgi_btns.o
 obj-$(CONFIG_INPUT_SPARCSPKR)          += sparcspkr.o
-obj-$(CONFIG_INPUT_TPS65910_PWRBUTTON) += tps65910-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)  += twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)      += twl4030-vibra.o
 obj-$(CONFIG_INPUT_UINPUT)             += uinput.o
@@ -50,3 +49,4 @@ obj-$(CONFIG_INPUT_WISTRON_BTNS)      += wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)          += wm831x-on.o
 obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)        += xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)            += yealink.o
+
diff --git a/drivers/input/misc/tps65910-pwrbutton.c b/drivers/input/misc/tps65910-pwrbutton.c
deleted file mode 100644 (file)
index 587de97..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/**
- * tps65910-pwrbutton.c - TPS65910 Power Button Input Driver
- *
- * Copyright (C) 2010 Mistral Solutions Pvt Ltd <www.mistralsolutions.com>
- *
- * Based on twl4030-pwrbutton.c
- *
- * Written by Srinath.R <srinath@mistralsolutions.com>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file "COPYING" in the main directory of this
- * archive for more details.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/tps65910.h>
-
-#define TPS65910_PWR_PWRON_IRQ (1 << 2)
-
-
-static irqreturn_t powerbutton_irq(int irq, void *_pwr)
-{
-       struct input_dev *pwr = _pwr;
-       int err;
-       u8 value;
-
-#ifdef CONFIG_LOCKDEP
-       /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
-        * we don't want and can't tolerate since this is a threaded
-        * IRQ and can sleep due to the i2c reads it has to issue.
-        * Although it might be friendlier not to borrow this thread
-        * context...
-        */
-       local_irq_enable();
-#endif
-       err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &value,
-                               TPS65910_REG_INT_STS);
-       if (!err  && (value & TPS65910_PWR_PWRON_IRQ))  {
-
-               if (value & TPS65910_PWR_PWRON_IRQ) {
-
-                       input_report_key(pwr, KEY_POWER,
-                                       TPS65910_PWR_PWRON_IRQ);
-                       input_sync(pwr);
-                       return IRQ_HANDLED;
-               }
-       } else {
-               dev_err(pwr->dev.parent, "tps65910: i2c error %d while reading"
-                       " TPS65910_REG_INT_STS register\n", err);
-       }
-       return IRQ_HANDLED;
-}
-
-static int __devinit tps65910_pwrbutton_probe(struct platform_device *pdev)
-{
-       struct input_dev *pwr;
-       int irq = platform_get_irq(pdev, 0);
-       int err;
-
-       pwr = input_allocate_device();
-       if (!pwr) {
-               dev_dbg(&pdev->dev, "Can't allocate power button\n");
-               return -ENOMEM;
-       }
-
-       pwr->evbit[0] = BIT_MASK(EV_KEY);
-       pwr->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
-       pwr->name = "tps65910_pwrbutton";
-       pwr->phys = "tps65910_pwrbutton/input0";
-       pwr->dev.parent = &pdev->dev;
-
-       err = request_irq(irq, powerbutton_irq,
-                       (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
-                       IRQF_SHARED), "tps65910_pwrbutton", pwr);
-       if (err < 0) {
-               dev_dbg(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
-               goto free_input_dev;
-       }
-
-       err = input_register_device(pwr);
-       if (err) {
-               dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
-               goto free_irq;
-       }
-
-       platform_set_drvdata(pdev, pwr);
-
-       return 0;
-
-free_irq:
-       free_irq(irq, NULL);
-free_input_dev:
-       input_free_device(pwr);
-       return err;
-}
-
-static int __devexit tps65910_pwrbutton_remove(struct platform_device *pdev)
-{
-       struct input_dev *pwr = platform_get_drvdata(pdev);
-       int irq = platform_get_irq(pdev, 0);
-
-       free_irq(irq, pwr);
-       input_unregister_device(pwr);
-
-       return 0;
-}
-
-struct platform_driver tps65910_pwrbutton_driver = {
-       .probe          = tps65910_pwrbutton_probe,
-       .remove         = __devexit_p(tps65910_pwrbutton_remove),
-       .driver         = {
-               .name   = "tps65910_pwrbutton",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init tps65910_pwrbutton_init(void)
-{
-       return platform_driver_register(&tps65910_pwrbutton_driver);
-}
-module_init(tps65910_pwrbutton_init);
-
-static void __exit tps65910_pwrbutton_exit(void)
-{
-       platform_driver_unregister(&tps65910_pwrbutton_driver);
-}
-module_exit(tps65910_pwrbutton_exit);
-
-MODULE_ALIAS("platform:tps65910_pwrbutton");
-MODULE_DESCRIPTION("TPS65910 Power Button");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Srinath R <srinath@mistralsolutions.com>");
-
index 410410396700a15b8ae3114f8c890b28e270d941..846f9603f0cace6e9a180a1755854a4d5e7e4a22 100755 (executable)
@@ -11,6 +11,58 @@ menuconfig INPUT_TOUCHSCREEN
 
 if INPUT_TOUCHSCREEN
 
+config TOUCHSCREEN_XPT2046_SPI
+       tristate "XPT2046 based touchscreens:SPI Interface"
+       depends on SPIM_RK29
+
+       config TOUCHSCREEN_XPT2046_NORMAL_SPI
+       tristate "normal mode"
+       depends on TOUCHSCREEN_XPT2046_SPI
+
+               config TOUCHSCREEN_480X800
+               tristate "480X800 resolution"
+               depends on TOUCHSCREEN_XPT2046_NORMAL_SPI
+
+               config TOUCHSCREEN_800X480
+               tristate "800X480 resolution"
+               depends on TOUCHSCREEN_XPT2046_NORMAL_SPI
+
+               config TOUCHSCREEN_320X480
+               tristate "320X480 resolution"
+               depends on TOUCHSCREEN_XPT2046_NORMAL_SPI
+
+       config TOUCHSCREEN_XPT2046_TSLIB_SPI
+       tristate "tslib mode"
+       depends on TOUCHSCREEN_XPT2046_SPI
+
+               config TOUCHSCREEN_480X800
+               tristate "480X800 resolution"
+               depends on TOUCHSCREEN_XPT2046_TSLIB_SPI
+
+               config TOUCHSCREEN_800X480
+               tristate "800X480 resolution"
+               depends on TOUCHSCREEN_XPT2046_TSLIB_SPI
+
+               config TOUCHSCREEN_320X480
+               tristate "320X480 resolution"
+               depends on TOUCHSCREEN_XPT2046_TSLIB_SPI
+
+       config TOUCHSCREEN_XPT2046_CBN_SPI
+       tristate "calibration mode"
+       depends on TOUCHSCREEN_XPT2046_SPI
+
+               config TOUCHSCREEN_480X800
+               tristate "480X800 resolution"
+               depends on TOUCHSCREEN_XPT2046_CBN_SPI
+
+               config TOUCHSCREEN_800X480
+               tristate "800X480 resolution"
+               depends on TOUCHSCREEN_XPT2046_CBN_SPI
+
+               config TOUCHSCREEN_320X480
+               tristate "320X480 resolution"
+               depends on TOUCHSCREEN_XPT2046_CBN_SPI
+
 config TOUCHSCREEN_88PM860X
        tristate "Marvell 88PM860x touchscreen"
        depends on MFD_88PM860X
@@ -55,6 +107,28 @@ config TOUCHSCREEN_AD7877
          To compile this driver as a module, choose M here: the
          module will be called ad7877.
 
+config TOUCHSCREEN_ILI2102_IIC
+       tristate "ili2102 based touchscreens: IIC Interface"
+       help
+         Say Y here if you have a touchscreen interface using the
+         hx8520 controller, and your board-specific initialization
+         code includes that in its table of IIC devices.
+
+         If unsure, say N (but it's safe to say "Y").
+
+config RK28_I2C_TS_NTP070
+       tristate "NTP070 based touchscreens: NTP070 Interface"
+       depends on I2C_RK2818
+
+config TOUCHSCREEN_IT7250
+       tristate "IT7250 based touchscreens: IT7250 Interface"
+       help
+         Say Y here if you have a touchscreen interface using the
+         xpt2046 controller, and your board-specific initialization
+         code includes that in its table of SPI devices.
+
+         If unsure, say N (but it's safe to say "Y").
+
 config TOUCHSCREEN_AD7879
        tristate "Analog Devices AD7879-1/AD7889-1 touchscreen interface"
        help
@@ -732,4 +806,199 @@ config TOUCHSCREEN_TPS6507X
          To compile this driver as a module, choose M here: the
          module will be called tps6507x_ts.
 
+config HANNSTAR_P1003
+       tristate "Hannstar P1003 touchscreen"
+       depends on I2C2_RK29
+       help
+         RK29 hannstar touch
+
+       config HANNSTAR_MAX_X
+               int "hannstar touch x max"
+               depends on HANNSTAR_P1003
+               default 1087
+               help
+                 RK29 hannstar touch max X size
+
+       config HANNSTAR_MAX_Y
+                int "hannstar touch Y max"
+                depends on HANNSTAR_P1003
+               default 800
+                help
+                  RK29 hannstar touch max Y size
+
+       config HANNSTAR_DEBUG
+               bool "hannstar debug"
+               depends on HANNSTAR_P1003
+               default n
+               help
+                 RK29 hannstar touch debug
+
+config ATMEL_MXT224
+        tristate "Atmel mXT224 touchscreen"
+        depends on I2C2_RK29
+        help
+          RK29 Atmel_mXT224 touch
+
+        config MXT224_MAX_X
+                int "atmel_mxt224 touch X max"
+                depends on ATMEL_MXT224
+                default 4095
+                help
+                  RK29 atmel_mxt224 touch max X size
+
+        config MXT224_MAX_Y
+                int "atmel_mxt224 touch Y max"
+                depends on ATMEL_MXT224
+                default 4095
+                help
+                  RK29 atmel_mxt224 touch max Y size
+
+config SINTEK_3FA16
+       tristate "Sintek 3FA16 touchscreen"
+        depends on I2C2_RK29
+        help
+          RK29 Sintek touch
+
+        config HANNSTAR_MAX_X
+                int "Sintek touch x max"
+                depends on SINTEK_3FA16
+                default 1024
+                help
+                  RK29 hannstar touch max X size
+
+        config HANNSTAR_MAX_Y
+                int "Sintek touch Y max"
+                depends on SINTEK_3FA16
+                default 600
+                help
+                  RK29 hannstar touch max Y size
+
+        config HANNSTAR_DEBUG
+                bool "Sintek debug"
+                depends on SINTEK_3FA16
+                default n
+                help
+                  RK29 hannstar touch debug
+
+config EETI_EGALAX
+        tristate "EETI_EGALAX touchscreen panel support"
+        depends on I2C
+        help
+          Say Y here to enable support for I2C connected EETI touch panels.
+
+          To compile this driver as a module, choose M here: the
+          module will be called eeti_egalax_ts.
+
+        config EETI_EGALAX_MAX_X
+                int "EETI_EGALAX_MAX_X"
+                depends on EETI_EGALAX
+                default 2047
+                help
+                  RK29 EETI_EGALAX touch max X size
+
+        config EETI_EGALAX_MAX_Y
+                int "EETI_EGALAX_MAX_Y"
+                depends on EETI_EGALAX
+                default 2047
+                help
+                  RK29 EETI_EGALAX touch max Y size
+
+        config EETI_EGALAX_DEBUG
+                bool "EETI_EGALAX debug"
+                depends on EETI_EGALAX
+                default n
+                help
+                  RK29 EETI_EGALAX touch debug
+
+config TOUCHSCREEN_IT7260
+       tristate "IT7260 based touchscreens: IT7260 Interface"
+       depends on I2C2_RK29
+       help
+         Say Y here if you have a touchscreen interface using the
+         it7260 controller, and your board-specific initialization
+         code includes that in its table of I2C devices.
+
+         If unsure, say N (but it's safe to say "Y").
+
+config TOUCHSCREEN_IT7260_I2C
+       tristate "IT7260 based touchscreens: IT7260 I2C Interface"
+       depends on I2C_RK29
+       help
+         Say Y here if you have a touchscreen interface using the
+         IT7260 controller, and your board-specific initialization
+         code includes that in its table of I2C devices.
+
+         If unsure, say N (but it's safe to say "Y").
+
+config TOUCHSCREEN_NAS
+        tristate "NAS based touchscreens: NAS Interface"
+        depends on I2C2_RK29
+        help
+          Say Y here if you have a touchscreen interface using the
+          nas controller, and your board-specific initialization
+          code includes that in its table of I2C devices.
+
+          If unsure, say N (but it's safe to say "Y").
+
+config LAIBAO_TS
+       tristate "LAIBAO touchscreen"
+       depends on I2C2_RK29
+       help
+         RK29 LAIBAO touchscreen
+
+config TOUCHSCREEN_GT801_IIC
+       tristate "GT801_IIC based touchscreens"
+       depends on I2C2_RK29
+
+config TOUCHSCREEN_GT818_IIC
+       tristate "GT818_IIC based touchscreens"
+       depends on I2C2_RK29
+
+config D70_L3188A
+       tristate "D70-L3188A based touchscreens"
+       depends on I2C2_RK29
+
+config TOUCHSCREEN_GT819
+       tristate "GT819 based touchscreens"
+       depends on I2C2_RK29
+
+config TOUCHSCREEN_FT5406
+       tristate "FT5406 based touchscreens: FT5406 Interface"
+       depends on I2C2_RK29
+       help
+         say Y here if you have a touchscreen interface using the FT5406
+         controller,and your board-specific initialization code includes that
+         in its table of I2C devices.
+
+         If unsure, say N(but it's safe to say "Y").
+
+config ATMEL_MXT1386
+        tristate "ATMEL_MXT1386 touchscreen panel support"
+        depends on I2C
+        help
+          Say Y here to enable support for I2C connected ATMEL_MXT1386 touch panels.
+
+          To compile this driver as a module, choose M here: the
+          module will be called atmel_mxt1386_ts.
+
+        config ATMEL_MXT1386_MAX_X
+                int "ATMEL_MXT1386_MAX_X"
+                depends on ATMEL_MXT1386
+                default 4095
+                help
+                  RK29 ATMEL_MXT1386 touch max X size
+
+        config ATMEL_MXT1386_MAX_Y
+                int "ATMEL_MXT1386_MAX_Y"
+                depends on ATMEL_MXT1386
+                default 4095
+                help
+                  RK29 ATMEL_MXT1386 touch max Y size
+
+        config ATMEL_MXT1386_DEBUG
+                bool "ATMEL_MXT1386 debug"
+                depends on ATMEL_MXT1386
+                default n
+                help
+                  RK29 ATMEL_MXT1386 touch debug
 endif
index f0fecd6f6a33e818c4f4713d2b62e1ecd762e4a9..70ffad500741b3184b08f22c5635fae7874a365a 100755 (executable)
@@ -74,9 +74,14 @@ obj-$(CONFIG_VIDEO_M5MOLS)   += m5mols/
 obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
 obj-$(CONFIG_SOC_CAMERA_MT9M111)       += mt9m111.o
+obj-$(CONFIG_SOC_CAMERA_MT9M112)       += mt9m112.o
 obj-$(CONFIG_SOC_CAMERA_MT9T031)       += mt9t031.o
+obj-$(CONFIG_SOC_CAMERA_MT9T111)       += mt9t111.o
 obj-$(CONFIG_SOC_CAMERA_MT9T112)       += mt9t112.o
 obj-$(CONFIG_SOC_CAMERA_MT9V022)       += mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_MT9P111)       += mt9p111.o
+obj-$(CONFIG_SOC_CAMERA_MT9D112)       += mt9d112.o
+obj-$(CONFIG_SOC_CAMERA_MT9D113)       += mt9d113.o
 obj-$(CONFIG_SOC_CAMERA_OV2640)                += ov2640.o
 obj-$(CONFIG_SOC_CAMERA_OV6650)                += ov6650.o
 obj-$(CONFIG_SOC_CAMERA_OV772X)                += ov772x.o
@@ -84,7 +89,25 @@ obj-$(CONFIG_SOC_CAMERA_OV9640)              += ov9640.o
 obj-$(CONFIG_SOC_CAMERA_OV9740)                += ov9740.o
 obj-$(CONFIG_SOC_CAMERA_RJ54N1)                += rj54n1cb0c.o
 obj-$(CONFIG_SOC_CAMERA_TW9910)                += tw9910.o
-
+obj-$(CONFIG_SOC_CAMERA_OV7675)                += ov7675.o
+obj-$(CONFIG_SOC_CAMERA_OV2655)                += ov2655.o
+obj-$(CONFIG_SOC_CAMERA_OV2659)                += ov2659.o
+obj-$(CONFIG_SOC_CAMERA_OV9650)                += ov9650.o
+obj-$(CONFIG_SOC_CAMERA_OV2640)                += ov2640.o
+obj-$(CONFIG_SOC_CAMERA_OV3640)                += ov3640.o
+obj-$(CONFIG_SOC_CAMERA_OV5640)                += ov5640.o
+obj-$(CONFIG_SOC_CAMERA_OV5642)                += ov5642.o
+obj-$(CONFIG_SOC_CAMERA_S5K6AA)                += s5k6aa.o
+obj-$(CONFIG_SOC_CAMERA_GT2005)                += gt2005.o
+obj-$(CONFIG_SOC_CAMERA_GC0307)                += gc0307.o
+obj-$(CONFIG_SOC_CAMERA_GC0308)                += gc0308.o
+obj-$(CONFIG_SOC_CAMERA_GC0309)                += gc0309.o
+obj-$(CONFIG_SOC_CAMERA_GC2015)                += gc2015.o
+obj-$(CONFIG_SOC_CAMERA_SIV120B)       += siv120b.o
+obj-$(CONFIG_SOC_CAMERA_SID130B)       += sid130B.o
+obj-$(CONFIG_SOC_CAMERA_HI253) += hi253.o
+obj-$(CONFIG_SOC_CAMERA_HI704) += hi704.o
+obj-$(CONFIG_SOC_CAMERA_NT99250)       += nt99250.o
 # And now the v4l2 drivers:
 
 obj-$(CONFIG_VIDEO_BT848) += bt8xx/
@@ -163,6 +186,9 @@ obj-$(CONFIG_VIDEO_MX1)                     += mx1_camera.o
 obj-$(CONFIG_VIDEO_MX2)                        += mx2_camera.o
 obj-$(CONFIG_VIDEO_MX3)                        += mx3_camera.o
 obj-$(CONFIG_VIDEO_PXA27x)             += pxa_camera.o
+obj-$(CONFIG_VIDEO_RK29_WORK_ONEFRAME) += rk29_camera_oneframe.o
+obj-$(CONFIG_VIDEO_RK29_WORK_PINGPONG) += rk29_camera_pingpong.o
+obj-$(CONFIG_VIDEO_RK29XX_VOUT)                += rk29xx/
 obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2)     += sh_mobile_csi2.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)      += sh_mobile_ceu_camera.o
 obj-$(CONFIG_VIDEO_OMAP1)              += omap1_camera.o
index 0cea0cf36679966c4c4883481ccb71333fc4bdf7..9b2ac56310ef989107adc782503b8bc1d7353d1f 100644 (file)
@@ -1,4 +1,5 @@
 /*
+<<<<<<< HEAD
  * ov2640 Camera Driver
  *
  * Copyright (C) 2010 Alberto Panizzo <maramaopercheseimorto@gmail.com>
@@ -7,12 +8,18 @@
  *
  * Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright (C) 2006, OmniVision
+=======
+o* Driver for MT9M001 CMOS Image Sensor from Micron
+ *
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
+>>>>>>> parent of 15f7fab... temp revert rk change
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
 
+<<<<<<< HEAD
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
@@ -1203,3 +1210,2963 @@ module_exit(ov2640_module_exit);
 MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor");
 MODULE_AUTHOR("Alberto Panizzo");
 MODULE_LICENSE("GPL v2");
+=======
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/log2.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/circ_buf.h>
+#include <linux/miscdevice.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+#include <mach/rk29_camera.h>
+
+static int debug;
+module_param(debug, int, S_IRUGO|S_IWUSR);
+
+#define dprintk(level, fmt, arg...) do {                       \
+       if (debug >= level)                                     \
+       printk(KERN_WARNING fmt , ## arg); } while (0)
+
+#define SENSOR_TR(format, ...) printk(KERN_ERR format, ## __VA_ARGS__)
+#define SENSOR_DG(format, ...) dprintk(1, format, ## __VA_ARGS__)
+
+
+#define _CONS(a,b) a##b
+#define CONS(a,b) _CONS(a,b)
+
+#define __STR(x) #x
+#define _STR(x) __STR(x)
+#define STR(x) _STR(x)
+
+#define MIN(x,y)   ((x<y) ? x: y)
+#define MAX(x,y)    ((x>y) ? x: y)
+
+/* Sensor Driver Configuration */
+#define SENSOR_NAME RK29_CAM_SENSOR_OV2640
+#define SENSOR_V4L2_IDENT V4L2_IDENT_OV2640
+#define SENSOR_ID 0x2642
+#define SENSOR_ID1 0x2641
+#define SENSOR_MIN_WIDTH    640
+#define SENSOR_MIN_HEIGHT   480
+#define SENSOR_MAX_WIDTH    1600
+#define SENSOR_MAX_HEIGHT   1200
+#define SENSOR_INIT_WIDTH      640                     /* Sensor pixel size for sensor_init_data array */
+#define SENSOR_INIT_HEIGHT  480
+#define SENSOR_INIT_WINSEQADR sensor_vga
+#define SENSOR_INIT_PIXFMT V4L2_MBUS_FMT_YUYV8_2X8
+
+#define CONFIG_SENSOR_WhiteBalance     0
+#define CONFIG_SENSOR_Brightness       1
+#define CONFIG_SENSOR_Contrast      0
+#define CONFIG_SENSOR_Saturation    1
+#define CONFIG_SENSOR_Effect        1
+#define CONFIG_SENSOR_Scene         0
+#define CONFIG_SENSOR_DigitalZoom   0
+#define CONFIG_SENSOR_Focus         0
+#define CONFIG_SENSOR_Exposure      0
+#define CONFIG_SENSOR_Flash         0
+#define CONFIG_SENSOR_Mirror        0
+#define CONFIG_SENSOR_Flip          0
+
+#define CONFIG_SENSOR_I2C_SPEED     250000       /* Hz */
+/* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
+#define CONFIG_SENSOR_I2C_NOSCHED   0
+#define CONFIG_SENSOR_I2C_RDWRCHK   0
+
+#define SENSOR_BUS_PARAM  (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\
+                          SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
+                          SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8  |SOCAM_MCLK_24MHZ)
+
+#define COLOR_TEMPERATURE_CLOUDY_DN  6500
+#define COLOR_TEMPERATURE_CLOUDY_UP    8000
+#define COLOR_TEMPERATURE_CLEARDAY_DN  5000
+#define COLOR_TEMPERATURE_CLEARDAY_UP    6500
+#define COLOR_TEMPERATURE_OFFICE_DN     3500
+#define COLOR_TEMPERATURE_OFFICE_UP     5000
+#define COLOR_TEMPERATURE_HOME_DN       2500
+#define COLOR_TEMPERATURE_HOME_UP       3500
+
+#define SENSOR_NAME_STRING(a) STR(CONS(SENSOR_NAME, a))
+#define SENSOR_NAME_VARFUN(a) CONS(SENSOR_NAME, a)
+
+struct reginfo
+{
+    u8 reg;
+    u8 val;
+};
+
+/* init 800*600 SVGA */
+static struct reginfo sensor_init_data[] =
+{
+#if 1
+    {0xff,0x01},
+    {0x12,0x80},
+    {0xff,0x00},
+    {0x2c,0xff},
+    {0x2e,0xdf},
+    {0xff,0x01},
+
+    {0x03,0x4f},
+    {0x0f,0x4b},
+
+
+    {0x3c,0x32},
+    {0x11,0x00},
+    {0x09,0x02},
+    {0x04,0xF8},//b7,b6 directs
+    {0x13,0xe5},
+    {0x14,0x48},
+    {0x2c,0x0c},
+    {0x33,0x78},
+    {0x3a,0x33},
+    {0x3b,0xfB},
+    {0x3e,0x00},
+    {0x43,0x11},
+    {0x16,0x10},
+    {0x39,0x02},
+    {0x35,0x88},
+    {0x22,0x09},
+    {0x37,0x40},
+    {0x23,0x00},
+    {0x34,0xa0},
+    {0x36,0x1a},
+    {0x06,0x02},
+    {0x07,0xc0},
+    {0x0d,0xb7},
+    {0x0e,0x01},
+    {0x4c,0x00},
+    {0x4a,0x81},
+    {0x21,0x99},
+    
+    //{0x24,0x58},
+    //{0x25,0x50},
+    //{0x26,0x92},
+    
+    {0x24, 0x70},
+    {0x25, 0x60},
+    {0x26, 0xa4},    
+    
+    {0x5c,0x00},
+    {0x63,0x00},
+    {0x46,0x3f},
+    {0x0c,0x3c},
+    {0x61,0x70},
+    {0x62,0x80},
+    {0x7c,0x05},
+    {0x20,0x80},
+    {0x28,0x30},
+    {0x6c,0x00},
+    {0x6d,0x80},
+    {0x6e,0x00},
+    {0x70,0x02},
+    {0x71,0x94},
+    {0x73,0xc1},
+    {0x3d,0x34},
+    {0x5a,0x57},
+    {0x4f,0xbb},
+    {0x50,0x9c},
+    {0xff,0x00},
+    {0xe5,0x7f},
+    {0xf9,0xc0},
+    {0x41,0x24},
+    {0xe0,0x14},
+    {0x76,0xff},
+    {0x33,0xa0},
+    {0x42,0x20},
+    {0x43,0x18},
+    {0x4c,0x00},
+    {0x87,0xd0},
+    {0x88,0x3f},
+    {0xd7,0x03},
+    {0xd9,0x10},
+    {0xd3,0x82},
+    {0xc8,0x08},
+    {0xc9,0x80},
+    {0x7c,0x00},
+    {0x7d,0x00},//0x00//0x07
+    {0x7c,0x03},
+    {0x7d,0x48},//0x48//0x40
+    {0x7d,0x48},//0x48//0x40
+    {0x7c,0x08},
+    {0x7d,0x20},
+    {0x7d,0x10},//0x10
+    {0x7d,0x0e},//0x0e
+
+    {0x92,0x00},
+    {0x93,0x06},
+    {0x93,0xc8},//e3
+    {0x93,0x05},
+    {0x93,0x05},
+    {0x93,0x00},
+    {0x93,0x04},
+    {0x93,0x00},
+    {0x93,0x00},
+    {0x93,0x00},
+    {0x93,0x00},
+    {0x93,0x00},
+    {0x93,0x00},
+    {0x93,0x00},
+    {0x96,0x00},
+    {0x97,0x08},
+    {0x97,0x19},
+    {0x97,0x02},
+    {0x97,0x0c},
+    {0x97,0x24},
+    {0x97,0x30},
+    {0x97,0x28},
+    {0x97,0x26},
+    {0x97,0x02},
+    {0x97,0x98},
+    {0x97,0x80},
+    {0x97,0x00},
+    {0x97,0x00},
+    {0xc3,0xef},//ed
+    {0xa4,0x00},
+    {0xa8,0x00},
+
+    {0xbf, 0x00},
+    {0xba, 0xdc},
+    {0xbb, 0x08},
+    {0xb6, 0x20},
+    {0xb8, 0x30},
+    {0xb7, 0x20},
+    {0xb9, 0x30},
+    {0xb3, 0xb4},
+    {0xb4, 0xca},
+    {0xb5, 0x34},
+    {0xb0, 0x46},
+    {0xb1, 0x46},
+    {0xb2, 0x06},
+    {0xc7, 0x00},
+    {0xc6, 0x51},
+    {0xc5, 0x11},
+    {0xc4, 0x9c},
+////
+    {0xc0,0xc8},
+    {0xc1,0x96},
+    {0x86,0x3d},
+    {0x50,0x92},
+    {0x51,0x90},
+    {0x52,0x2c},
+    {0x53,0x00},
+    {0x54,0x00},
+    {0x55,0x88},
+    {0x57,0x00},
+    {0x5a,0x50},
+    {0x5b,0x3c},
+    {0x5c,0x00},
+    {0xc3,0xed},
+    {0x7f,0x00},
+    {0xda,0x01},
+    {0xe5,0x1f},
+    {0xe1,0x67},
+    {0xe0,0x00},
+    {0xdd,0xff},
+    {0x05,0x00},
+
+#endif
+#if 1
+    {0xff, 0x01},
+    {0x5d, 0x00},
+    {0x5e, 0x3c},
+    {0x5f, 0x28},
+    {0x60, 0x55},
+
+
+    {0xff, 0x00},
+    {0xc3, 0xef},
+    {0xa6, 0x00},
+    {0xa7, 0x0f},
+    {0xa7, 0x4e},
+    {0xa7, 0x7a},
+    {0xa7, 0x33},
+    {0xa7, 0x00},
+    {0xa7, 0x23},
+    {0xa7, 0x27},
+    {0xa7, 0x3a},
+    {0xa7, 0x70},
+    {0xa7, 0x33},
+    {0xa7, 0x00},//L
+    {0xa7, 0x23},
+    {0xa7, 0x20},
+    {0xa7, 0x0c},
+    {0xa7, 0x66},
+    {0xa7, 0x33},
+    {0xa7, 0x00},
+    {0xa7, 0x23},
+    {0xc3, 0xef},
+#endif
+
+
+#if 1
+    {0xff,0x00},
+    {0x92,0x00},
+    {0x93,0x06},
+    {0x93,0xc1},//e
+    {0x93,0x02},
+    {0x93,0x02},
+    {0x93,0x00},
+    {0x93,0x04},
+#endif
+
+    {0x03, 0x0f},
+    {0xe0, 0x04},
+    {0xc0, 0xc8},
+    {0xc1, 0x96},
+    {0x86, 0x3d},
+    {0x50, 0x89},
+    {0x51, 0x90},
+    {0x52, 0x2c},
+    {0x53, 0x00},
+    {0x54, 0x00},
+    {0x55, 0x88},
+    {0x57, 0x00},
+    {0x5a, 0xa0},
+    {0x5b, 0x78},
+    {0x5c, 0x00},
+    {0xd3, 0x04},
+    {0xe0, 0x00},
+
+  {0x0, 0x0}   //end flag
+
+};
+
+/* 1600X1200 UXGA */
+static struct reginfo sensor_uxga[] =
+{
+    {0xff, 0x00},
+    {0xe0, 0x04},
+    {0xc0, 0xc8},
+    {0xc1, 0x96},
+    {0x86, 0x3d},
+    {0x50, 0x00},
+    {0x51, 0x90},
+    {0x52, 0x2c},
+    {0x53, 0x00},
+    {0x54, 0x00},
+    {0x55, 0x88},
+    {0x57, 0x00},
+    {0x5a, 0x90},
+    {0x5b, 0x2c},
+    {0x5c, 0x05},
+    {0xd3, 0x82},
+    {0xe0, 0x00},
+  {0x0, 0x0}   //end flag
+};
+
+/* 1280X1024 SXGA */
+static struct reginfo sensor_sxga[] =
+{
+    {0xff, 0x00},
+    {0xe0, 0x04},
+    {0xc0, 0xc8},
+    {0xc1, 0x96},
+    {0x86, 0x3d},
+    {0x50, 0x00},
+    {0x51, 0x90},
+    {0x52, 0x2c},
+    {0x53, 0x00},
+    {0x54, 0x00},
+    {0x55, 0x88},
+    {0x57, 0x00},
+    {0x5a, 0x40},
+    {0x5b, 0x00},
+    {0x5c, 0x05},
+    {0xd3, 0x82},
+    {0xe0, 0x00},
+  {0x0, 0x0}   //end flag
+};
+
+
+static struct reginfo sensor_xga[] =
+{
+    {0xff, 0x00},
+    {0xe0, 0x04},
+    {0xc0, 0xc8},
+    {0xc1, 0x96},
+    {0x86, 0x3d},
+    {0x50, 0x00},
+    {0x51, 0x90},
+    {0x52, 0x2c},
+    {0x53, 0x00},
+    {0x54, 0x00},
+    {0x55, 0x88},
+    {0x57, 0x00},
+    {0x5a, 0x40},
+    {0x5b, 0x00},
+    {0x5c, 0x05},
+    {0xd3, 0x82},
+    {0xe0, 0x00},
+  {0x0, 0x0}   //end flag
+
+
+};
+
+
+/* 800X600 SVGA*/
+static struct reginfo sensor_svga[] =
+{
+  {0x0, 0x0}   //end flag
+};
+
+/* 640X480 VGA */
+static struct reginfo sensor_vga[] =
+{
+   {0x0, 0x0}   //end flag
+ };
+
+/* 352X288 CIF */
+static struct reginfo sensor_cif[] =
+{
+  {0x0, 0x0}   //end flag
+};
+
+/* 320*240 QVGA */
+static  struct reginfo sensor_qvga[] =
+{
+  {0x0, 0x0}   //end flag
+};
+
+/* 176X144 QCIF*/
+static struct reginfo sensor_qcif[] =
+{
+  {0x0, 0x0}   //end flag
+};
+#if 0
+/* 160X120 QQVGA*/
+static struct reginfo ov2655_qqvga[] =
+{
+
+    {0x300E, 0x34},
+    {0x3011, 0x01},
+    {0x3012, 0x10},
+    {0x302a, 0x02},
+    {0x302b, 0xE6},
+    {0x306f, 0x14},
+    {0x3362, 0x90},
+
+    {0x3070, 0x5d},
+    {0x3072, 0x5d},
+    {0x301c, 0x07},
+    {0x301d, 0x07},
+
+    {0x3020, 0x01},
+    {0x3021, 0x18},
+    {0x3022, 0x00},
+    {0x3023, 0x06},
+    {0x3024, 0x06},
+    {0x3025, 0x58},
+    {0x3026, 0x02},
+    {0x3027, 0x61},
+    {0x3088, 0x00},
+    {0x3089, 0xa0},
+    {0x308a, 0x00},
+    {0x308b, 0x78},
+    {0x3316, 0x64},
+    {0x3317, 0x25},
+    {0x3318, 0x80},
+    {0x3319, 0x08},
+    {0x331a, 0x0a},
+    {0x331b, 0x07},
+    {0x331c, 0x80},
+    {0x331d, 0x38},
+    {0x3100, 0x00},
+    {0x3302, 0x11},
+
+    {0x0, 0x0},
+};
+
+
+
+static  struct reginfo ov2655_Sharpness_auto[] =
+{
+    {0x3306, 0x00},
+};
+
+static  struct reginfo ov2655_Sharpness1[] =
+{
+    {0x3306, 0x08},
+    {0x3371, 0x00},
+};
+
+static  struct reginfo ov2655_Sharpness2[][3] =
+{
+    //Sharpness 2
+    {0x3306, 0x08},
+    {0x3371, 0x01},
+};
+
+static  struct reginfo ov2655_Sharpness3[] =
+{
+    //default
+    {0x3306, 0x08},
+    {0x332d, 0x02},
+};
+static  struct reginfo ov2655_Sharpness4[]=
+{
+    //Sharpness 4
+    {0x3306, 0x08},
+    {0x332d, 0x03},
+};
+
+static  struct reginfo ov2655_Sharpness5[] =
+{
+    //Sharpness 5
+    {0x3306, 0x08},
+    {0x332d, 0x04},
+};
+#endif
+
+static  struct reginfo sensor_ClrFmt_YUYV[]=
+{
+    //{0x4300, 0x30},
+    {0x00, 0x00}
+};
+
+static  struct reginfo sensor_ClrFmt_UYVY[]=
+{
+    //{0x4300, 0x32},
+    {0x00, 0x00}
+};
+
+#if CONFIG_SENSOR_WhiteBalance
+static  struct reginfo sensor_WhiteB_Auto[]=
+{
+    {0x3406, 0x00},  //AWB auto, bit[1]:0,auto
+    {0x0000, 0x00}
+};
+/* Cloudy Colour Temperature : 6500K - 8000K  */
+static  struct reginfo sensor_WhiteB_Cloudy[]=
+{
+    {0x3406, 0x01},
+    {0x3400, 0x07},
+    {0x3401, 0x08},
+    {0x3402, 0x04},
+    {0x3403, 0x00},
+    {0x3404, 0x05},
+    {0x3405, 0x00},
+    {0x0000, 0x00}
+};
+/* ClearDay Colour Temperature : 5000K - 6500K  */
+static  struct reginfo sensor_WhiteB_ClearDay[]=
+{
+    //Sunny
+    {0x3406, 0x01},
+    {0x3400, 0x07},
+    {0x3401, 0x02},
+    {0x3402, 0x04},
+    {0x3403, 0x00},
+    {0x3404, 0x05},
+    {0x3405, 0x15},
+    {0x0000, 0x00}
+};
+/* Office Colour Temperature : 3500K - 5000K  */
+static  struct reginfo sensor_WhiteB_TungstenLamp1[]=
+{
+    //Office
+    {0x3406, 0x01},
+    {0x3400, 0x06},
+    {0x3401, 0x2a},
+    {0x3402, 0x04},
+    {0x3403, 0x00},
+    {0x3404, 0x07},
+    {0x3405, 0x24},
+    {0x0000, 0x00}
+
+};
+/* Home Colour Temperature : 2500K - 3500K  */
+static  struct reginfo sensor_WhiteB_TungstenLamp2[]=
+{
+    //Home
+    {0x3406, 0x01},
+    {0x3400, 0x04},
+    {0x3401, 0x58},
+    {0x3402, 0x04},
+    {0x3403, 0x00},
+    {0x3404, 0x07},
+    {0x3405, 0x24},
+    {0x0000, 0x00}
+};
+static struct reginfo *sensor_WhiteBalanceSeqe[] = {sensor_WhiteB_Auto, sensor_WhiteB_TungstenLamp1,sensor_WhiteB_TungstenLamp2,
+    sensor_WhiteB_ClearDay, sensor_WhiteB_Cloudy,NULL,
+};
+#endif
+
+#if CONFIG_SENSOR_Brightness
+static  struct reginfo sensor_Brightness0[]=
+{
+    // Brightness -2
+    {0xff, 0x01},
+    {0x24, 0x34},
+    {0x25, 0x22},
+    {0x26, 0x70},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Brightness1[]=
+{
+    // Brightness -1
+
+    {0xff, 0x01},
+    {0x24, 0x58},
+    {0x25, 0x50},
+    {0x26, 0x92},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Brightness2[]=
+{
+    //  Brightness 0
+
+       {0xff, 0x01},
+       {0x24, 0xa8},
+       {0x25, 0x90},
+       {0x26, 0xd6},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Brightness3[]=
+{
+    // Brightness +1
+
+    {0xff, 0x01},
+    {0x24, 0x48},
+    {0x25, 0x40},
+    {0x26, 0x81},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Brightness4[]=
+{
+    //  Brightness +2
+
+    {0xff, 0x01},
+    {0x24, 0x58},
+    {0x25, 0x50},
+    {0x26, 0x92},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Brightness5[]=
+{
+    //  Brightness +3
+    {0xff, 0x01},
+    {0x24, 0x70},
+    {0x25, 0x60},
+    {0x26, 0xa4},
+  {0x0, 0x0}   //end flag
+};
+static struct reginfo *sensor_BrightnessSeqe[] = {sensor_Brightness0, sensor_Brightness1, sensor_Brightness2, sensor_Brightness3,
+    sensor_Brightness4, sensor_Brightness5,NULL,
+};
+
+#endif
+
+#if CONFIG_SENSOR_Effect
+static  struct reginfo sensor_Effect_Normal[] =
+{
+       {0xff,0x00},
+       {0x7c,0x00},
+       {0x7d,0x00},
+       {0x7c,0x05},
+       {0x7d,0x80},
+       {0x7d,0x80},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Effect_WandB[] =
+{
+    {0xff,0x00},
+    {0x7c,0x00},
+    {0x7d,0x18},
+    {0x7c,0x05},
+    {0x7d,0x80},
+    {0x7d,0x80},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Effect_Sepia[] =
+{
+    {0xff,0x00},
+    {0x7c,0x00},
+    {0x7d,0x18},
+    {0x7c,0x05},
+    {0x7d,0x40},
+    {0x7d,0xc0},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Effect_Negative[] =
+{
+    {0xff,0x00},
+    {0x7c,0x00},
+    {0x7d,0x40},
+    {0x7c,0x05},
+    {0x7d,0x80},
+    {0x7d,0x80},
+  {0x0, 0x0}   //end flag
+};
+static  struct reginfo sensor_Effect_Bluish[] =
+{
+    {0Xff, 0X00},
+    {0X7c, 0X00},
+    {0X7d, 0X18},
+    {0X7c, 0X05},
+    {0X7d, 0Xa0},
+    {0X7d, 0X40},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Effect_Green[] =
+{
+    {0Xff, 0X00},
+    {0X7c, 0X00},
+    {0X7d, 0X18},
+    {0X7c, 0X05},
+    {0X7d, 0X40},
+    {0X7d, 0X40},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Effect_Exp_Windows_Half[] =
+{
+       {0xff, 0x01},
+       {0x5d, 0x00},
+       {0x5e, 0x3c},
+       {0x5f, 0x28},
+       {0x60, 0x55},
+  {0x0, 0x0}   //end flag
+};
+static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effect_WandB, sensor_Effect_Negative,sensor_Effect_Sepia,
+    sensor_Effect_Bluish, sensor_Effect_Green,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Exposure
+static  struct reginfo sensor_Exposure0[]=
+{
+       {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_Exposure1[]=
+{
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_Exposure2[]=
+{
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_Exposure3[]=
+{
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_Exposure4[]=
+{
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_Exposure5[]=
+{
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_Exposure6[]=
+{
+    {0x0000, 0x00}
+};
+
+static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,
+    sensor_Exposure4, sensor_Exposure5,sensor_Exposure6,NULL,
+};
+#endif
+#if CONFIG_SENSOR_Saturation
+static  struct reginfo sensor_Saturation0[]=
+{
+       {0xff, 0x00},
+       {0x90, 0x00},
+       {0x91, 0x0e},
+       {0x91, 0x1a},
+       {0x91, 0x31},
+       {0x91, 0x5a},
+       {0x91, 0x69},
+       {0x91, 0x75},
+       {0x91, 0x7e},
+       {0x91, 0x88},
+       {0x91, 0x8f},
+       {0x91, 0x96},
+       {0x91, 0xa3},
+       {0x91, 0xaf},
+       {0x91, 0xc4},
+       {0x91, 0xd7},
+       {0x91, 0xe8},
+       {0x91, 0x20},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Saturation1[]=
+{
+    {0xff, 0x00},
+    {0x90, 0x00},
+    {0x91, 0x03},
+    {0x91, 0x0a},
+    {0x91, 0x1a},
+    {0x91, 0x3f},
+    {0x91, 0x4e},
+    {0x91, 0x5b},
+    {0x91, 0x68},
+    {0x91, 0x75},
+    {0x91, 0x7f},
+    {0x91, 0x89},
+    {0x91, 0x9a},
+    {0x91, 0xa6},
+    {0x91, 0xbd},
+    {0x91, 0xd3},
+    {0x91, 0xe5},
+    {0x91, 0x24},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Saturation2[]=
+{
+    {0xff, 0x00},
+    {0x90, 0x00},
+    {0x91, 0x04},
+    {0x91, 0x07},
+    {0x91, 0x10},
+    {0x91, 0x28},
+    {0x91, 0x36},
+    {0x91, 0x44},
+    {0x91, 0x52},
+    {0x91, 0x60},
+    {0x91, 0x6c},
+    {0x91, 0x78},
+    {0x91, 0x8c},
+    {0x91, 0x9e},
+    {0x91, 0xbb},
+    {0x91, 0xd3},
+    {0x91, 0xe5},
+    {0x91, 0x24},
+  {0x0, 0x0}   //end flag      
+};
+static struct reginfo *sensor_SaturationSeqe[] = {sensor_Saturation0, sensor_Saturation1, sensor_Saturation2, NULL,};
+
+
+#endif
+#if CONFIG_SENSOR_Contrast
+static  struct reginfo sensor_Contrast0[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x10},
+    {0x7d, 0x4a},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+
+};
+
+static  struct reginfo sensor_Contrast1[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x14},
+    {0x7d, 0x40},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Contrast2[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x18},
+    {0x7d, 0x34},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Contrast3[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x1c},
+    {0x7d, 0x2a},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Contrast4[]=
+{
+    {0xff,0x00},
+    {0x7c,0x00},
+    {0x7d,0x04},
+    {0x7c,0x07},
+    {0x7d,0x20},
+    {0x7d,0x24},
+    {0x7d,0x16},
+    {0x7d,0x06},
+  {0x0, 0x0}   //end flag
+};
+
+
+static  struct reginfo sensor_Contrast5[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x20},
+    {0x7d, 0x20},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Contrast6[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x24},
+    {0x7d, 0x16},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+};
+
+
+static  struct reginfo sensor_Contrast7[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x28},
+    {0x7d, 0x0c},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Contrast8[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x2c},
+    {0x7d, 0x02},
+    {0x7d, 0x06},
+  {0x0, 0x0}   //end flag
+};
+
+static  struct reginfo sensor_Contrast9[]=
+{
+    {0xff, 0x00},
+    {0x7c, 0x00},
+    {0x7d, 0x04},
+    {0x7c, 0x07},
+    {0x7d, 0x20},
+    {0x7d, 0x30},
+    {0x7d, 0x08},
+    {0x7d, 0x0e},
+  {0x0, 0x0}   //end flag
+};
+
+
+
+static struct reginfo *sensor_ContrastSeqe[] = {sensor_Contrast0, sensor_Contrast1, sensor_Contrast2, sensor_Contrast3,
+    sensor_Contrast4, sensor_Contrast5, sensor_Contrast6, NULL,
+};
+
+#endif
+#if CONFIG_SENSOR_Mirror
+static  struct reginfo sensor_MirrorOn[]=
+{
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_MirrorOff[]=
+{
+    {0x0000, 0x00}
+};
+static struct reginfo *sensor_MirrorSeqe[] = {sensor_MirrorOff, sensor_MirrorOn,NULL,};
+#endif
+#if CONFIG_SENSOR_Flip
+static  struct reginfo sensor_FlipOn[]=
+{
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_FlipOff[]=
+{
+    {0x0000, 0x00}
+};
+static struct reginfo *sensor_FlipSeqe[] = {sensor_FlipOff, sensor_FlipOn,NULL,};
+
+#endif
+#if CONFIG_SENSOR_Scene
+static  struct reginfo sensor_SceneAuto[] =
+{
+    {0x3a00, 0x78},
+    {0x0000, 0x00}
+};
+
+static  struct reginfo sensor_SceneNight[] =
+{
+    {0x3003, 0x80},
+       {0x3004, 0x20},
+       {0x3005, 0x18},
+       {0x3006, 0x0d},
+       {0x3a00, 0x7c},
+       {0x3a02 ,0x07},
+       {0x3a03 ,0x38},
+       {0x3a14 ,0x07},
+       {0x3a15 ,0x38},
+    {0x0000, 0x00}
+};
+static struct reginfo *sensor_SceneSeqe[] = {sensor_SceneAuto, sensor_SceneNight,NULL,};
+
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static struct reginfo sensor_Zoom0[] =
+{
+    {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom1[] =
+{
+     {0x0, 0x0},
+};
+
+static struct reginfo sensor_Zoom2[] =
+{
+    {0x0, 0x0},
+};
+
+
+static struct reginfo sensor_Zoom3[] =
+{
+    {0x0, 0x0},
+};
+static struct reginfo *sensor_ZoomSeqe[] = {sensor_Zoom0, sensor_Zoom1, sensor_Zoom2, sensor_Zoom3, NULL,};
+#endif
+static const struct v4l2_querymenu sensor_menus[] =
+{
+       #if CONFIG_SENSOR_WhiteBalance
+    { .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 0,  .name = "auto",  .reserved = 0, }, {  .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 1, .name = "incandescent",  .reserved = 0,},
+    { .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 2,  .name = "fluorescent", .reserved = 0,}, {  .id = V4L2_CID_DO_WHITE_BALANCE, .index = 3,  .name = "daylight", .reserved = 0,},
+    { .id = V4L2_CID_DO_WHITE_BALANCE,  .index = 4,  .name = "cloudy-daylight", .reserved = 0,},
+    #endif
+
+       #if CONFIG_SENSOR_Effect
+    { .id = V4L2_CID_EFFECT,  .index = 0,  .name = "none",  .reserved = 0, }, {  .id = V4L2_CID_EFFECT,  .index = 1, .name = "mono",  .reserved = 0,},
+    { .id = V4L2_CID_EFFECT,  .index = 2,  .name = "negative", .reserved = 0,}, {  .id = V4L2_CID_EFFECT, .index = 3,  .name = "sepia", .reserved = 0,},
+    { .id = V4L2_CID_EFFECT,  .index = 4, .name = "posterize", .reserved = 0,} ,{ .id = V4L2_CID_EFFECT,  .index = 5,  .name = "aqua", .reserved = 0,},
+    #endif
+
+       #if CONFIG_SENSOR_Scene
+    { .id = V4L2_CID_SCENE,  .index = 0, .name = "auto", .reserved = 0,} ,{ .id = V4L2_CID_SCENE,  .index = 1,  .name = "night", .reserved = 0,},
+    #endif
+
+       #if CONFIG_SENSOR_Flash
+    { .id = V4L2_CID_FLASH,  .index = 0,  .name = "off",  .reserved = 0, }, {  .id = V4L2_CID_FLASH,  .index = 1, .name = "auto",  .reserved = 0,},
+    { .id = V4L2_CID_FLASH,  .index = 2,  .name = "on", .reserved = 0,}, {  .id = V4L2_CID_FLASH, .index = 3,  .name = "torch", .reserved = 0,},
+    #endif
+};
+
+static const struct v4l2_queryctrl sensor_controls[] =
+{
+       #if CONFIG_SENSOR_WhiteBalance
+    {
+        .id            = V4L2_CID_DO_WHITE_BALANCE,
+        .type          = V4L2_CTRL_TYPE_MENU,
+        .name          = "White Balance Control",
+        .minimum       = 0,
+        .maximum       = 4,
+        .step          = 1,
+        .default_value = 0,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_Brightness
+       {
+        .id            = V4L2_CID_BRIGHTNESS,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "Brightness Control",
+        .minimum       = -3,
+        .maximum       = 2,
+        .step          = 1,
+        .default_value = 0,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_Effect
+       {
+        .id            = V4L2_CID_EFFECT,
+        .type          = V4L2_CTRL_TYPE_MENU,
+        .name          = "Effect Control",
+        .minimum       = 0,
+        .maximum       = 5,
+        .step          = 1,
+        .default_value = 0,
+    },
+       #endif
+
+       #if CONFIG_SENSOR_Exposure
+       {
+        .id            = V4L2_CID_EXPOSURE,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "Exposure Control",
+        .minimum       = 0,
+        .maximum       = 6,
+        .step          = 1,
+        .default_value = 0,
+    },
+       #endif
+
+       #if CONFIG_SENSOR_Saturation
+       {
+        .id            = V4L2_CID_SATURATION,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "Saturation Control",
+        .minimum       = 0,
+        .maximum       = 2,
+        .step          = 1,
+        .default_value = 0,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_Contrast
+       {
+        .id            = V4L2_CID_CONTRAST,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "Contrast Control",
+        .minimum       = -3,
+        .maximum       = 3,
+        .step          = 1,
+        .default_value = 0,
+    },
+       #endif
+
+       #if CONFIG_SENSOR_Mirror
+       {
+        .id            = V4L2_CID_HFLIP,
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,
+        .name          = "Mirror Control",
+        .minimum       = 0,
+        .maximum       = 1,
+        .step          = 1,
+        .default_value = 1,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_Flip
+       {
+        .id            = V4L2_CID_VFLIP,
+        .type          = V4L2_CTRL_TYPE_BOOLEAN,
+        .name          = "Flip Control",
+        .minimum       = 0,
+        .maximum       = 1,
+        .step          = 1,
+        .default_value = 1,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_Scene
+    {
+        .id            = V4L2_CID_SCENE,
+        .type          = V4L2_CTRL_TYPE_MENU,
+        .name          = "Scene Control",
+        .minimum       = 0,
+        .maximum       = 1,
+        .step          = 1,
+        .default_value = 0,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_DigitalZoom
+    {
+        .id            = V4L2_CID_ZOOM_RELATIVE,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "DigitalZoom Control",
+        .minimum       = -1,
+        .maximum       = 1,
+        .step          = 1,
+        .default_value = 0,
+    }, {
+        .id            = V4L2_CID_ZOOM_ABSOLUTE,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "DigitalZoom Control",
+        .minimum       = 0,
+        .maximum       = 3,
+        .step          = 1,
+        .default_value = 0,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_Focus
+       {
+        .id            = V4L2_CID_FOCUS_RELATIVE,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "Focus Control",
+        .minimum       = -1,
+        .maximum       = 1,
+        .step          = 1,
+        .default_value = 0,
+    }, {
+        .id            = V4L2_CID_FOCUS_ABSOLUTE,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "Focus Control",
+        .minimum       = 0,
+        .maximum       = 255,
+        .step          = 1,
+        .default_value = 125,
+    },
+    #endif
+
+       #if CONFIG_SENSOR_Flash
+       {
+        .id            = V4L2_CID_FLASH,
+        .type          = V4L2_CTRL_TYPE_MENU,
+        .name          = "Flash Control",
+        .minimum       = 0,
+        .maximum       = 3,
+        .step          = 1,
+        .default_value = 0,
+    },
+       #endif
+};
+
+static int sensor_probe(struct i2c_client *client, const struct i2c_device_id *did);
+static int sensor_video_probe(struct soc_camera_device *icd, struct i2c_client *client);
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
+static int sensor_g_ext_controls(struct v4l2_subdev *sd,  struct v4l2_ext_controls *ext_ctrl);
+static int sensor_s_ext_controls(struct v4l2_subdev *sd,  struct v4l2_ext_controls *ext_ctrl);
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg);
+static int sensor_resume(struct soc_camera_device *icd);
+static int sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd);
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value);
+#endif
+static int sensor_deactivate(struct i2c_client *client);
+
+static struct soc_camera_ops sensor_ops =
+{
+    .suspend                     = sensor_suspend,
+    .resume                       = sensor_resume,
+    .set_bus_param             = sensor_set_bus_param,
+    .query_bus_param   = sensor_query_bus_param,
+    .controls          = sensor_controls,
+    .menus                         = sensor_menus,
+    .num_controls              = ARRAY_SIZE(sensor_controls),
+    .num_menus         = ARRAY_SIZE(sensor_menus),
+};
+
+/* only one fixed colorspace per pixelcode */
+struct sensor_datafmt {
+       enum v4l2_mbus_pixelcode code;
+       enum v4l2_colorspace colorspace;
+};
+
+/* Find a data format by a pixel code in an array */
+static const struct sensor_datafmt *sensor_find_datafmt(
+       enum v4l2_mbus_pixelcode code, const struct sensor_datafmt *fmt,
+       int n)
+{
+       int i;
+       for (i = 0; i < n; i++)
+               if (fmt[i].code == code)
+                       return fmt + i;
+
+       return NULL;
+}
+
+static const struct sensor_datafmt sensor_colour_fmts[] = {
+    {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+    {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}    
+};
+
+typedef struct sensor_info_priv_s
+{
+    int whiteBalance;
+    int brightness;
+    int contrast;
+    int saturation;
+    int effect;
+    int scene;
+    int digitalzoom;
+    int focus;
+    int flash;
+    int exposure;
+       bool snap2preview;
+       bool video2preview;
+    unsigned char mirror;                                        /* HFLIP */
+    unsigned char flip;                                          /* VFLIP */
+    unsigned int winseqe_cur_addr;
+    struct sensor_datafmt fmt;
+
+} sensor_info_priv_t;
+
+struct sensor
+{
+    struct v4l2_subdev subdev;
+    struct i2c_client *client;
+    sensor_info_priv_t info_priv;
+    int model; /* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
+#if CONFIG_SENSOR_I2C_NOSCHED
+       atomic_t tasklock_cnt;
+#endif
+       struct rk29camera_platform_data *sensor_io_request;
+    struct rk29camera_gpio_res *sensor_gpio_res;
+};
+
+static struct sensor* to_sensor(const struct i2c_client *client)
+{
+    return container_of(i2c_get_clientdata(client), struct sensor, subdev);
+}
+
+static int sensor_task_lock(struct i2c_client *client, int lock)
+{
+#if CONFIG_SENSOR_I2C_NOSCHED
+       int cnt = 3;
+    struct sensor *sensor = to_sensor(client);
+
+       if (lock) {
+               if (atomic_read(&sensor->tasklock_cnt) == 0) {
+                       while ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt>0)) {
+                               SENSOR_TR("\n %s will obtain i2c in atomic, but i2c bus is locked! Wait...\n",SENSOR_NAME_STRING());
+                               msleep(35);
+                               cnt--;
+                       }
+                       if ((atomic_read(&client->adapter->bus_lock.count) < 1) && (cnt<=0)) {
+                               SENSOR_TR("\n %s obtain i2c fail in atomic!!\n",SENSOR_NAME_STRING());
+                               goto sensor_task_lock_err;
+                       }
+                       preempt_disable();
+               }
+
+               atomic_add(1, &sensor->tasklock_cnt);
+       } else {
+               if (atomic_read(&sensor->tasklock_cnt) > 0) {
+                       atomic_sub(1, &sensor->tasklock_cnt);
+
+                       if (atomic_read(&sensor->tasklock_cnt) == 0)
+                               preempt_enable();
+               }
+       }
+       return 0;
+sensor_task_lock_err:
+       return -1;  
+#else
+    return 0;
+#endif
+
+}
+static int sensor_write(struct i2c_client *client, u8 reg, u8 val)
+{
+    int err,cnt;
+    u8 buf[2];
+    struct i2c_msg msg[1];
+
+    buf[0] = reg & 0xFF;
+    buf[1] = val;
+
+    msg->addr = client->addr;
+    msg->flags = client->flags;
+    msg->buf = buf;
+    msg->len = sizeof(buf);
+    msg->scl_rate = CONFIG_SENSOR_I2C_SPEED;                                        /* ddl@rock-chips.com : 100kHz */
+    msg->read_type = 0;               /* fpga i2c:0==I2C_NORMAL : direct use number not enum for don't want include spi_fpga.h */
+
+    cnt = 3;
+    err = -EAGAIN;
+
+    while ((cnt-->0) && (err < 0)) {                       /* ddl@rock-chips.com :  Transfer again if transent is failed   */
+        err = i2c_transfer(client->adapter, msg, 1);
+
+        if (err >= 0) {
+            return 0;
+        } else {
+            SENSOR_TR("\n %s write reg(0x%x, val:0x%x) failed, try to write again!\n",SENSOR_NAME_STRING(),reg, val);
+            udelay(10);
+        }
+    }
+
+    return err;
+}
+
+/* sensor register read */
+static int sensor_read(struct i2c_client *client, u8 reg, u8 *val)
+{
+    int err,cnt;
+    u8 buf[1];
+    struct i2c_msg msg[2];
+
+    buf[0] = reg ;//>> 8;
+   // buf[1] = 0;
+
+    msg[0].addr = client->addr;
+    msg[0].flags = client->flags;
+    msg[0].buf = buf;
+    msg[0].len = sizeof(buf);
+    msg[0].scl_rate = CONFIG_SENSOR_I2C_SPEED;       /* ddl@rock-chips.com : 100kHz */
+    msg[0].read_type = 2;//0x55;   /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+    msg[1].addr = client->addr;
+    msg[1].flags = client->flags|I2C_M_RD;
+    msg[1].buf = buf;
+    msg[1].len = 1;
+    msg[1].scl_rate = CONFIG_SENSOR_I2C_SPEED;                       /* ddl@rock-chips.com : 100kHz */
+    msg[1].read_type = 2;                             /* fpga i2c:0==I2C_NO_STOP : direct use number not enum for don't want include spi_fpga.h */
+
+    cnt = 3;
+    err = -EAGAIN;
+    while ((cnt-->0) && (err < 0)) {                       /* ddl@rock-chips.com :  Transfer again if transent is failed   */
+        err = i2c_transfer(client->adapter, msg, 2);
+
+        if (err >= 0) {
+            *val = buf[0];
+            return 0;
+        } else {
+               SENSOR_TR("\n %s read reg(0x%x val:0x%x) failed, try to read again! \n",SENSOR_NAME_STRING(),reg, *val);
+            udelay(10);
+        }
+    }
+
+    return err;
+}
+
+/* write a array of registers  */
+static int sensor_write_array(struct i2c_client *client, struct reginfo *regarray)
+{
+    int err = 0, cnt;
+    int i = 0;
+#if CONFIG_SENSOR_I2C_RDWRCHK    
+       char valchk;
+#endif
+
+       cnt = 0;
+       if (sensor_task_lock(client, 1) < 0)
+               goto sensor_write_array_end;
+    while (regarray[i].reg != 0)
+    {
+        err = sensor_write(client, regarray[i].reg, regarray[i].val);
+        if (err < 0)
+        {
+            if (cnt-- > 0) {
+                           SENSOR_TR("%s..write failed current reg:0x%x, Write array again !\n", SENSOR_NAME_STRING(),regarray[i].reg);
+                               i = 0;
+                               continue;
+            } else {
+                SENSOR_TR("%s..write array failed!!!\n", SENSOR_NAME_STRING());
+                err = -EPERM;
+                               goto sensor_write_array_end;
+            }
+        } else {
+        #if CONFIG_SENSOR_I2C_RDWRCHK
+                       sensor_read(client, regarray[i].reg, &valchk);
+                       if (valchk != regarray[i].val)
+                               SENSOR_TR("%s Reg:0x%x write(0x%x, 0x%x) fail\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+               #endif
+        }
+        i++;
+    }
+
+sensor_write_array_end:
+       sensor_task_lock(client,0);
+       return err;
+}
+#if CONFIG_SENSOR_I2C_RDWRCHK
+static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regarray)
+{
+    int cnt;
+    int i = 0;
+       char valchk;
+
+       cnt = 0;
+       valchk = 0;
+    while (regarray[i].reg != 0)
+    {
+               sensor_read(client, regarray[i].reg, &valchk);
+               if (valchk != regarray[i].val)
+                       SENSOR_TR("%s Reg:0x%x read(0x%x, 0x%x) error\n",SENSOR_NAME_STRING(), regarray[i].reg, regarray[i].val, valchk);
+
+        i++;
+    }
+    return 0;
+}
+#endif
+static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
+{
+       struct soc_camera_link *icl = to_soc_camera_link(icd);
+       int ret = 0;
+
+    SENSOR_DG("%s %s  cmd(%d) on(%d)\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd,on);
+
+       switch (cmd)
+       {
+               case Sensor_PowerDown:
+               {
+                       if (icl->powerdown) {
+                               ret = icl->powerdown(icd->pdev, on);
+                               if (ret == RK29_CAM_IO_SUCCESS) {
+                                       if (on == 0) {
+                                               mdelay(2);
+                                               if (icl->reset)
+                                                       icl->reset(icd->pdev);
+                                       }
+                               } else if (ret == RK29_CAM_EIO_REQUESTFAIL) {
+                                       ret = -ENODEV;
+                                       goto sensor_power_end;
+                               }
+                       }
+                       break;
+               }
+               case Sensor_Flash:
+               {
+                       struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+               struct sensor *sensor = to_sensor(client);
+
+                       if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
+                               sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+                       }
+            break;
+               }
+               default:
+               {
+                       SENSOR_TR("%s %s cmd(0x%x) is unknown!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+                       break;
+               }
+       }
+sensor_power_end:
+       return ret;
+}
+static int sensor_init(struct v4l2_subdev *sd, u32 val)
+{
+    struct i2c_client *client = sd->priv;
+    struct soc_camera_device *icd = client->dev.platform_data;
+    struct sensor *sensor = to_sensor(client);
+       const struct v4l2_queryctrl *qctrl;
+    const struct sensor_datafmt *fmt;
+    char value;
+    int ret,pid = 0;
+
+    SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+       if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+               ret = -ENODEV;
+               goto sensor_INIT_ERR;
+       }
+
+    /* soft reset */
+       if (sensor_task_lock(client,1)<0)
+               goto sensor_INIT_ERR;
+    ret = sensor_write(client, 0xff, 1);
+    ret |= sensor_write(client, 0x12, 0x80);
+    if (ret != 0)
+    {
+        SENSOR_TR("%s soft reset sensor failed\n",SENSOR_NAME_STRING());
+        ret = -ENODEV;
+               goto sensor_INIT_ERR;
+    }
+
+    mdelay(5);  //delay 5 microseconds
+       /* check if it is an sensor sensor */
+    ret = sensor_write(client, 0xff, 1);
+    ret |= sensor_read(client, 0x0a, &value);
+    if (ret != 0) {
+        SENSOR_TR("read chip id high byte failed\n");
+        ret = -ENODEV;
+        goto sensor_INIT_ERR;
+    }
+
+    pid = value << 8;
+    ret = sensor_read(client, 0x0b, &value);
+    if (ret != 0) {
+        SENSOR_TR("read chip id low byte failed\n");
+        ret = -ENODEV;
+        goto sensor_INIT_ERR;
+    }
+
+    pid |= (value & 0xff);
+
+    SENSOR_DG("\n %s  pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+    if ((pid == SENSOR_ID)||(pid == SENSOR_ID1)) {
+        sensor->model = SENSOR_V4L2_IDENT;
+    } else {
+        SENSOR_TR("error: %s mismatched   pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+        ret = -ENODEV;
+        goto sensor_INIT_ERR;
+    }
+
+    ret = sensor_write_array(client, sensor_init_data);
+    if (ret != 0)
+    {
+        SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
+        goto sensor_INIT_ERR;
+    }
+       sensor_task_lock(client,0);
+    sensor->info_priv.winseqe_cur_addr  = (int)SENSOR_INIT_WINSEQADR;
+    fmt = sensor_find_datafmt(SENSOR_INIT_PIXFMT,sensor_colour_fmts, ARRAY_SIZE(sensor_colour_fmts));
+    if (!fmt) {
+        SENSOR_TR("error: %s initial array colour fmts is not support!!",SENSOR_NAME_STRING());
+        ret = -EINVAL;
+        goto sensor_INIT_ERR;
+    }
+       sensor->info_priv.fmt = *fmt;
+
+    /* sensor sensor information for initialization  */
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+       if (qctrl)
+       sensor->info_priv.whiteBalance = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_BRIGHTNESS);
+       if (qctrl)
+       sensor->info_priv.brightness = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+       if (qctrl)
+       sensor->info_priv.effect = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EXPOSURE);
+       if (qctrl)
+        sensor->info_priv.exposure = qctrl->default_value;
+
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SATURATION);
+       if (qctrl)
+        sensor->info_priv.saturation = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_CONTRAST);
+       if (qctrl)
+        sensor->info_priv.contrast = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_HFLIP);
+       if (qctrl)
+        sensor->info_priv.mirror = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_VFLIP);
+       if (qctrl)
+        sensor->info_priv.flip = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_SCENE);
+       if (qctrl)
+        sensor->info_priv.scene = qctrl->default_value;
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+       if (qctrl)
+        sensor->info_priv.digitalzoom = qctrl->default_value;
+
+    /* ddl@rock-chips.com : if sensor support auto focus and flash, programer must run focus and flash code  */
+       #if CONFIG_SENSOR_Focus
+    sensor_set_focus();
+    qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FOCUS_ABSOLUTE);
+       if (qctrl)
+        sensor->info_priv.focus = qctrl->default_value;
+       #endif
+
+       #if CONFIG_SENSOR_Flash
+       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
+       if (qctrl)
+        sensor->info_priv.flash = qctrl->default_value;
+    #endif
+
+    SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
+
+    return 0;
+sensor_INIT_ERR:
+       sensor_task_lock(client,0);
+       sensor_deactivate(client);
+    return ret;
+}
+
+static int sensor_deactivate(struct i2c_client *client)
+{
+       struct soc_camera_device *icd = client->dev.platform_data;
+
+       SENSOR_DG("\n%s..%s.. Enter\n",SENSOR_NAME_STRING(),__FUNCTION__);
+
+       /* ddl@rock-chips.com : all sensor output pin must change to input for other sensor */
+#if 0  
+       sensor_task_lock(client, 1);
+    sensor_write(client, 0x3000, reg_val&0xfc);
+       sensor_write(client, 0x3001, 0x00);
+       sensor_task_lock(client, 0);
+#endif
+       sensor_ioctrl(icd, Sensor_PowerDown, 1);
+       /* ddl@rock-chips.com : sensor config init width , because next open sensor quickly(soc_camera_open -> Try to configure with default parameters) */
+       icd->user_width = SENSOR_INIT_WIDTH;
+    icd->user_height = SENSOR_INIT_HEIGHT;
+       msleep(100);
+       return 0;
+}
+
+static  struct reginfo sensor_power_down_sequence[]=
+{
+    {0x00,0x00}
+};
+static int sensor_suspend(struct soc_camera_device *icd, pm_message_t pm_msg)
+{
+    int ret;
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if (pm_msg.event == PM_EVENT_SUSPEND) {
+        SENSOR_DG("\n %s Enter Suspend.. \n", SENSOR_NAME_STRING());
+        ret = sensor_write_array(client, sensor_power_down_sequence) ;
+        if (ret != 0) {
+            SENSOR_TR("\n %s..%s WriteReg Fail.. \n", SENSOR_NAME_STRING(),__FUNCTION__);
+            return ret;
+        } else {
+            ret = sensor_ioctrl(icd, Sensor_PowerDown, 1);
+            if (ret < 0) {
+                           SENSOR_TR("\n %s suspend fail for turn on power!\n", SENSOR_NAME_STRING());
+                return -EINVAL;
+            }
+        }
+    } else {
+        SENSOR_TR("\n %s cann't suppout Suspend..\n",SENSOR_NAME_STRING());
+        return -EINVAL;
+    }
+    return 0;
+}
+
+static int sensor_resume(struct soc_camera_device *icd)
+{
+       int ret;
+
+    ret = sensor_ioctrl(icd, Sensor_PowerDown, 0);
+    if (ret < 0) {
+               SENSOR_TR("\n %s resume fail for turn on power!\n", SENSOR_NAME_STRING());
+        return -EINVAL;
+    }
+
+       SENSOR_DG("\n %s Enter Resume.. \n", SENSOR_NAME_STRING());
+
+    return 0;
+
+}
+
+static int sensor_set_bus_param(struct soc_camera_device *icd,
+                                unsigned long flags)
+{
+
+    return 0;
+}
+
+static unsigned long sensor_query_bus_param(struct soc_camera_device *icd)
+{
+    struct soc_camera_link *icl = to_soc_camera_link(icd);
+    unsigned long flags = SENSOR_BUS_PARAM;
+
+    return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+static int sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+    struct i2c_client *client = sd->priv;
+    struct soc_camera_device *icd = client->dev.platform_data;
+    struct sensor *sensor = to_sensor(client);
+
+    mf->width  = icd->user_width;
+       mf->height      = icd->user_height;
+       mf->code        = sensor->info_priv.fmt.code;
+       mf->colorspace  = sensor->info_priv.fmt.colorspace;
+       mf->field       = V4L2_FIELD_NONE;
+
+    return 0;
+}
+static bool sensor_fmt_capturechk(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+    bool ret = false;
+
+       if ((mf->width == 1024) && (mf->height == 768)) {
+               ret = true;
+       } else if ((mf->width == 1280) && (mf->height == 1024)) {
+               ret = true;
+       } else if ((mf->width == 1600) && (mf->height == 1200)) {
+               ret = true;
+       } else if ((mf->width == 2048) && (mf->height == 1536)) {
+               ret = true;
+       } else if ((mf->width == 2592) && (mf->height == 1944)) {
+               ret = true;
+       }
+
+       if (ret == true)
+               SENSOR_DG("%s %dx%d is capture format\n", __FUNCTION__, mf->width, mf->height);
+       return ret;
+}
+
+static bool sensor_fmt_videochk(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+    bool ret = false;
+
+       if ((mf->width == 1280) && (mf->height == 720)) {
+               ret = true;
+       } else if ((mf->width == 1920) && (mf->height == 1080)) {
+               ret = true;
+       }
+
+       if (ret == true)
+               SENSOR_DG("%s %dx%d is video format\n", __FUNCTION__, mf->width, mf->height);
+       return ret;
+}
+static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+    struct i2c_client *client = sd->priv;
+    struct sensor *sensor = to_sensor(client);
+    const struct sensor_datafmt *fmt;
+       const struct v4l2_queryctrl *qctrl;
+       struct soc_camera_device *icd = client->dev.platform_data;
+    struct reginfo *winseqe_set_addr=NULL;
+    int ret=0, set_w,set_h;
+
+       fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,
+                                  ARRAY_SIZE(sensor_colour_fmts));
+       if (!fmt) {
+        ret = -EINVAL;
+        goto sensor_s_fmt_end;
+    }
+
+       if (sensor->info_priv.fmt.code != mf->code) {
+               switch (mf->code)
+               {
+                       case V4L2_MBUS_FMT_YUYV8_2X8:
+                       {
+                               winseqe_set_addr = sensor_ClrFmt_YUYV;
+                               break;
+                       }
+                       case V4L2_MBUS_FMT_UYVY8_2X8:
+                       {
+                               winseqe_set_addr = sensor_ClrFmt_UYVY;
+                               break;
+                       }
+                       default:
+                               break;
+               }
+               if (winseqe_set_addr != NULL) {
+            sensor_write_array(client, winseqe_set_addr);
+                       sensor->info_priv.fmt.code = mf->code;
+            sensor->info_priv.fmt.colorspace= mf->colorspace;            
+                       SENSOR_DG("%s v4l2_mbus_code:%d set success!\n", SENSOR_NAME_STRING(),mf->code);
+               } else {
+                       SENSOR_TR("%s v4l2_mbus_code:%d is invalidate!\n", SENSOR_NAME_STRING(),mf->code);
+               }
+       }
+
+    set_w = mf->width;
+    set_h = mf->height;
+
+       if (((set_w <= 176) && (set_h <= 144)) && sensor_qcif[0].reg)
+       {
+               winseqe_set_addr = sensor_qcif;
+        set_w = 176;
+        set_h = 144;
+       }
+       else if (((set_w <= 320) && (set_h <= 240)) && sensor_qvga[0].reg)
+    {
+        winseqe_set_addr = sensor_qvga;
+        set_w = 320;
+        set_h = 240;
+    }
+    else if (((set_w <= 352) && (set_h<= 288)) && sensor_cif[0].reg)
+    {
+        winseqe_set_addr = sensor_cif;
+        set_w = 352;
+        set_h = 288;
+    }
+    else if (((set_w <= 640) && (set_h <= 480)) && sensor_vga[0].reg)
+    {
+        winseqe_set_addr = sensor_vga;
+        set_w = 640;
+        set_h = 480;
+    }
+    else if (((set_w <= 800) && (set_h <= 600)) && sensor_svga[0].reg)
+    {
+        winseqe_set_addr = sensor_svga;
+        set_w = 800;
+        set_h = 600;
+    }
+       else if (((set_w <= 1024) && (set_h <= 768)) && sensor_xga[0].reg)
+    {
+        winseqe_set_addr = sensor_xga;
+        set_w = 1024;
+        set_h = 768;
+    }
+    else if (((set_w <= 1280) && (set_h <= 1024)) && sensor_sxga[0].reg)
+    {
+        winseqe_set_addr = sensor_sxga;
+        set_w = 1280;
+        set_h = 1024;
+    }
+    else if (((set_w <= 1600) && (set_h <= 1200)) && sensor_uxga[0].reg)
+    {
+        winseqe_set_addr = sensor_uxga;
+        set_w = 1600;
+        set_h = 1200;
+    }
+    else
+    {
+        winseqe_set_addr = SENSOR_INIT_WINSEQADR;               /* ddl@rock-chips.com : Sensor output smallest size if  isn't support app  */
+        set_w = SENSOR_INIT_WIDTH;
+        set_h = SENSOR_INIT_HEIGHT;
+               SENSOR_TR("\n %s..%s Format is Invalidate. pix->width = %d.. pix->height = %d\n",SENSOR_NAME_STRING(),__FUNCTION__,mf->width,mf->height);
+    }
+
+    if ((int)winseqe_set_addr  != sensor->info_priv.winseqe_cur_addr) {
+        #if CONFIG_SENSOR_Flash
+        if (sensor_fmt_capturechk(sd,mf) == true) {      /* ddl@rock-chips.com : Capture */
+            if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+                sensor_ioctrl(icd, Sensor_Flash, Flash_On);
+                SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
+            }           
+        } else {                                        /* ddl@rock-chips.com : Video */
+            if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+                sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+                SENSOR_DG("%s flash off in preivew!\n", SENSOR_NAME_STRING());
+            }
+        }
+        #endif        
+        ret |= sensor_write_array(client, winseqe_set_addr);
+        if (ret != 0) {
+            SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
+            #if CONFIG_SENSOR_Flash
+            if (sensor_fmt_capturechk(sd,mf) == true) {
+                if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
+                    sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+                    SENSOR_TR("%s Capture format set fail, flash off !\n", SENSOR_NAME_STRING());
+                }
+            }
+            #endif
+            goto sensor_s_fmt_end;
+        }
+
+        sensor->info_priv.winseqe_cur_addr  = (int)winseqe_set_addr;
+
+               if (sensor_fmt_capturechk(sd,mf) == true) {                                 /* ddl@rock-chips.com : Capture */
+        #if CONFIG_SENSOR_Effect
+                       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+                       sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+        #endif
+        #if CONFIG_SENSOR_WhiteBalance
+                       if (sensor->info_priv.whiteBalance != 0) {
+                               qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+                               sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+                       }
+        #endif
+                       sensor->info_priv.snap2preview = true;
+               } else if (sensor_fmt_videochk(sd,mf) == true) {                        /* ddl@rock-chips.com : Video */
+               #if CONFIG_SENSOR_Effect
+                       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+                       sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+        #endif
+        #if CONFIG_SENSOR_WhiteBalance
+                       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+                       sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+        #endif
+                       sensor->info_priv.video2preview = true;
+               } else if ((sensor->info_priv.snap2preview == true) || (sensor->info_priv.video2preview == true)) {
+               #if CONFIG_SENSOR_Effect
+                       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
+                       sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
+        #endif
+        #if CONFIG_SENSOR_WhiteBalance    
+                       qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_DO_WHITE_BALANCE);
+                       sensor_set_whiteBalance(icd, qctrl,sensor->info_priv.whiteBalance);
+        #endif    
+                       sensor->info_priv.video2preview = false;            
+                       sensor->info_priv.snap2preview = false;
+               }
+        SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),__FUNCTION__,set_w,set_h);
+    }
+    else
+    {
+        SENSOR_DG("\n %s .. Current Format is validate. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),set_w,set_h);
+    }
+
+       mf->width = set_w;
+    mf->height = set_h;
+
+sensor_s_fmt_end:
+    return ret;
+}
+
+static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+    struct i2c_client *client = sd->priv;
+    struct sensor *sensor = to_sensor(client);
+    const struct sensor_datafmt *fmt;
+    int ret = 0;
+   
+       fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,
+                                  ARRAY_SIZE(sensor_colour_fmts));
+       if (fmt == NULL) {
+               fmt = &sensor->info_priv.fmt;
+        mf->code = fmt->code;
+       } 
+
+    if (mf->height > SENSOR_MAX_HEIGHT)
+        mf->height = SENSOR_MAX_HEIGHT;
+    else if (mf->height < SENSOR_MIN_HEIGHT)
+        mf->height = SENSOR_MIN_HEIGHT;
+
+    if (mf->width > SENSOR_MAX_WIDTH)
+        mf->width = SENSOR_MAX_WIDTH;
+    else if (mf->width < SENSOR_MIN_WIDTH)
+        mf->width = SENSOR_MIN_WIDTH;
+
+    mf->colorspace = fmt->colorspace;
+    
+    return ret;
+}
+ static int sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id)
+{
+    struct i2c_client *client = sd->priv;
+
+    if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
+        return -EINVAL;
+
+    if (id->match.addr != client->addr)
+        return -ENODEV;
+
+    id->ident = SENSOR_V4L2_IDENT;      /* ddl@rock-chips.com :  Return OV2655  identifier */
+    id->revision = 0;
+
+    return 0;
+}
+#if CONFIG_SENSOR_Brightness
+static int sensor_set_brightness(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_BrightnessSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_BrightnessSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+       SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Effect
+static int sensor_set_effect(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_EffectSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_EffectSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+       SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Exposure
+static int sensor_set_exposure(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_ExposureSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_ExposureSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+       SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Saturation
+static int sensor_set_saturation(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_SaturationSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_SaturationSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+    SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Contrast
+static int sensor_set_contrast(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_ContrastSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_ContrastSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+    SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Mirror
+static int sensor_set_mirror(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_MirrorSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_MirrorSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+    SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flip
+static int sensor_set_flip(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_FlipSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_FlipSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+    SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Scene
+static int sensor_set_scene(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_SceneSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_SceneSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+    SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+static int sensor_set_whiteBalance(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum))
+    {
+        if (sensor_WhiteBalanceSeqe[value - qctrl->minimum] != NULL)
+        {
+            if (sensor_write_array(client, sensor_WhiteBalanceSeqe[value - qctrl->minimum]) != 0)
+            {
+                SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+                return -EINVAL;
+            }
+            SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+            return 0;
+        }
+    }
+       SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+static int sensor_set_digitalzoom(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int *value)
+{
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+    struct sensor *sensor = to_sensor(client);
+       const struct v4l2_queryctrl *qctrl_info;
+    int digitalzoom_cur, digitalzoom_total;
+
+       qctrl_info = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_ZOOM_ABSOLUTE);
+       if (qctrl_info)
+               return -EINVAL;
+
+    digitalzoom_cur = sensor->info_priv.digitalzoom;
+    digitalzoom_total = qctrl_info->maximum;
+
+    if ((*value > 0) && (digitalzoom_cur >= digitalzoom_total))
+    {
+        SENSOR_TR("%s digitalzoom is maximum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+        return -EINVAL;
+    }
+
+    if  ((*value < 0) && (digitalzoom_cur <= qctrl_info->minimum))
+    {
+        SENSOR_TR("%s digitalzoom is minimum - %x\n", SENSOR_NAME_STRING(), digitalzoom_cur);
+        return -EINVAL;
+    }
+
+    if ((*value > 0) && ((digitalzoom_cur + *value) > digitalzoom_total))
+    {
+        *value = digitalzoom_total - digitalzoom_cur;
+    }
+
+    if ((*value < 0) && ((digitalzoom_cur + *value) < 0))
+    {
+        *value = 0 - digitalzoom_cur;
+    }
+
+    digitalzoom_cur += *value;
+
+    if (sensor_ZoomSeqe[digitalzoom_cur] != NULL)
+    {
+        if (sensor_write_array(client, sensor_ZoomSeqe[digitalzoom_cur]) != 0)
+        {
+            SENSOR_TR("%s..%s WriteReg Fail.. \n",SENSOR_NAME_STRING(), __FUNCTION__);
+            return -EINVAL;
+        }
+        SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, *value);
+        return 0;
+    }
+
+    return -EINVAL;
+}
+#endif
+#if CONFIG_SENSOR_Flash
+static int sensor_set_flash(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+{    
+    if ((value >= qctrl->minimum) && (value <= qctrl->maximum)) {
+        if (value == 3) {       /* ddl@rock-chips.com: torch */
+            sensor_ioctrl(icd, Sensor_Flash, Flash_Torch);   /* Flash On */
+        } else {
+            sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+        }
+        SENSOR_DG("%s..%s : %x\n",SENSOR_NAME_STRING(),__FUNCTION__, value);
+        return 0;
+    }
+    
+       SENSOR_TR("\n %s..%s valure = %d is invalidate..    \n",SENSOR_NAME_STRING(),__FUNCTION__,value);
+    return -EINVAL;
+}
+#endif
+
+static int sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+    struct i2c_client *client = sd->priv;
+    struct sensor *sensor = to_sensor(client);
+    const struct v4l2_queryctrl *qctrl;
+
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+    if (!qctrl)
+    {
+        SENSOR_TR("\n %s ioctrl id = %d  is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+        return -EINVAL;
+    }
+
+    switch (ctrl->id)
+    {
+        case V4L2_CID_BRIGHTNESS:
+            {
+                ctrl->value = sensor->info_priv.brightness;
+                break;
+            }
+        case V4L2_CID_SATURATION:
+            {
+                ctrl->value = sensor->info_priv.saturation;
+                break;
+            }
+        case V4L2_CID_CONTRAST:
+            {
+                ctrl->value = sensor->info_priv.contrast;
+                break;
+            }
+        case V4L2_CID_DO_WHITE_BALANCE:
+            {
+                ctrl->value = sensor->info_priv.whiteBalance;
+                break;
+            }
+        case V4L2_CID_EXPOSURE:
+            {
+                ctrl->value = sensor->info_priv.exposure;
+                break;
+            }
+        case V4L2_CID_HFLIP:
+            {
+                ctrl->value = sensor->info_priv.mirror;
+                break;
+            }
+        case V4L2_CID_VFLIP:
+            {
+                ctrl->value = sensor->info_priv.flip;
+                break;
+            }
+        default :
+                break;
+    }
+    return 0;
+}
+
+
+
+static int sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+    struct i2c_client *client = sd->priv;
+    struct sensor *sensor = to_sensor(client);
+    struct soc_camera_device *icd = client->dev.platform_data;
+    const struct v4l2_queryctrl *qctrl;
+
+
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ctrl->id);
+
+    if (!qctrl)
+    {
+        SENSOR_TR("\n %s ioctrl id = %d  is invalidate \n", SENSOR_NAME_STRING(), ctrl->id);
+        return -EINVAL;
+    }
+
+    switch (ctrl->id)
+    {
+#if CONFIG_SENSOR_Brightness
+        case V4L2_CID_BRIGHTNESS:
+            {
+                if (ctrl->value != sensor->info_priv.brightness)
+                {
+                    if (sensor_set_brightness(icd, qctrl,ctrl->value) != 0)
+                    {
+                        return -EINVAL;
+                    }
+                    sensor->info_priv.brightness = ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Exposure
+        case V4L2_CID_EXPOSURE:
+            {
+                if (ctrl->value != sensor->info_priv.exposure)
+                {
+                    if (sensor_set_exposure(icd, qctrl,ctrl->value) != 0)
+                    {
+                        return -EINVAL;
+                    }
+                    sensor->info_priv.exposure = ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Saturation
+        case V4L2_CID_SATURATION:
+            {
+                if (ctrl->value != sensor->info_priv.saturation)
+                {
+                    if (sensor_set_saturation(icd, qctrl,ctrl->value) != 0)
+                    {
+                        return -EINVAL;
+                    }
+                    sensor->info_priv.saturation = ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Contrast
+        case V4L2_CID_CONTRAST:
+            {
+                if (ctrl->value != sensor->info_priv.contrast)
+                {
+                    if (sensor_set_contrast(icd, qctrl,ctrl->value) != 0)
+                    {
+                        return -EINVAL;
+                    }
+                    sensor->info_priv.contrast = ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_WhiteBalance
+        case V4L2_CID_DO_WHITE_BALANCE:
+            {
+                if (ctrl->value != sensor->info_priv.whiteBalance)
+                {
+                    if (sensor_set_whiteBalance(icd, qctrl,ctrl->value) != 0)
+                    {
+                        return -EINVAL;
+                    }
+                    sensor->info_priv.whiteBalance = ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Mirror
+        case V4L2_CID_HFLIP:
+            {
+                if (ctrl->value != sensor->info_priv.mirror)
+                {
+                    if (sensor_set_mirror(icd, qctrl,ctrl->value) != 0)
+                        return -EINVAL;
+                    sensor->info_priv.mirror = ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Flip
+        case V4L2_CID_VFLIP:
+            {
+                if (ctrl->value != sensor->info_priv.flip)
+                {
+                    if (sensor_set_flip(icd, qctrl,ctrl->value) != 0)
+                        return -EINVAL;
+                    sensor->info_priv.flip = ctrl->value;
+                }
+                break;
+            }
+#endif
+        default:
+            break;
+    }
+
+    return 0;
+}
+static int sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl)
+{
+    const struct v4l2_queryctrl *qctrl;
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+    struct sensor *sensor = to_sensor(client);
+
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+    if (!qctrl)
+    {
+        SENSOR_TR("\n %s ioctrl id = %d  is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+        return -EINVAL;
+    }
+
+    switch (ext_ctrl->id)
+    {
+        case V4L2_CID_SCENE:
+            {
+                ext_ctrl->value = sensor->info_priv.scene;
+                break;
+            }
+        case V4L2_CID_EFFECT:
+            {
+                ext_ctrl->value = sensor->info_priv.effect;
+                break;
+            }
+        case V4L2_CID_ZOOM_ABSOLUTE:
+            {
+                ext_ctrl->value = sensor->info_priv.digitalzoom;
+                break;
+            }
+        case V4L2_CID_ZOOM_RELATIVE:
+            {
+                return -EINVAL;
+            }
+        case V4L2_CID_FOCUS_ABSOLUTE:
+            {
+                ext_ctrl->value = sensor->info_priv.focus;
+                break;
+            }
+        case V4L2_CID_FOCUS_RELATIVE:
+            {
+                return -EINVAL;
+            }
+        case V4L2_CID_FLASH:
+            {
+                ext_ctrl->value = sensor->info_priv.flash;
+                break;
+            }
+        default :
+            break;
+    }
+    return 0;
+}
+static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl)
+{
+    const struct v4l2_queryctrl *qctrl;
+    struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
+    struct sensor *sensor = to_sensor(client);
+    int val_offset;
+
+    qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
+
+    if (!qctrl)
+    {
+        SENSOR_TR("\n %s ioctrl id = %d  is invalidate \n", SENSOR_NAME_STRING(), ext_ctrl->id);
+        return -EINVAL;
+    }
+
+       val_offset = 0;
+    switch (ext_ctrl->id)
+    {
+#if CONFIG_SENSOR_Scene
+        case V4L2_CID_SCENE:
+            {
+                if (ext_ctrl->value != sensor->info_priv.scene)
+                {
+                    if (sensor_set_scene(icd, qctrl,ext_ctrl->value) != 0)
+                        return -EINVAL;
+                    sensor->info_priv.scene = ext_ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Effect
+        case V4L2_CID_EFFECT:
+            {
+                if (ext_ctrl->value != sensor->info_priv.effect)
+                {
+                    if (sensor_set_effect(icd, qctrl,ext_ctrl->value) != 0)
+                        return -EINVAL;
+                    sensor->info_priv.effect= ext_ctrl->value;
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_DigitalZoom
+        case V4L2_CID_ZOOM_ABSOLUTE:
+            {
+                if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+                    return -EINVAL;
+
+                if (ext_ctrl->value != sensor->info_priv.digitalzoom)
+                {
+                    val_offset = ext_ctrl->value -sensor->info_priv.digitalzoom;
+
+                    if (sensor_set_digitalzoom(icd, qctrl,&val_offset) != 0)
+                        return -EINVAL;
+                    sensor->info_priv.digitalzoom += val_offset;
+
+                    SENSOR_DG("%s digitalzoom is %x\n",SENSOR_NAME_STRING(),  sensor->info_priv.digitalzoom);
+                }
+
+                break;
+            }
+        case V4L2_CID_ZOOM_RELATIVE:
+            {
+                if (ext_ctrl->value)
+                {
+                    if (sensor_set_digitalzoom(icd, qctrl,&ext_ctrl->value) != 0)
+                        return -EINVAL;
+                    sensor->info_priv.digitalzoom += ext_ctrl->value;
+
+                    SENSOR_DG("%s digitalzoom is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.digitalzoom);
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Focus
+        case V4L2_CID_FOCUS_ABSOLUTE:
+            {
+                if ((ext_ctrl->value < qctrl->minimum) || (ext_ctrl->value > qctrl->maximum))
+                    return -EINVAL;
+
+                if (ext_ctrl->value != sensor->info_priv.focus)
+                {
+                    val_offset = ext_ctrl->value -sensor->info_priv.focus;
+
+                    sensor->info_priv.focus += val_offset;
+                }
+
+                break;
+            }
+        case V4L2_CID_FOCUS_RELATIVE:
+            {
+                if (ext_ctrl->value)
+                {
+                    sensor->info_priv.focus += ext_ctrl->value;
+
+                    SENSOR_DG("%s focus is %x\n", SENSOR_NAME_STRING(), sensor->info_priv.focus);
+                }
+                break;
+            }
+#endif
+#if CONFIG_SENSOR_Flash
+        case V4L2_CID_FLASH:
+            {
+                if (sensor_set_flash(icd, qctrl,ext_ctrl->value) != 0)
+                    return -EINVAL;
+                sensor->info_priv.flash = ext_ctrl->value;
+
+                SENSOR_DG("%s flash is %x\n",SENSOR_NAME_STRING(), sensor->info_priv.flash);
+                break;
+            }
+#endif
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+static int sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+    struct i2c_client *client = sd->priv;
+    struct soc_camera_device *icd = client->dev.platform_data;
+    int i, error_cnt=0, error_idx=-1;
+
+
+    for (i=0; i<ext_ctrl->count; i++) {
+        if (sensor_g_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+            error_cnt++;
+            error_idx = i;
+        }
+    }
+
+    if (error_cnt > 1)
+        error_idx = ext_ctrl->count;
+
+    if (error_idx != -1) {
+        ext_ctrl->error_idx = error_idx;
+        return -EINVAL;
+    } else {
+        return 0;
+    }
+}
+
+static int sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl)
+{
+    struct i2c_client *client = sd->priv;
+    struct soc_camera_device *icd = client->dev.platform_data;
+    int i, error_cnt=0, error_idx=-1;
+
+
+    for (i=0; i<ext_ctrl->count; i++) {
+        if (sensor_s_ext_control(icd, &ext_ctrl->controls[i]) != 0) {
+            error_cnt++;
+            error_idx = i;
+        }
+    }
+
+    if (error_cnt > 1)
+        error_idx = ext_ctrl->count;
+
+    if (error_idx != -1) {
+        ext_ctrl->error_idx = error_idx;
+        return -EINVAL;
+    } else {
+        return 0;
+    }
+}
+
+/* Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one */
+static int sensor_video_probe(struct soc_camera_device *icd,
+                              struct i2c_client *client)
+{
+    char value;
+    int ret,pid = 0;
+    struct sensor *sensor = to_sensor(client);
+
+    /* We must have a parent by now. And it cannot be a wrong one.
+     * So this entire test is completely redundant. */
+    if (!icd->dev.parent ||
+           to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
+               return -ENODEV;
+
+       if (sensor_ioctrl(icd, Sensor_PowerDown, 0) < 0) {
+               ret = -ENODEV;
+               goto sensor_video_probe_err;
+       }
+
+    /* soft reset */
+    ret = sensor_write(client, 0xff, 0x1);
+    if (ret != 0) {
+        SENSOR_TR("soft reset %s failed\n",SENSOR_NAME_STRING());
+        ret = -ENODEV;
+               goto sensor_video_probe_err;
+    }
+    mdelay(5);          //delay 5 microseconds
+
+    /* check if it is an sensor sensor */
+    ret = sensor_read(client, 0x0a, &value);
+    if (ret != 0) {
+        SENSOR_TR("read chip id high byte failed\n");
+        ret = -ENODEV;
+        goto sensor_video_probe_err;
+    }
+    pid = value << 8;
+
+    ret = sensor_read(client, 0x0b, &value);
+    if (ret != 0) {
+        SENSOR_TR("read chip id low byte failed\n");
+        ret = -ENODEV;
+        goto sensor_video_probe_err;
+    }
+
+    pid |= (value & 0xff);
+    SENSOR_DG("\n %s  pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+
+    if ((pid == SENSOR_ID)||(pid == SENSOR_ID1)) {
+        sensor->model = SENSOR_V4L2_IDENT;
+    } else {
+        SENSOR_TR("error: %s mismatched   pid = 0x%x\n", SENSOR_NAME_STRING(), pid);
+        ret = -ENODEV;
+        goto sensor_video_probe_err;
+    }
+
+    return 0;
+
+sensor_video_probe_err:
+
+    return ret;
+}
+
+static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+       struct i2c_client *client = sd->priv;
+    struct soc_camera_device *icd = client->dev.platform_data;  
+    struct sensor *sensor = to_sensor(client);
+    int ret = 0;
+    
+       SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+       switch (cmd)
+       {
+               case RK29_CAM_SUBDEV_DEACTIVATE:
+               {
+                       sensor_deactivate(client);
+                       break;
+               }
+
+               case RK29_CAM_SUBDEV_IOREQUEST:
+               {
+                       sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;           
+            if (sensor->sensor_io_request != NULL) { 
+                if (sensor->sensor_io_request->gpio_res[0].dev_name && 
+                    (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
+                    sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
+                } else if (sensor->sensor_io_request->gpio_res[1].dev_name && 
+                    (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
+                    sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+                }
+            } else {
+                SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
+                ret = -EINVAL;
+                goto sensor_ioctl_end;
+            }
+            /* ddl@rock-chips.com : if gpio_flash havn't been set in board-xxx.c, sensor driver must notify is not support flash control 
+               for this project */
+            #if CONFIG_SENSOR_Flash    
+               if (sensor->sensor_gpio_res) { 
+                if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
+                    for (i = 0; i < icd->ops->num_controls; i++) {
+                               if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
+                                       memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));                                       
+                               }
+                    }
+                    sensor->info_priv.flash = 0xff;
+                    SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+                }
+               }
+            #endif
+                       break;
+               }
+               default:
+               {
+                       SENSOR_TR("%s %s cmd(0x%x) is unknown !\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+                       break;
+               }
+       }
+
+sensor_ioctl_end:
+       return ret;
+
+}
+static int sensor_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+                           enum v4l2_mbus_pixelcode *code)
+{
+       if (index >= ARRAY_SIZE(sensor_colour_fmts))
+               return -EINVAL;
+
+       *code = sensor_colour_fmts[index].code;
+       return 0;
+}
+static struct v4l2_subdev_core_ops sensor_subdev_core_ops = {
+       .init           = sensor_init,
+       .g_ctrl         = sensor_g_control,
+       .s_ctrl         = sensor_s_control,
+       .g_ext_ctrls          = sensor_g_ext_controls,
+       .s_ext_ctrls          = sensor_s_ext_controls,
+       .g_chip_ident   = sensor_g_chip_ident,
+       .ioctl = sensor_ioctl,
+};
+
+static struct v4l2_subdev_video_ops sensor_subdev_video_ops = {
+       .s_mbus_fmt     = sensor_s_fmt,
+       .g_mbus_fmt     = sensor_g_fmt,
+       .try_mbus_fmt   = sensor_try_fmt,
+       .enum_mbus_fmt  = sensor_enum_fmt,
+};
+
+static struct v4l2_subdev_ops sensor_subdev_ops = {
+       .core   = &sensor_subdev_core_ops,
+       .video = &sensor_subdev_video_ops,
+};
+
+static int sensor_probe(struct i2c_client *client,
+                        const struct i2c_device_id *did)
+{
+    struct sensor *sensor;
+    struct soc_camera_device *icd = client->dev.platform_data;
+    struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+    struct soc_camera_link *icl;
+    int ret;
+
+    SENSOR_DG("\n%s..%s..%d..\n",__FUNCTION__,__FILE__,__LINE__);
+    if (!icd) {
+        dev_err(&client->dev, "%s: missing soc-camera data!\n",SENSOR_NAME_STRING());
+        return -EINVAL;
+    }
+
+    icl = to_soc_camera_link(icd);
+    if (!icl) {
+        dev_err(&client->dev, "%s driver needs platform data\n", SENSOR_NAME_STRING());
+        return -EINVAL;
+    }
+
+    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+        dev_warn(&adapter->dev,
+                "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
+        return -EIO;
+    }
+
+    sensor = kzalloc(sizeof(struct sensor), GFP_KERNEL);
+    if (!sensor)
+        return -ENOMEM;
+
+    v4l2_i2c_subdev_init(&sensor->subdev, client, &sensor_subdev_ops);
+
+    /* Second stage probe - when a capture adapter is there */
+    icd->ops           = &sensor_ops;
+    sensor->info_priv.fmt = sensor_colour_fmts[0];
+       #if CONFIG_SENSOR_I2C_NOSCHED
+       atomic_set(&sensor->tasklock_cnt,0);
+       #endif
+
+    ret = sensor_video_probe(icd, client);
+    if (ret < 0) {
+        icd->ops = NULL;
+        i2c_set_clientdata(client, NULL);
+        kfree(sensor);
+               sensor = NULL;
+    }
+    SENSOR_DG("\n%s..%s..%d  ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
+    return ret;
+}
+
+static int sensor_remove(struct i2c_client *client)
+{
+    struct sensor *sensor = to_sensor(client);
+    struct soc_camera_device *icd = client->dev.platform_data;
+
+    icd->ops = NULL;
+    i2c_set_clientdata(client, NULL);
+    client->driver = NULL;
+    kfree(sensor);
+       sensor = NULL;
+    return 0;
+}
+
+static const struct i2c_device_id sensor_id[] = {
+       {SENSOR_NAME_STRING(), 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, sensor_id);
+
+static struct i2c_driver sensor_i2c_driver = {
+       .driver = {
+               .name = SENSOR_NAME_STRING(),
+       },
+       .probe          = sensor_probe,
+       .remove         = sensor_remove,
+       .id_table       = sensor_id,
+};
+
+static int __init sensor_mod_init(void)
+{
+    SENSOR_DG("\n%s..%s.. \n",__FUNCTION__,SENSOR_NAME_STRING());
+    return i2c_add_driver(&sensor_i2c_driver);
+}
+
+static void __exit sensor_mod_exit(void)
+{
+    i2c_del_driver(&sensor_i2c_driver);
+}
+
+device_initcall_sync(sensor_mod_init);
+module_exit(sensor_mod_exit);
+
+MODULE_DESCRIPTION(SENSOR_NAME_STRING(Camera sensor driver));
+MODULE_AUTHOR("ddl <kernel@rock-chips>");
+MODULE_LICENSE("GPL");
+
+
+>>>>>>> parent of 15f7fab... temp revert rk change
index 4e4d4122d9a60339175486b999a8576b25565c09..372bd75bc4b340f201651d026b3c8e46c398127d 100644 (file)
@@ -484,6 +484,7 @@ static int soc_camera_open(struct file *file)
                                        icd->current_fmt->host_fmt->fourcc,
                        },
                };
+<<<<<<< HEAD
 
                ret = soc_camera_power_set(icd, icl, 1);
                if (ret < 0)
@@ -492,6 +493,20 @@ static int soc_camera_open(struct file *file)
                /* The camera could have been already on, try to reset */
                if (icl->reset)
                        icl->reset(icd->pdev);
+=======
+        /* ddl@rock-chips.com : accelerate device open  */
+        if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+               if (icl->power) {
+                       ret = icl->power(icd->pdev, 1);
+                       if (ret < 0)
+                               goto epower;
+               }
+
+               /* The camera could have been already on, try to reset */
+               if (icl->reset)
+                       icl->reset(icd->pdev);
+       }
+>>>>>>> parent of 15f7fab... temp revert rk change
 
                ret = ici->ops->add(icd);
                if (ret < 0) {
@@ -504,6 +519,7 @@ static int soc_camera_open(struct file *file)
                if (ret < 0 && ret != -ENOSYS)
                        goto eresume;
 
+        if ((file->f_flags & O_ACCMODE) == O_RDWR) {
                /*
                 * Try to configure with default parameters. Notice: this is the
                 * very first open, so, we cannot race against other calls,
@@ -513,6 +529,7 @@ static int soc_camera_open(struct file *file)
                ret = soc_camera_set_fmt(icd, &f);
                if (ret < 0)
                        goto esfmt;
+<<<<<<< HEAD
 
                if (ici->ops->init_videobuf) {
                        ici->ops->init_videobuf(&icd->vb_vidq, icd);
@@ -521,6 +538,9 @@ static int soc_camera_open(struct file *file)
                        if (ret < 0)
                                goto einitvb;
                }
+=======
+        }
+>>>>>>> parent of 15f7fab... temp revert rk change
        }
 
        file->private_data = icd;
@@ -562,7 +582,14 @@ static int soc_camera_close(struct file *file)
                if (ici->ops->init_videobuf2)
                        vb2_queue_release(&icd->vb2_vidq);
 
+<<<<<<< HEAD
                soc_camera_power_set(icd, icl, 0);
+=======
+        if ((file->f_flags & O_ACCMODE) == O_RDWR) {
+               if (icl->power)
+                       icl->power(icd->pdev, 0);
+        }
+>>>>>>> parent of 15f7fab... temp revert rk change
        }
 
        if (icd->streamer == file)
@@ -653,8 +680,14 @@ static struct v4l2_file_operations soc_camera_fops = {
 static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
                                    struct v4l2_format *f)
 {
+<<<<<<< HEAD
        struct soc_camera_device *icd = file->private_data;
        int ret;
+=======
+       struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       int ret,i;
+>>>>>>> parent of 15f7fab... temp revert rk change
 
        WARN_ON(priv != file->private_data);
 
@@ -666,10 +699,31 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
        if (icd->streamer && icd->streamer != file)
                return -EBUSY;
 
+<<<<<<< HEAD
        if (is_streaming(to_soc_camera_host(icd->dev.parent), icd)) {
+=======
+       #if 1
+       if (icf->vb_vidq.bufs[0]) {
+>>>>>>> parent of 15f7fab... temp revert rk change
                dev_err(&icd->dev, "S_FMT denied: queue initialised\n");
                return -EBUSY;
        }
+       #else
+
+       /* ddl@rock-chips.com :
+            Judge queue  initialised by Judge icf->vb_vidq.bufs[0] whether is NULL , it is error.    */
+
+       i = 0;
+       while (icf->vb_vidq.bufs[i] && (i<VIDEO_MAX_FRAME)) {
+               if (icf->vb_vidq.bufs[i]->state != VIDEOBUF_NEEDS_INIT) {
+                       dev_err(&icd->dev, "S_FMT denied: queue initialised, icf->vb_vidq.bufs[%d]->state:0x%x\n",i,icf->vb_vidq.bufs[i]->state);
+                       ret = -EBUSY;
+                       goto unlock;
+               }
+               i++;
+       }
+
+       #endif
 
        ret = soc_camera_set_fmt(icd, f);
 
@@ -678,7 +732,27 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
 
        return ret;
 }
+static int soc_camera_enum_frameintervals (struct file *file, void  *priv,
+                                          struct v4l2_frmivalenum *fival)
+{
+    struct soc_camera_file *icf = file->private_data;
+       struct soc_camera_device *icd = icf->icd;
+       const struct soc_camera_data_format *format;
+    struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+    struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+    int ret;
+    
+       WARN_ON(priv != file->private_data);
 
+    ret = v4l2_subdev_call(sd, video, enum_frameintervals, fival);
+    if (ret == -ENOIOCTLCMD) 
+        if (ici->ops->enum_frameinervals)
+           ret = ici->ops->enum_frameinervals(icd, fival); 
+        else 
+           ret = -ENOIOCTLCMD;
+
+    return ret;
+}
 static int soc_camera_enum_fmt_vid_cap(struct file *file, void  *priv,
                                       struct v4l2_fmtdesc *f)
 {
@@ -739,6 +813,8 @@ static int soc_camera_streamon(struct file *file, void *priv,
        struct soc_camera_device *icd = file->private_data;
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       struct soc_camera_host *ici =
+                    to_soc_camera_host(icd->dev.parent);
        int ret;
 
        WARN_ON(priv != file->private_data);
@@ -746,9 +822,17 @@ static int soc_camera_streamon(struct file *file, void *priv,
        if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
+<<<<<<< HEAD
        if (icd->streamer != file)
                return -EBUSY;
 
+=======
+       mutex_lock(&icd->video_lock);
+
+       v4l2_subdev_call(sd, video, s_stream, 1);
+    if (ici->ops->s_stream)
+           ici->ops->s_stream(icd, 1);                         /* ddl@rock-chips.com : Add stream control for host */
+>>>>>>> parent of 15f7fab... temp revert rk change
        /* This calls buf_queue from host driver's videobuf_queue_ops */
        if (ici->ops->init_videobuf)
                ret = videobuf_streamon(&icd->vb_vidq);
@@ -766,15 +850,25 @@ static int soc_camera_streamoff(struct file *file, void *priv,
 {
        struct soc_camera_device *icd = file->private_data;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+<<<<<<< HEAD
        struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+=======
+    struct soc_camera_host *ici =
+                    to_soc_camera_host(icd->dev.parent);
+>>>>>>> parent of 15f7fab... temp revert rk change
 
        WARN_ON(priv != file->private_data);
 
        if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
+<<<<<<< HEAD
 
        if (icd->streamer != file)
                return -EBUSY;
+=======
+    
+       mutex_lock(&icd->video_lock);
+>>>>>>> parent of 15f7fab... temp revert rk change
 
        /*
         * This calls buf_release from host driver's videobuf_queue_ops for all
@@ -786,7 +880,15 @@ static int soc_camera_streamoff(struct file *file, void *priv,
                vb2_streamoff(&icd->vb2_vidq, i);
 
        v4l2_subdev_call(sd, video, s_stream, 0);
+    if (ici->ops->s_stream)
+               ici->ops->s_stream(icd, 0);                             /* ddl@rock-chips.com : Add stream control for host */
 
+<<<<<<< HEAD
+=======
+    videobuf_mmap_free(&icf->vb_vidq);          /* ddl@rock-chips.com : free video buf */
+       mutex_unlock(&icd->video_lock);
+
+>>>>>>> parent of 15f7fab... temp revert rk change
        return 0;
 }
 
@@ -821,6 +923,40 @@ static int soc_camera_queryctrl(struct file *file, void *priv,
        return -EINVAL;
 }
 
+/* ddl@rock-chips.com : Add ioctrl -VIDIOC_QUERYMENU */
+static int soc_camera_querymenu(struct file *file, void *priv,
+                                struct v4l2_querymenu *qm)
+{
+    struct soc_camera_file *icf = file->private_data;
+    struct soc_camera_device *icd = icf->icd;
+    struct v4l2_queryctrl qctrl;
+    int i,j;
+
+    qctrl.id = qm->id;
+
+    if (soc_camera_queryctrl(file,priv, &qctrl) == 0) {
+        for (i = 0; i < icd->ops->num_menus; i++) {
+            if (qm->id == icd->ops->menus[i].id) {
+                for (j=0; j<=(qctrl.maximum - qctrl.minimum); j++) {
+
+                    if (qm->index == icd->ops->menus[i].index) {
+                        snprintf(qm->name, sizeof(qm->name), icd->ops->menus[i].name);
+                        qm->reserved = 0;
+
+                        return 0;
+                    } else {
+                        i++;
+                        if ( i >= icd->ops->num_menus)
+                            return -EINVAL;
+                    }
+                }
+            }
+        }
+    }
+
+    return -EINVAL;
+}
+
 static int soc_camera_g_ctrl(struct file *file, void *priv,
                             struct v4l2_control *ctrl)
 {
@@ -859,6 +995,64 @@ static int soc_camera_s_ctrl(struct file *file, void *priv,
        return v4l2_subdev_call(sd, core, s_ctrl, ctrl);
 }
 
+
+ /* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
+static int soc_camera_try_ext_ctrl(struct file *file, void *priv,
+                             struct v4l2_ext_controls *ctrl)
+{
+    struct soc_camera_file *icf = file->private_data;
+    struct soc_camera_device *icd = icf->icd;
+    const struct v4l2_queryctrl *qctrl;
+    int i;
+
+    WARN_ON(priv != file->private_data);
+
+    if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
+        return -EINVAL;
+
+    for (i=0; i<ctrl->count; i++) {
+        qctrl = soc_camera_find_qctrl(icd->ops, ctrl->controls[i].id);
+        if (!qctrl)
+            return -EINVAL;
+
+        if ((ctrl->controls[i].value < qctrl->minimum) ||(ctrl->controls[i].value > qctrl->minimum))
+            return -ERANGE;
+    }
+
+    return 0;
+}
+ /* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
+static int soc_camera_g_ext_ctrl(struct file *file, void *priv,
+                             struct v4l2_ext_controls *ctrl)
+{
+    struct soc_camera_file *icf = file->private_data;
+    struct soc_camera_device *icd = icf->icd;
+    struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+
+    WARN_ON(priv != file->private_data);
+
+    if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
+        return -EINVAL;
+
+    return v4l2_subdev_call(sd, core, g_ext_ctrls, ctrl);
+}
+ /* ddl@rock-chips.com : Add ioctrl -VIDIOC_XXX_ext_ctrl for soc-camera */
+static int soc_camera_s_ext_ctrl(struct file *file, void *priv,
+                             struct v4l2_ext_controls *ctrl)
+{
+    struct soc_camera_file *icf = file->private_data;
+    struct soc_camera_device *icd = icf->icd;
+    struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+
+    WARN_ON(priv != file->private_data);
+
+    if (ctrl->ctrl_class != V4L2_CTRL_CLASS_CAMERA)
+        return -EINVAL;
+
+    return v4l2_subdev_call(sd, core, s_ext_ctrls, ctrl);
+}
+
+
 static int soc_camera_cropcap(struct file *file, void *fh,
                              struct v4l2_cropcap *a)
 {
@@ -1471,8 +1665,13 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
        .vidioc_streamon         = soc_camera_streamon,
        .vidioc_streamoff        = soc_camera_streamoff,
        .vidioc_queryctrl        = soc_camera_queryctrl,
+        .vidioc_querymenu       = soc_camera_querymenu,     /* ddl@rock-chips.com:   Add ioctrl - vidioc_querymenu for soc-camera */
        .vidioc_g_ctrl           = soc_camera_g_ctrl,
        .vidioc_s_ctrl           = soc_camera_s_ctrl,
+       .vidioc_g_ext_ctrls    = soc_camera_g_ext_ctrl,   /* ddl@rock-chips.com:   Add ioctrl - vidioc_g_ext_ctrls for soc-camera */
+       .vidioc_s_ext_ctrls    = soc_camera_s_ext_ctrl,   /* ddl@rock-chips.com:   Add ioctrl - vidioc_s_ext_ctrls for soc-camera */
+       .vidioc_try_ext_ctrls    = soc_camera_try_ext_ctrl,/* ddl@rock-chips.com:   Add ioctrl - vidioc_try_ext_ctrls for soc-camera */
+    .vidioc_enum_frameintervals = soc_camera_enum_frameintervals,/* ddl@rock-chips.com:   Add ioctrl - VIDIOC_ENUM_FRAMEINTERVALS for soc-camera */
        .vidioc_cropcap          = soc_camera_cropcap,
        .vidioc_g_crop           = soc_camera_g_crop,
        .vidioc_s_crop           = soc_camera_s_crop,
index 543a80395b7f57d2c122049a7d8e69fc27a50901..82dc041d99a84dd094bf00df988799ee07478fe0 100644 (file)
@@ -295,8 +295,10 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
        struct uvc_frame *frame;
        int ret;
 
-       if (fmt->type != stream->type)
+       if (fmt->type != stream->type) {
+        printk("uvc_v4l2_set_format, fmt->type(%d) != stream->type(%d)\n",fmt->type,stream->type);
                return -EINVAL;
+       }
 
        ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
        if (ret < 0)
@@ -305,6 +307,7 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
        mutex_lock(&stream->mutex);
 
        if (uvc_queue_allocated(&stream->queue)) {
+        printk("uvc_queue_allocated failed\n");
                ret = -EBUSY;
                goto done;
        }
@@ -799,8 +802,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_S_FMT:
-               if ((ret = uvc_acquire_privileges(handle)) < 0)
+               if ((ret = uvc_acquire_privileges(handle)) < 0) {
+            printk("uvc_acquire_privileges error.");
                        return ret;
+               }
 
                return uvc_v4l2_set_format(stream, arg);
 
@@ -974,14 +979,18 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_QBUF:
-               if (!uvc_has_privileges(handle))
+               if (!uvc_has_privileges(handle)) {
+            printk("uvcvideo: VIDIOC_QBUF uvc_has_privileges failed\n");
                        return -EBUSY;
+               }
 
                return uvc_queue_buffer(&stream->queue, arg);
 
        case VIDIOC_DQBUF:
-               if (!uvc_has_privileges(handle))
+               if (!uvc_has_privileges(handle)) {
+            printk("uvcvideo: VIDIOC_DQBUF uvc_has_privileges failed\n");
                        return -EBUSY;
+               }
 
                return uvc_dequeue_buffer(&stream->queue, arg,
                        file->f_flags & O_NONBLOCK);
index 69e8c6ffcc49b8b64700c8049acaf0b172d25350..5ea5514c94ff8f07284a553638854b49d0664b32 100644 (file)
@@ -821,10 +821,10 @@ static long __video_do_ioctl(struct file *file,
        case VIDIOC_S_FMT:
        {
                struct v4l2_format *f = (struct v4l2_format *)arg;
-
+               
                /* FIXME: Should be one dump per type */
                dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
-
+               
                switch (f->type) {
                case V4L2_BUF_TYPE_VIDEO_CAPTURE:
                        CLEAR_AFTER_FIELD(f, fmt.pix);
index 6ca938a6bf94d336ddbfd830c02bc4739436ffc9..b91fe3180fd6165a08d7e748b58034c4455cc4c9 100755 (executable)
@@ -385,6 +385,17 @@ config MFD_WM831X_SPI
          for accessing the device, additional drivers must be enabled in
          order to use the functionality of the device.
 
+config MFD_WM831X_SPI_A22
+       bool "Support Wolfson Microelectronics WM831x/2x PMICs with SPI for A22"
+       #select MFD_CORE
+       #select MFD_WM831X
+       depends on SPI_MASTER && GENERIC_HARDIRQS
+       help
+         Support for the Wolfson Microelecronics WM831x and WM832x PMICs
+         when controlled using SPI.  This driver provides common support
+         for accessing the device, additional drivers must be enabled in
+         order to use the functionality of the device.
+
 config MFD_WM8350
        bool
        depends on GENERIC_HARDIRQS
index d7d47d2a4c7615c17d4aec23080692f2b603dda7..670e4c0fca6301b7f30c1b123d24fff721db794f 100755 (executable)
@@ -26,6 +26,7 @@ wm831x-objs                   := wm831x-core.o wm831x-irq.o wm831x-otp.o
 obj-$(CONFIG_MFD_WM831X)       += wm831x.o
 obj-$(CONFIG_MFD_WM831X_I2C)   += wm831x-i2c.o
 obj-$(CONFIG_MFD_WM831X_SPI)   += wm831x-spi.o
+obj-$(CONFIG_MFD_WM831X_SPI_A22)       += wm831x-spi-a22.o
 wm8350-objs                    := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
 wm8350-objs                    += wm8350-irq.o
 obj-$(CONFIG_MFD_WM8350)       += wm8350.o
diff --git a/drivers/mfd/tps65910-core.c b/drivers/mfd/tps65910-core.c
deleted file mode 100644 (file)
index 01c6439..0000000
+++ /dev/null
@@ -1,801 +0,0 @@
-/*
- * tps65910-core.c -- Multifunction core driver for  TPS65910x chips
- *
- * Copyright (C) 2010 Mistral solutions Pvt Ltd <www.mistralsolutions.com>
- *
- * Based on twl-core.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <linux/regulator/machine.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c/tps65910.h>
-#include <mach/board.h>
-#include <mach/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#if 0
-#define DBG(x...)      printk(KERN_INFO x)
-#else
-#define DBG(x...)
-#endif
-#define TPS65910_SPEED         400 * 1000
-
-
-#define DRIVER_NAME                    "tps659102"
-
-#if defined(CONFIG_GPIO_TPS65910)
-#define tps65910_has_gpio()            true
-#else
-#define tps65910_has_gpio()            false
-#endif
-
-#if defined(CONFIG_REGULATOR_TPS65910)
-#define tps65910_has_regulator()       true
-#else
-#define tps65910_has_regulator()       false
-#endif
-
-#if defined(CONFIG_RTC_DRV_TPS65910)
-#define tps65910_has_rtc()             true
-#else
-#define tps65910_has_rtc()             false
-#endif
-
-#define TPS65910_GENERAL                       0
-#define TPS65910_SMARTREFLEX           1
-
-
-struct tps65910_platform_data *gtps65910_platform = NULL;
-
-enum tps65910x_model {
-       TPS65910,       /* TI processors OMAP3 family */
-       TPS659101,      /* Samsung - S5PV210, S5PC1xx */
-       TPS659102,      /* Samsung - S3C64xx */
-       TPS659103,      /* Reserved */
-       TPS659104,      /* Reserved */
-       TPS659105,      /* TI processors - DM643x, DM644x */
-       TPS659106,      /* Reserved */
-       TPS659107,      /* Reserved */
-       TPS659108,      /* Reserved */
-       TPS659109,      /* Freescale - i.MX51 */
-
-};
-
-static bool inuse;
-static struct work_struct core_work;
-static struct mutex work_lock;
-
-/* Structure for each TPS65910 Slave */
-struct tps65910_client {
-       struct i2c_client *client;
-       u8 address;
-       /* max numb of i2c_msg required for read = 2 */
-       struct i2c_msg xfer_msg[2];
-       /* To lock access to xfer_msg */
-       struct mutex xfer_lock;
-};
-static struct tps65910_client tps65910_modules[TPS65910_NUM_SLAVES];
-
-/* bbch = Back-up battery charger control register */
-int tps65910_enable_bbch(u8 voltage)
-{
-       u8 val = 0;
-       int err;
-
-       if (voltage == TPS65910_BBSEL_3P0 || voltage == TPS65910_BBSEL_2P52 ||
-                       voltage == TPS65910_BBSEL_3P15 ||
-                       voltage == TPS65910_BBSEL_VBAT) {
-               val = (voltage | TPS65910_BBCHEN);
-               err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val,
-                               TPS65910_REG_BBCH);
-               if (err) {
-                       printk(KERN_ERR "Unable write TPS65910_REG_BBCH reg\n");
-                       return -EIO;
-               }
-       } else {
-               printk(KERN_ERR"Invalid argumnet for %s \n", __func__);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(tps65910_enable_bbch);
-
-int tps65910_disable_bbch(void)
-{
-       u8 val = 0;
-       int err;
-
-       err = tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_BBCH);
-
-       if (!err) {
-               val &= ~TPS65910_BBCHEN;
-
-               err = tps65910_i2c_write_u8(TPS65910_I2C_ID0, val,
-                               TPS65910_REG_BBCH);
-               if (err) {
-                       printk(KERN_ERR "Unable write TPS65910_REG_BBCH \
-                                       reg\n");
-                       return -EIO;
-               }
-       } else {
-               printk(KERN_ERR "Unable to read TPS65910_REG_BBCH reg\n");
-               return -EIO;
-       }
-       return 0;
-}
-EXPORT_SYMBOL(tps65910_disable_bbch);
-
-int tps65910_i2c_read_u8(u8 mod_no, u8 *value, u8 reg)
-{
-       struct tps65910_client *tps65910;
-       int ret;
-       
-       switch (mod_no) {
-       case TPS65910_I2C_ID0:
-               tps65910 = &tps65910_modules[0];
-               tps65910->address = TPS65910_I2C_ID0;
-               break;
-       case TPS65910_I2C_ID1:
-               tps65910 = &tps65910_modules[1];
-               tps65910->address = TPS65910_I2C_ID1;
-               break;
-       default:
-               printk(KERN_ERR "Invalid Slave address for TPS65910\n");
-               return -ENODEV;
-       }
-       
-       ret = i2c_master_reg8_recv(tps65910->client, reg, (char *)value, 1, TPS65910_SPEED);
-       DBG("%s: ret=%d, slave_addr=0x%x, reg=0x%x, value=0x%x\n", __FUNCTION__, (ret > 0 ? 0: -EINVAL), mod_no, reg, *value);
-
-       return (ret > 0 ? 0: -EINVAL);
-}
-EXPORT_SYMBOL(tps65910_i2c_read_u8);
-
-int tps65910_i2c_write_u8(u8 slave_addr, u8 value, u8 reg)
-{
-       struct tps65910_client *tps65910;
-       int ret;
-
-       switch (slave_addr) {
-       case TPS65910_I2C_ID0:
-               tps65910 = &tps65910_modules[0];
-               tps65910->address = TPS65910_I2C_ID0;
-               break;
-       case TPS65910_I2C_ID1:
-               tps65910 = &tps65910_modules[1];
-               tps65910->address = TPS65910_I2C_ID1;
-               break;
-       default:
-               printk(KERN_ERR "Invalid Slave address for TPS65910\n");
-               return -ENODEV;
-       }
-
-       ret = i2c_master_reg8_send(tps65910->client, reg, (char *)&value, 1, TPS65910_SPEED);
-       DBG("%s: ret=%d, slave_addr=0x%x, reg=0x%x, value=0x%x\n", __FUNCTION__, ret, slave_addr, reg, value);
-
-       if (ret < 0)
-               return -EIO;
-       else
-               return 0;
-}
-EXPORT_SYMBOL(tps65910_i2c_write_u8);
-
-
-int tps65910_enable_irq(int irq)
-{
-       u8  mask = 0x00;
-
-       if (irq > 7) {
-               irq -= 8;
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0,
-                               &mask, TPS65910_REG_INT_MSK2);
-               mask &= ~(1 << irq);
-               return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
-                               mask, TPS65910_REG_INT_MSK2);
-       } else {
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0,
-                               &mask, TPS65910_REG_INT_MSK);
-               mask &= ~(1 << irq);
-               return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
-                               mask, TPS65910_REG_INT_MSK);
-       }
-}
-EXPORT_SYMBOL(tps65910_enable_irq);
-
-int tps65910_disable_irq(int irq)
-{
-       u8  mask = 0x00;
-
-       if (irq > 7) {
-               irq -= 8;
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0,
-                               &mask, TPS65910_REG_INT_MSK2);
-               mask |= (1 << irq);
-               return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
-                               mask, TPS65910_REG_INT_MSK2);
-       } else {
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0,
-                               &mask, TPS65910_REG_INT_MSK);
-               mask = (1 << irq);
-               return tps65910_i2c_write_u8(TPS65910_I2C_ID0,
-                               mask, TPS65910_REG_INT_MSK);
-       }
-}
-EXPORT_SYMBOL(tps65910_disable_irq);
-
-int tps65910_add_irq_work(int irq,
-               void (*handler)(void *data))
-{
-       int ret = 0;
-       gtps65910_platform->handlers[irq] = handler;
-       ret = tps65910_enable_irq(irq);
-
-       return ret;
-}
-EXPORT_SYMBOL(tps65910_add_irq_work);
-
-int tps65910_remove_irq_work(int irq)
-{
-       int ret = 0;
-       ret = tps65910_disable_irq(irq);
-       gtps65910_platform->handlers[irq] = NULL;
-       return ret;
-}
-EXPORT_SYMBOL(tps65910_remove_irq_work);
-
-static void tps65910_core_work(struct work_struct *work)
-{
-       /* Read the status register and take action  */
-       u8      status = 0x00;
-       u8      status2 = 0x00;
-       u8      mask = 0x00;
-       u8      mask2 = 0x00;
-       u16 isr = 0x00;
-       u16 irq = 0;
-       void    (*handler)(void *data) = NULL;
-
-       DBG("Enter::%s %d\n",__FUNCTION__,__LINE__);
-       mutex_lock(&work_lock);
-       while (1) {
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0, &status2,
-                               TPS65910_REG_INT_STS2);
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0, &mask2,
-                               TPS65910_REG_INT_MSK2);
-               status2 &= (~mask2);
-               isr = (status2 << 8);
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0, &status,
-                               TPS65910_REG_INT_STS);
-               tps65910_i2c_read_u8(TPS65910_I2C_ID0, &mask,
-                               TPS65910_REG_INT_MSK);
-               status &= ~(mask);
-               isr |= status;
-               if (!isr)
-                       break;
-
-               while (isr) {
-                       irq = fls(isr) - 1;
-                       isr &= ~(1 << irq);
-                       handler = gtps65910_platform->handlers[irq];
-                       if (handler)
-                               handler(gtps65910_platform);
-               }
-       }
-       enable_irq(gtps65910_platform->irq_num);
-       mutex_unlock(&work_lock);
-}
-
-
-static irqreturn_t tps65910_isr(int irq,  void *data)
-{
-       disable_irq_nosync(irq);
-       (void) schedule_work(&core_work);
-       return IRQ_HANDLED;
-}
-
-
-static struct device *add_numbered_child(unsigned chip, const char *name,
-       int num, void *pdata, unsigned pdata_len, bool can_wakeup, int irq)
-{
-
-       struct platform_device  *pdev;
-       struct tps65910_client  *tps65910 = &tps65910_modules[chip];
-       int  status;
-
-       pdev = platform_device_alloc(name, num);
-       if (!pdev) {
-               dev_dbg(&tps65910->client->dev, "can't alloc dev\n");
-               status = -ENOMEM;
-               goto err;
-       }
-       device_init_wakeup(&pdev->dev, can_wakeup);
-       pdev->dev.parent = &tps65910->client->dev;
-
-       if (pdata) {
-               status = platform_device_add_data(pdev, pdata, pdata_len);
-               if (status < 0) {
-                       dev_dbg(&pdev->dev, "can't add platform_data\n");
-                       goto err;
-               }
-       }
-       status = platform_device_add(pdev);
-
-err:
-       if (status < 0) {
-               platform_device_put(pdev);
-               dev_err(&tps65910->client->dev, "can't add %s dev\n", name);
-               return ERR_PTR(status);
-       }
-       return &pdev->dev;
-
-}
-
-static inline struct device *add_child(unsigned chip, const char *name,
-               void *pdata, unsigned pdata_len,
-               bool can_wakeup, int irq)
-{
-       return add_numbered_child(chip, name, -1, pdata, pdata_len,
-                       can_wakeup, irq);
-}
-
-static
-struct device *add_regulator_linked(int num, struct regulator_init_data *pdata,
-               struct regulator_consumer_supply *consumers,
-               unsigned num_consumers)
-{
-       /* regulator framework demands init_data */
-       if (!pdata)
-               return NULL;
-
-       if (consumers) {
-               pdata->consumer_supplies = consumers;
-               pdata->num_consumer_supplies = num_consumers;
-       }
-       
-       return add_numbered_child(TPS65910_GENERAL, "tps65910_regulator", num,
-                       pdata, sizeof(*pdata), false, TPS65910_HOST_IRQ);
-}
-
-       static struct device *
-add_regulator(int num, struct regulator_init_data *pdata)
-{
-       return add_regulator_linked(num, pdata, NULL, 0);
-}
-
-static int
-add_children(struct tps65910_platform_data *pdata, unsigned long features)
-{
-       int             status;
-       struct device   *child;
-
-       struct platform_device  *pdev = NULL;
-
-       DBG("cwz add_children: tps65910 add children.\n");
-
-       if (tps65910_has_gpio() && (pdata->gpio != NULL)) {
-
-               pdev = platform_device_alloc("tps65910_gpio", -1);
-               if (!pdev) {
-                       status = -ENOMEM;
-                       goto err;
-               }
-               pdev->dev.parent = &tps65910_modules[0].client->dev;
-               device_init_wakeup(&pdev->dev, 0);
-               if (pdata) {
-                       status = platform_device_add_data(pdev, pdata,
-                                                       sizeof(*pdata));
-                       if (status < 0) {
-                               dev_dbg(&pdev->dev,
-                               "can't add platform_data\n");
-                               goto err;
-                       }
-               }
-       }
-       if (tps65910_has_rtc()) {
-               child = add_child(TPS65910_GENERAL, "tps65910_rtc",
-                               NULL, 0, true, pdata->irq_num);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-       }
-
-       if (tps65910_has_regulator()) {
-               child = add_regulator(TPS65910_VIO, pdata->vio);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VDD1, pdata->vdd1);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VDD2, pdata->vdd2);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VDD3, pdata->vdd3);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VDIG1, pdata->vdig1);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VDIG2, pdata->vdig2);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VAUX33, pdata->vaux33);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VMMC, pdata->vmmc);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VAUX1, pdata->vaux1);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VAUX2, pdata->vaux2);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VDAC, pdata->vdac);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-
-               child = add_regulator(TPS65910_VPLL, pdata->vpll);
-               if (IS_ERR(child))
-                       return PTR_ERR(child);
-       }
-       
-       return 0;
-err:
-       return -1;
-}
-
-static int tps65910_remove(struct i2c_client *client)
-{
-       unsigned i;
-
-       for (i = 0; i < TPS65910_NUM_SLAVES; i++) {
-
-               struct tps65910_client *tps65910 = &tps65910_modules[i];
-
-               if (tps65910->client && tps65910->client != client)
-                       i2c_unregister_device(tps65910->client);
-
-               tps65910_modules[i].client = NULL;
-       }
-       inuse = false;
-       return 0;
-}
-
-static int __init
-tps65910_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
-       int      status;
-       unsigned i;
-       struct tps65910_platform_data   *pdata;
-       pdata = client->dev.platform_data;
-       gtps65910_platform = pdata;
-
-       DBG("cwz: tps65910_i2c_probe\n");
-       
-       if (!pdata) {
-               dev_dbg(&client->dev, "no platform data?\n");
-               return -EINVAL;
-       }
-
-       if (!i2c_check_functionality(client->adapter,I2C_FUNC_I2C)) {
-               dev_dbg(&client->dev, "can't talk I2C?\n");
-               return -EIO;
-       }
-
-       if (inuse) {
-               dev_dbg(&client->dev, "driver is already in use\n");
-               return -EBUSY;
-       } 
-       for (i = 0; i < TPS65910_NUM_SLAVES; i++) {
-
-               struct tps65910_client  *tps65910 = &tps65910_modules[i];
-
-               tps65910->address = client->addr;
-
-               if (i == 0)
-                       tps65910->client = client;
-               else {
-                       tps65910->client = i2c_new_dummy(client->adapter,
-                                       tps65910->address);
-
-                       if (!tps65910->client) {
-                               dev_err(&client->dev,
-                                               "can't attach client %d\n", i);
-                               status = -ENOMEM;
-                               goto fail;
-                       }
-               }
-               mutex_init(&tps65910->xfer_lock);
-       } 
-
-       inuse = true;
-
-       if (pdata->board_tps65910_config != NULL)
-               pdata->board_tps65910_config(pdata);
-
-       if (pdata->irq_num) {
-               /* TPS65910 power ON interrupt(s) would have already been
-                * occurred, so immediately after request_irq the control will
-                * be transferred to tps65910_isr, if we do core_work
-                * initialization after requesting IRQ, the system crashes
-                * and does not boot; to avoid this we do core_work
-                * initialization before requesting IRQ
-                */
-               mutex_init(&work_lock);
-
-               if(gpio_request(client->irq, "tps65910 irq"))
-               {
-                       dev_err(&client->dev, "gpio request fail\n");
-                       gpio_free(client->irq);
-                       goto fail;
-               }
-               
-               pdata->irq_num = gpio_to_irq(client->irq);
-               gpio_pull_updown(client->irq,GPIOPullUp);
-
-               status = request_irq(pdata->irq_num, tps65910_isr,
-                                       IRQF_TRIGGER_FALLING, client->dev.driver->name, pdata);
-               if (status < 0) {
-                       pr_err("tps65910: could not claim irq%d: %d\n",
-                                       pdata->irq_num, status);
-                       goto fail;
-               }
-               enable_irq_wake(pdata->irq_num);
-               INIT_WORK(&core_work, tps65910_core_work);
-       }
-
-       status = add_children(pdata, 0x00);
-       if (status < 0)
-               goto fail;
-
-       return 0;
-
-fail:
-       if (status < 0)
-               tps65910_remove(client);
-
-       return status;
-}
-
-
-static int tps65910_i2c_remove(struct i2c_client *client)
-{
-       unsigned i;
-
-       for (i = 0; i < TPS65910_NUM_SLAVES; i++) {
-
-               struct tps65910_client  *tps65910 = &tps65910_modules[i];
-
-               if (tps65910->client && tps65910->client != client)
-                       i2c_unregister_device(tps65910->client);
-
-               tps65910_modules[i].client = NULL;
-       }
-       inuse = false;
-       return 0;
-}
-
-/* chip-specific feature flags, for i2c_device_id.driver_data */
-static const struct i2c_device_id tps65910_i2c_ids[] = {
-       { "tps65910", TPS65910 },
-       { "tps659101", TPS659101 },
-       { "tps659102", TPS659102 },
-       { "tps659103", TPS659103 },
-       { "tps659104", TPS659104 },
-       { "tps659105", TPS659105 },
-       { "tps659106", TPS659106 },
-       { "tps659107", TPS659107 },
-       { "tps659108", TPS659108 },
-       { "tps659109", TPS659109 },
-       {/* end of list */ },
-};
-MODULE_DEVICE_TABLE(i2c, tps65910_i2c_ids);
-
-/* One Client Driver ,3 Clients - Regulator, RTC , GPIO */
-static struct i2c_driver tps65910_i2c_driver = {
-       .driver         = {
-               .name   = DRIVER_NAME,
-               .owner  = THIS_MODULE,
-       },
-       .id_table       = tps65910_i2c_ids,
-       .probe          = tps65910_i2c_probe,
-       .remove         = __devexit_p(tps65910_i2c_remove),
-};
-
-static int __init tps65910_init(void)
-{
-       int res;
-
-       res = i2c_add_driver(&tps65910_i2c_driver);
-       if (res < 0) {
-               pr_err(DRIVER_NAME ": driver registration failed\n");
-               return res;
-       }
-
-       return 0;
-}
-subsys_initcall_sync(tps65910_init);
-
-static void __exit tps65910_exit(void)
-{
-       i2c_del_driver(&tps65910_i2c_driver);
-}
-module_exit(tps65910_exit);
-
-
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static int proc_tps65910_show(struct seq_file *s, void *v)
-{
-    u8 val = 0;
-       
-       seq_printf(s, "\n\nTPS65910 Registers is:\n");
-
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_REF);
-       seq_printf(s, "REF_REG=0x%x, Value=0x%x\n", TPS65910_REG_REF, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VRTC);
-       seq_printf(s, "VRTC_REG=0x%x, Value=0x%x\n", TPS65910_REG_VRTC, val);
-       
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD1);
-       seq_printf(s, "VDD1_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD1, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD1_OP);
-       seq_printf(s, "VDD1_OP_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD1_OP, val);
-
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD2);
-       seq_printf(s, "VDD2_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD2, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDD2_OP);
-       seq_printf(s, "VDD2_OP_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDD2_OP, val);
-
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VIO);
-       seq_printf(s, "VIO_REG=0x%x, Value=0x%x\n", TPS65910_REG_VIO, val);
-
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDIG1);
-       seq_printf(s, "VDIG1_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDIG1, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDIG2);
-       seq_printf(s, "VDIG2_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDIG2, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VAUX1);
-       seq_printf(s, "VAUX1_REG=0x%x, Value=0x%x\n", TPS65910_REG_VAUX1, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VAUX2);
-       seq_printf(s, "VAUX2_REG=0x%x, Value=0x%x\n", TPS65910_REG_VAUX2, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VAUX33);
-       seq_printf(s, "VAUX33_REG=0x%x, Value=0x%x\n", TPS65910_REG_VAUX33, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VMMC);
-       seq_printf(s, "VMMC_REG=0x%x, Value=0x%x\n", TPS65910_REG_VMMC, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VPLL);
-       seq_printf(s, "VPLL_REG=0x%x, Value=0x%x\n", TPS65910_REG_VPLL, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_VDAC);
-       seq_printf(s, "VDAC_REG=0x%x, Value=0x%x\n", TPS65910_REG_VDAC, val);
-
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL);
-       seq_printf(s, "DEVCTRL_REG=0x%x, Value=0x%x\n", TPS65910_REG_DEVCTRL, val);
-       tps65910_i2c_read_u8(TPS65910_I2C_ID0, &val, TPS65910_REG_DEVCTRL2);
-       seq_printf(s, "DEVCTRL2_REG=0x%x, Value=0x%x\n", TPS65910_REG_DEVCTRL2, val);
-
-#if 0  //      cwz 1 test vcore
-{
-    struct regulator *vldo;
-       
-       vldo = regulator_get(NULL, "vcore");
-       if (!IS_ERR(vldo))
-       {
-               int uV = 0;
-#if 0          
-               seq_printf(s, "Set VCORE.\n");
-               regulator_set_voltage(vldo,1350000,1350000);
-#endif
-               uV = regulator_get_voltage(vldo);
-               seq_printf(s, "Get VCORE=%d(uV).\n", uV);
-       }
-}
-#endif
-
-#if 0
-{
-    struct regulator *vldo;
-
-#if 1
-       vldo = regulator_get(NULL, "vaux1");
-       if (!IS_ERR(vldo))
-       {               
-               seq_printf(s, "Disable VAUX1.\n");
-               regulator_disable(vldo);
-       }
-#endif
-
-#if 1
-       vldo = regulator_get(NULL, "vdig1");
-       if (!IS_ERR(vldo))
-       {               
-               seq_printf(s, "Disable VDIG1.\n");
-               regulator_disable(vldo);
-       }
-
-       vldo = regulator_get(NULL, "vdig2");
-       if (!IS_ERR(vldo))
-       {               
-               seq_printf(s, "Disable VDIG2.\n");
-               regulator_disable(vldo);
-       }
-#endif
-
-#if 0  //      fih board is for hdmi
-       vldo = regulator_get(NULL, "vdac");
-       if (!IS_ERR(vldo))
-       {               
-               seq_printf(s, "Disable VDAC.\n");
-               regulator_disable(vldo);
-       }
-#endif
-
-#if 1
-       vldo = regulator_get(NULL, "vaux2");
-       if (!IS_ERR(vldo))
-       {               
-               seq_printf(s, "Disable VAUX2.\n");
-               regulator_disable(vldo);
-       }
-#endif
-}
-#endif
-
-       return 0;
-}
-
-static int proc_tps65910_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_tps65910_show, NULL);
-}
-
-static const struct file_operations proc_tps65910_fops = {
-       .open           = proc_tps65910_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-static int __init proc_tps65910_init(void)
-{
-       proc_create("tps65910", 0, NULL, &proc_tps65910_fops);
-       return 0;
-}
-late_initcall(proc_tps65910_init);
-#endif /* CONFIG_PROC_FS */
-
-MODULE_AUTHOR("cwz <cwz@rock-chips.com>");
-MODULE_DESCRIPTION("I2C Core interface for TPS65910");
-MODULE_LICENSE("GPL");
index 265f75fc6a25f404a60d0954f2228585bb149938..11a390a02e28605f722def7c80224f9376cd9bee 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
 #include <linux/mfd/wm831x/auxadc.h>
 #include <linux/mfd/wm831x/otp.h>
 #include <linux/mfd/wm831x/regulator.h>
+#include <linux/mfd/wm831x/pmu.h>
+
 
 /* Current settings - values are 2*2^(reg_val/4) microamps.  These are
  * exported since they are used by multiple drivers.
  */
+ extern int reboot_cmd_get(void);
 int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {
        2,
        2,
@@ -383,7 +387,7 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
                 * the notification of the interrupt may be delayed by
                 * threaded IRQ handling. */
                if (!wait_for_completion_timeout(&wm831x->auxadc_done,
-                                                msecs_to_jiffies(500))) {
+                                                msecs_to_jiffies(2000))) {
                        dev_err(wm831x->dev, "Timed out waiting for AUXADC\n");
                        ret = -EBUSY;
                        goto disable;
@@ -997,6 +1001,20 @@ static struct mfd_cell wm8310_devs[] = {
                .num_resources = ARRAY_SIZE(wm831x_wdt_resources),
                .resources = wm831x_wdt_resources,
        },
+#if defined(CONFIG_KEYBOARD_WM831X_GPIO)
+       {
+               .name           = "wm831x_gpio-keys",
+               .num_resources  = 0,
+       },
+#endif
+#if defined(CONFIG_WM831X_CHARGER_DISPLAY)
+       {
+               .name           = "wm831x_charger_display",
+               .num_resources  = 0,
+       },
+#endif
+
+
 };
 
 static struct mfd_cell wm8311_devs[] = {
@@ -1455,11 +1473,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
                goto err;
        }
-       switch (ret) {
-       case 0x6204:
-       case 0x6246:
-               break;
-       default:
+       if (ret != 0x6204) {
                dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
                ret = -EINVAL;
                goto err;
@@ -1489,12 +1503,15 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        switch (ret) {
        case WM8310:
                parent = WM8310;
-               wm831x->num_gpio = 16;
+               wm831x->num_gpio = 12;
                wm831x->charger_irq_wake = 1;
                if (rev > 0) {
                        wm831x->has_gpio_ena = 1;
                        wm831x->has_cs_sts = 1;
                }
+               //ILIM = 900ma
+               ret = wm831x_reg_read(wm831x, WM831X_POWER_STATE) & 0xffff;
+               wm831x_reg_write(wm831x, WM831X_POWER_STATE, (ret&0xfff8) | 0x04);      
 
                dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
                break;
@@ -1541,12 +1558,15 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
                break;
 
+<<<<<<< HEAD
        case WM8326:
                parent = WM8326;
                wm831x->num_gpio = 12;
                dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
                break;
 
+=======
+>>>>>>> parent of 15f7fab... temp revert rk change
        default:
                dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
                ret = -EINVAL;
@@ -1632,7 +1652,13 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        case WM8326:
                ret = mfd_add_devices(wm831x->dev, -1,
                                      wm8320_devs, ARRAY_SIZE(wm8320_devs),
-                                     NULL, wm831x->irq_base);
+                                     NULL, 0);
+               break;
+
+       case WM8325:
+               ret = mfd_add_devices(wm831x->dev, -1,
+                                     wm8320_devs, ARRAY_SIZE(wm8320_devs),
+                                     NULL, 0);
                break;
 
        default:
@@ -1658,7 +1684,11 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        wm831x_otp_init(wm831x);
 
        if (pdata && pdata->post_init) {
+               wm831x_reg_unlock(wm831x);
+               wm831x_set_bits(wm831x, WM831X_RESET_CONTROL,0x0010,0x0000);
+               wm831x_set_bits(wm831x, WM831X_LDO_ENABLE,0Xf800,0Xf800);
                ret = pdata->post_init(wm831x);
+               wm831x_reg_lock(wm831x);
                if (ret != 0) {
                        dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
                        goto err_irq;
@@ -1688,6 +1718,22 @@ void wm831x_device_exit(struct wm831x *wm831x)
 int wm831x_device_suspend(struct wm831x *wm831x)
 {
        int reg, mask;
+       int i;
+       
+       //mask some intterupt avoid wakeing up system while suspending
+       for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
+               /* If there's been a change in the mask write it back
+                * to the hardware. */
+               //printk("irq_masks_cur[%d]=0x%x\n",i,wm831x->irq_masks_cur[i]);
+
+               if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
+                       wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
+                       wm831x_reg_write(wm831x,
+                                        WM831X_INTERRUPT_STATUS_1_MASK + i,
+                                        wm831x->irq_masks_cur[i]);
+               }
+       
+       }
 
        /* If the charger IRQs are a wake source then make sure we ack
         * them even if they're not actively being used (eg, no power
@@ -1720,6 +1766,102 @@ int wm831x_device_suspend(struct wm831x *wm831x)
 
        return 0;
 }
+<<<<<<< HEAD
+=======
+void wm831x_enter_sleep(void){
+#if 1//def CONFIG_RK2818_SOC_PM
+       struct regulator *dcdc;
+       int i;          
+       dcdc=regulator_get(NULL, "dcdc1");
+       struct wm831x_dcdc *dc = regulator_get_drvdata(dcdc);
+       struct wm831x *wm831x = dc->wm831x;
+       if(wm831x){
+               wm831x_set_bits(wm831x, WM831X_POWER_STATE, 0x4000, 0x4000); // SYSTEM SLEEP MODE
+               for (i=0; i<5; i++)
+                       wm831x_reg_write(wm831x,WM831X_INTERRUPT_STATUS_1+i, 0xffff);  // INTRUPT FLAG CLEAR 
+                       
+               printk("%s:complete! \n",__func__);
+               
+       }else{
+               printk("%s:error!",__func__);
+       }
+       regulator_put(dcdc);
+#endif 
+}
+EXPORT_SYMBOL_GPL(wm831x_enter_sleep);
+
+void wm831x_exit_sleep(void){
+#if 1//def CONFIG_RK2818_SOC_PM
+       struct regulator *dcdc;
+       dcdc=regulator_get(NULL, "dcdc1");
+       struct wm831x_dcdc *dc = regulator_get_drvdata(dcdc);
+       struct wm831x *wm831x = dc->wm831x;
+       if(wm831x){
+               wm831x_set_bits(wm831x, WM831X_POWER_STATE, 0x4000, 0);  // SYSTEM ON MODE
+               printk("%s:complete! \n",__func__);
+               
+       }else{
+               printk("%s:error!",__func__);
+       }
+       regulator_put(dcdc);
+#endif 
+}
+EXPORT_SYMBOL_GPL(wm831x_exit_sleep);
+
+int wm831x_device_shutdown(struct wm831x *wm831x)
+{
+       struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+       int ret = 0;
+       
+       printk("pre WM831X_POWER_STATE = 0x%x\n", wm831x_reg_read(wm831x, WM831X_POWER_STATE));
+
+       if (pdata && pdata->last_deinit) {
+               ret = pdata->last_deinit(wm831x);
+               if (ret != 0) {
+                       dev_info(wm831x->dev, "last_deinit() failed: %d\n", ret);
+                       //goto err_irq;
+               }
+       }
+
+       //if(0 == reboot_cmd_get())
+       {
+               if(wm831x_set_bits(wm831x, WM831X_POWER_STATE, WM831X_CHIP_ON_MASK, 0) < 0)
+                       printk("%s wm831x_set_bits err\n", __FUNCTION__);
+               //printk("post WM831X_POWER_STATE = 0x%x\n", wm831x_reg_read(wm831x, WM831X_POWER_STATE));
+       }
+
+       return 0;       
+}
+
+EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
+
+
+int wm831x_read_usb(struct wm831x *wm831x)
+{
+       int ret, usb_chg = 0, wall_chg = 0;
+       
+       ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS);
+       if (ret < 0)
+               return ret;
+
+       if (ret & WM831X_PWR_USB)
+               usb_chg = 1;
+       if (ret & WM831X_PWR_WALL)
+               wall_chg = 1;
+
+       return ((usb_chg | wall_chg) ? 1 : 0);
+
+}
+
+
+int wm831x_device_restart(struct wm831x *wm831x)
+{
+       wm831x_reg_write(wm831x,WM831X_RESET_ID, 0xffff); 
+
+       return 0;
+}
+
+>>>>>>> parent of 15f7fab... temp revert rk change
 
 MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
 MODULE_LICENSE("GPL");
index a06cbc739716c25c57ae872f90c2ba9cc6fa506d..a905baf527bb822c6df7d77f9e97fc2d38f02b3e 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/mfd/core.h>
 #include <linux/slab.h>
+#include <linux/gpio.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
@@ -51,6 +52,7 @@ static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
                                   int bytes, void *src)
 {
        struct i2c_client *i2c = wm831x->control_data;
+<<<<<<< HEAD
        struct i2c_msg xfer[2];
        int ret;
 
@@ -70,6 +72,19 @@ static int wm831x_i2c_write_device(struct wm831x *wm831x, unsigned short reg,
        if (ret < 0)
                return ret;
        if (ret != 2)
+=======
+       unsigned char msg[bytes + 2];
+       int ret;
+
+       reg = cpu_to_be16(reg);
+       memcpy(&msg[0], &reg, 2);
+       memcpy(&msg[2], src, bytes);
+
+       ret = i2c_master_send(i2c, msg, bytes + 2);
+       if (ret < 0)
+               return ret;
+       if (ret < bytes + 2)
+>>>>>>> parent of 15f7fab... temp revert rk change
                return -EIO;
 
        return 0;
@@ -79,18 +94,44 @@ static int wm831x_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct wm831x *wm831x;
+<<<<<<< HEAD
+
+=======
+       int ret,gpio,irq;
 
+>>>>>>> parent of 15f7fab... temp revert rk change
        wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
        if (wm831x == NULL)
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm831x);
+<<<<<<< HEAD
+=======
+       
+       gpio = i2c->irq;
+       ret = gpio_request(gpio, "wm831x");
+       if (ret) {
+               printk( "failed to request rk gpio irq for wm831x \n");
+               return ret;
+       }
+       gpio_pull_updown(gpio, GPIOPullUp);
+       if (ret) {
+           printk("failed to pull up gpio irq for wm831x \n");
+               return ret;
+       }       
+       irq = gpio_to_irq(gpio);
+       
+>>>>>>> parent of 15f7fab... temp revert rk change
        wm831x->dev = &i2c->dev;
        wm831x->control_data = i2c;
        wm831x->read_dev = wm831x_i2c_read_device;
        wm831x->write_dev = wm831x_i2c_write_device;
 
+<<<<<<< HEAD
        return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
+=======
+       return wm831x_device_init(wm831x, id->driver_data, irq);
+>>>>>>> parent of 15f7fab... temp revert rk change
 }
 
 static int wm831x_i2c_remove(struct i2c_client *i2c)
@@ -109,6 +150,33 @@ static int wm831x_i2c_suspend(struct device *dev)
        return wm831x_device_suspend(wm831x);
 }
 
+static int wm831x_i2c_resume(struct device *dev)
+{
+       struct wm831x *wm831x = dev_get_drvdata(dev);
+       int i;
+       //set some intterupt again while resume 
+       for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
+               //printk("irq_masks_cur[%d]=0x%x\n",i,wm831x->irq_masks_cur[i]);
+
+               if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
+                       wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
+                       wm831x_reg_write(wm831x,
+                                        WM831X_INTERRUPT_STATUS_1_MASK + i,
+                                        wm831x->irq_masks_cur[i]);
+               }
+       
+       }
+
+       return 0;
+}
+
+void wm831x_i2c_shutdown(struct i2c_client *i2c)
+{
+       struct wm831x *wm831x = i2c_get_clientdata(i2c);
+       printk("%s\n", __FUNCTION__);
+       wm831x_device_shutdown(wm831x);
+}
+
 static const struct i2c_device_id wm831x_i2c_id[] = {
        { "wm8310", WM8310 },
        { "wm8311", WM8311 },
@@ -123,6 +191,7 @@ MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
 
 static const struct dev_pm_ops wm831x_pm_ops = {
        .suspend = wm831x_i2c_suspend,
+       .resume = wm831x_i2c_resume,
 };
 
 static struct i2c_driver wm831x_i2c_driver = {
@@ -133,6 +202,7 @@ static struct i2c_driver wm831x_i2c_driver = {
        },
        .probe = wm831x_i2c_probe,
        .remove = wm831x_i2c_remove,
+       .shutdown = wm831x_i2c_shutdown,
        .id_table = wm831x_i2c_id,
 };
 
@@ -140,6 +210,7 @@ static int __init wm831x_i2c_init(void)
 {
        int ret;
 
+       printk("%s \n", __FUNCTION__);
        ret = i2c_add_driver(&wm831x_i2c_driver);
        if (ret != 0)
                pr_err("Failed to register wm831x I2C driver: %d\n", ret);
index 42b928ec891e6b4b2a60a6323ed5d6265659e978..5baffaaef70fa338181298f4f18bcc70988f55af 100755 (executable)
 #include <linux/mfd/wm831x/irq.h>
 
 #include <linux/delay.h>
+<<<<<<< HEAD
+=======
+#include <linux/wakelock.h>
+/*
+ * Since generic IRQs don't currently support interrupt controllers on
+ * interrupt driven buses we don't use genirq but instead provide an
+ * interface that looks very much like the standard ones.  This leads
+ * to some bodges, including storing interrupt handler information in
+ * the static irq_data table we use to look up the data for individual
+ * interrupts, but hopefully won't last too long.
+ */
+#define WM831X_IRQ_TYPE IRQF_TRIGGER_LOW
+>>>>>>> parent of 15f7fab... temp revert rk change
 
 struct wm831x_irq_data {
        int primary;
@@ -32,6 +45,12 @@ struct wm831x_irq_data {
        int mask;
 };
 
+struct wm831x_handle_irq
+{      
+       int irq;
+       struct list_head        queue;
+};
+
 static struct wm831x_irq_data wm831x_irqs[] = {
        [WM831X_IRQ_TEMP_THW] = {
                .primary = WM831X_TEMP_INT,
@@ -373,6 +392,7 @@ static void wm831x_irq_enable(struct irq_data *data)
                                                             data->irq);
 
        wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
+       //printk("%s:irq=%d\n",__FUNCTION__,irq);
 }
 
 static void wm831x_irq_disable(struct irq_data *data)
@@ -382,6 +402,16 @@ static void wm831x_irq_disable(struct irq_data *data)
                                                             data->irq);
 
        wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
+       //printk("%s:irq=%d\n",__FUNCTION__,irq);
+}
+
+static void wm831x_irq_disable(unsigned int irq)
+{
+       struct wm831x *wm831x = get_irq_chip_data(irq);
+       struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, irq);
+
+       wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
+       //printk("%s:irq=%d\n",__FUNCTION__,irq);
 }
 
 static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
@@ -389,16 +419,21 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
        struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
        int val, irq;
 
+<<<<<<< HEAD
        irq = data->irq - wm831x->irq_base;
 
        if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
+=======
+       irq = irq - wm831x->irq_base;
+       if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_12) {
+>>>>>>> parent of 15f7fab... temp revert rk change
                /* Ignore internal-only IRQs */
                if (irq >= 0 && irq < WM831X_NUM_IRQS)
                        return 0;
                else
                        return -EINVAL;
        }
-
+       //printk("wm831x_irq_set_type:type=%x,irq=%d\n",type,irq);
        switch (type) {
        case IRQ_TYPE_EDGE_BOTH:
                val = WM831X_GPN_INT_MODE;
@@ -413,29 +448,106 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
                return -EINVAL;
        }
 
-       return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq,
+       return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq - 1,
                               WM831X_GPN_INT_MODE | WM831X_GPN_POL, val);
 }
 
+static int wm831x_irq_set_wake(unsigned irq, unsigned state)
+{      
+       struct wm831x *wm831x = get_irq_chip_data(irq); 
+
+       //only wm831x irq
+       if ((irq > wm831x->irq_base + WM831X_IRQ_TEMP_THW) &&( irq < wm831x->irq_base + WM831X_NUM_IRQS)) 
+       {
+               if(state)
+               wm831x_irq_unmask(irq); 
+               else    
+               wm831x_irq_mask(irq);
+               return 0;
+       }
+       else
+       {
+               printk("%s:irq number err!irq=%d\n",__FUNCTION__,irq);
+               return -EINVAL;
+       }
+
+
+}
+
 static struct irq_chip wm831x_irq_chip = {
+<<<<<<< HEAD
        .name                   = "wm831x",
        .irq_bus_lock           = wm831x_irq_lock,
        .irq_bus_sync_unlock    = wm831x_irq_sync_unlock,
        .irq_disable            = wm831x_irq_disable,
        .irq_enable             = wm831x_irq_enable,
        .irq_set_type           = wm831x_irq_set_type,
+=======
+       .name = "wm831x",
+       .bus_lock = wm831x_irq_lock,
+       .bus_sync_unlock = wm831x_irq_sync_unlock,
+       .disable = wm831x_irq_disable,
+       .mask = wm831x_irq_mask,
+       .unmask = wm831x_irq_unmask,
+       .set_type = wm831x_irq_set_type,
+       .set_wake       = wm831x_irq_set_wake,
+>>>>>>> parent of 15f7fab... temp revert rk change
 };
 
-/* The processing of the primary interrupt occurs in a thread so that
- * we can interact with the device over I2C or SPI. */
-static irqreturn_t wm831x_irq_thread(int irq, void *data)
+#if WM831X_IRQ_LIST
+static void wm831x_handle_worker(struct work_struct *work)
 {
-       struct wm831x *wm831x = data;
+       struct wm831x *wm831x = container_of(work, struct wm831x, handle_work);
+       int irq;
+
+       while (1) {
+               unsigned long flags;
+               struct wm831x_handle_irq *hd = NULL;
+
+               spin_lock_irqsave(&wm831x->work_lock, flags);
+               if (!list_empty(&wm831x->handle_queue)) {
+                       hd = list_first_entry(&wm831x->handle_queue, struct wm831x_handle_irq, queue);
+                       list_del(&hd->queue);
+               }
+               spin_unlock_irqrestore(&wm831x->work_lock, flags);
+
+               if (!hd)        // trans_queue empty
+                       break;
+
+               irq = hd->irq;  //get wm831x intterupt status
+               //printk("%s:irq=%d\n",__FUNCTION__,irq);
+               
+               /*start to handle wm831x intterupt*/
+               handle_nested_irq(wm831x->irq_base + irq);
+       
+               kfree(hd);
+
+       }
+}
+#endif
+/* Main interrupt handling occurs in a workqueue since we need
+ * interrupts enabled to interact with the chip. */
+static void wm831x_irq_worker(struct work_struct *work)
+{
+       struct wm831x *wm831x = container_of(work, struct wm831x, irq_work);
        unsigned int i;
        int primary;
        int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
        int read[WM831X_NUM_IRQ_REGS] = { 0 };
        int *status;
+       unsigned long flags;
+       struct wm831x_handle_irq *hd;
+       int ret;
+
+#if (WM831X_IRQ_TYPE != IRQF_TRIGGER_LOW)
+       /*mask wm831x irq at first*/
+       ret = wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG,
+                             WM831X_IRQ_IM_MASK, WM831X_IRQ_IM_EANBLE);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to mask irq: %d\n", ret);
+               goto out;
+       }
+#endif
 
        primary = wm831x_reg_read(wm831x, WM831X_SYSTEM_INTERRUPTS);
        if (primary < 0) {
@@ -443,6 +555,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                        primary);
                goto out;
        }
+       
+       mutex_lock(&wm831x->irq_lock);
 
        /* The touch interrupts are visible in the primary register as
         * an optimisation; open code this to avoid complicating the
@@ -458,10 +572,10 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
 
        for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
                int offset = wm831x_irqs[i].reg - 1;
-
+               
                if (!(primary & wm831x_irqs[i].primary))
                        continue;
-
+               
                status = &status_regs[offset];
 
                /* Hopefully there should only be one register to read
@@ -473,7 +587,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                                dev_err(wm831x->dev,
                                        "Failed to read IRQ status: %d\n",
                                        *status);
-                               goto out;
+                               goto out_lock;
                        }
 
                        read[offset] = 1;
@@ -482,11 +596,39 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                /* Report it if it isn't masked, or forget the status. */
                if ((*status & ~wm831x->irq_masks_cur[offset])
                    & wm831x_irqs[i].mask)
+               {
+                       #if WM831X_IRQ_LIST
+                       /*add intterupt handle on list*/
+                       hd = kzalloc(sizeof(struct wm831x_handle_irq), GFP_KERNEL);
+                       if (!hd)
+                       {
+                               printk("err:%s:ENOMEM\n",__FUNCTION__);
+                               return ;
+                       }
+                       
+                       if(i == WM831X_IRQ_ON)
+                       wake_lock(&wm831x->handle_wake);                //keep wake while handle WM831X_IRQ_ON
+                       hd->irq = i;
+                       spin_lock_irqsave(&wm831x->work_lock, flags);
+                       list_add_tail(&hd->queue, &wm831x->handle_queue);
+                       spin_unlock_irqrestore(&wm831x->work_lock, flags);
+                       queue_work(wm831x->handle_wq, &wm831x->handle_work);
+                       
+                       #else
+                       if(i == WM831X_IRQ_ON)
+                       wake_lock(&wm831x->handle_wake);                //keep wake while handle WM831X_IRQ_ON
                        handle_nested_irq(wm831x->irq_base + i);
+                       
+                       #endif
+               }
+                       
                else
                        *status &= ~wm831x_irqs[i].mask;
        }
-
+       
+out_lock:      
+       mutex_unlock(&wm831x->irq_lock);
+       
 out:
        /* Touchscreen interrupts are handled specially in the driver */
        status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
@@ -496,7 +638,45 @@ out:
                        wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
                                         status_regs[i]);
        }
+       
+#if (WM831X_IRQ_TYPE != IRQF_TRIGGER_LOW)      
+       ret = wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG,
+                             WM831X_IRQ_IM_MASK, 0);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to open irq: %d\n", ret);
+       }
+#endif
+#if (WM831X_IRQ_TYPE == IRQF_TRIGGER_LOW)
+       enable_irq(wm831x->irq);        
+#endif
+       wake_unlock(&wm831x->irq_wake);
 
+}
+/* The processing of the primary interrupt occurs in a thread so that
+ * we can interact with the device over I2C or SPI. */
+static irqreturn_t wm831x_irq_thread(int irq, void *data)
+{
+       struct wm831x *wm831x = data;
+       int msdelay = 0;
+       /* Shut the interrupt to the CPU up and schedule the actual
+        * handler; we can't check that the IRQ is asserted. */
+#if (WM831X_IRQ_TYPE == IRQF_TRIGGER_LOW)
+       disable_irq_nosync(irq);
+#endif
+       wake_lock(&wm831x->irq_wake);
+       if(wm831x->flag_suspend)
+       {
+               spin_lock(&wm831x->flag_lock);
+               wm831x->flag_suspend = 0;
+               spin_unlock(&wm831x->flag_lock);
+               msdelay = 50;   //wait for spi/i2c resume
+               printk("%s:msdelay=%d\n",__FUNCTION__,msdelay);
+       }
+       else
+               msdelay = 0;
+               
+       queue_delayed_work(wm831x->irq_wq, &wm831x->irq_work, msecs_to_jiffies(msdelay));
+       //printk("%s\n",__FUNCTION__);
        return IRQ_HANDLED;
 }
 
@@ -504,7 +684,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
 {
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
        int i, cur_irq, ret;
-
+       printk( "wm831x_irq_init:irq=%d,%d\n",irq,pdata->irq_base);
        mutex_init(&wm831x->irq_lock);
 
        /* Mask the individual interrupt sources */
@@ -521,6 +701,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
                return 0;
        }
 
+<<<<<<< HEAD
        if (pdata->irq_cmos)
                i = 0;
        else
@@ -540,9 +721,32 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
                         ret);
        }
 
+=======
+       wm831x->irq_wq = create_singlethread_workqueue("wm831x-irq");
+       if (!wm831x->irq_wq) {
+               dev_err(wm831x->dev, "Failed to allocate IRQ worker\n");
+               return -ESRCH;
+       }
+
+       
+>>>>>>> parent of 15f7fab... temp revert rk change
        wm831x->irq = irq;
+       wm831x->flag_suspend = 0;
        wm831x->irq_base = pdata->irq_base;
+       INIT_DELAYED_WORK(&wm831x->irq_work, wm831x_irq_worker);
+       wake_lock_init(&wm831x->irq_wake, WAKE_LOCK_SUSPEND, "wm831x_irq_wake");
+       wake_lock_init(&wm831x->handle_wake, WAKE_LOCK_SUSPEND, "wm831x_handle_wake");
+#if WM831X_IRQ_LIST
+       wm831x->handle_wq = create_rt_workqueue("wm831x_handle_wq");
+       if (!wm831x->handle_wq) {
+               printk("cannot create workqueue\n");
+               return -EBUSY;
+       }
+       INIT_WORK(&wm831x->handle_work, wm831x_handle_worker);
+       INIT_LIST_HEAD(&wm831x->handle_queue);
 
+#endif
+       
        /* Register them with genirq */
        for (cur_irq = wm831x->irq_base;
             cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
@@ -560,6 +764,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
                irq_set_noprobe(cur_irq);
 #endif
        }
+<<<<<<< HEAD
 
        if (irq) {
                ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
@@ -577,6 +782,24 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
 
 
 
+=======
+#if (WM831X_IRQ_TYPE == IRQF_TRIGGER_LOW)
+       ret = request_threaded_irq(wm831x->irq, wm831x_irq_thread, NULL, 
+                                IRQF_TRIGGER_LOW| IRQF_ONESHOT,//IRQF_TRIGGER_FALLING, // 
+                                  "wm831x", wm831x);
+#else
+       ret = request_threaded_irq(wm831x->irq, wm831x_irq_thread, NULL, 
+                                IRQF_TRIGGER_FALLING, //IRQF_TRIGGER_LOW| IRQF_ONESHOT,// 
+                                  "wm831x", wm831x);
+#endif
+       if (ret != 0) {
+               dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
+                       wm831x->irq, ret);
+               return ret;
+       }
+
+       enable_irq_wake(wm831x->irq); // so wm831x irq can wake up system
+>>>>>>> parent of 15f7fab... temp revert rk change
        /* Enable top level interrupts, we mask at secondary level */
        wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0);
 
index eed8e4f7a5a14c6c724097567f1b817419dba3a9..97c8dab6c954f73ea04e77687439c26b9c1b92c1 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
+#include <linux/gpio.h>
 
 #include <linux/mfd/wm831x/core.h>
 
@@ -28,14 +29,24 @@ static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg,
 
        /* Go register at a time */
        for (r = reg; r < reg + (bytes / 2); r++) {
+<<<<<<< HEAD
                tx_val = r | 0x8000;
 
+=======
+               tx_val = cpu_to_be16(r | 0x8000);
+               //printk("read:reg=0x%x,",reg);
+>>>>>>> parent of 15f7fab... temp revert rk change
                ret = spi_write_then_read(wm831x->control_data,
                                          (u8 *)&tx_val, 2, (u8 *)d, 2);
                if (ret != 0)
                        return ret;
+<<<<<<< HEAD
 
                *d = be16_to_cpu(*d);
+=======
+               //printk("rec=0x%x\n",be16_to_cpu(*d));
+               //*d = be16_to_cpu(*d);
+>>>>>>> parent of 15f7fab... temp revert rk change
 
                d++;
        }
@@ -53,9 +64,15 @@ static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg,
 
        /* Go register at a time */
        for (r = reg; r < reg + (bytes / 2); r++) {
+<<<<<<< HEAD
                data[0] = r;
                data[1] = *s++;
 
+=======
+               data[0] = cpu_to_be16(r);
+               data[1] = *s++;
+               //printk("write:reg=0x%x,send=0x%x\n",reg, data[0]);
+>>>>>>> parent of 15f7fab... temp revert rk change
                ret = spi_write(spi, (char *)&data, sizeof(data));
                if (ret != 0)
                        return ret;
@@ -68,7 +85,12 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
 {
        struct wm831x *wm831x;
        enum wm831x_parent type;
+<<<<<<< HEAD
+
+=======
+       int ret,gpio,irq;
 
+>>>>>>> parent of 15f7fab... temp revert rk change
        /* Currently SPI support for ID tables is unmerged, we're faking it */
        if (strcmp(spi->modalias, "wm8310") == 0)
                type = WM8310;
@@ -96,13 +118,33 @@ static int __devinit wm831x_spi_probe(struct spi_device *spi)
        spi->bits_per_word = 16;
        spi->mode = SPI_MODE_0;
 
+<<<<<<< HEAD
+=======
+       gpio = spi->irq;
+       ret = gpio_request(gpio, "wm831x");
+       if (ret) {
+               printk( "failed to request rk gpio irq for wm831x \n");
+               return ret;
+       }
+       gpio_pull_updown(gpio, GPIOPullUp);
+       if (ret) {
+           printk("failed to pull up gpio irq for wm831x \n");
+               return ret;
+       }       
+       irq = gpio_to_irq(gpio);
+
+>>>>>>> parent of 15f7fab... temp revert rk change
        dev_set_drvdata(&spi->dev, wm831x);
        wm831x->dev = &spi->dev;
        wm831x->control_data = spi;
        wm831x->read_dev = wm831x_spi_read_device;
        wm831x->write_dev = wm831x_spi_write_device;
 
+<<<<<<< HEAD
        return wm831x_device_init(wm831x, type, spi->irq);
+=======
+       return wm831x_device_init(wm831x, type, irq);
+>>>>>>> parent of 15f7fab... temp revert rk change
 }
 
 static int __devexit wm831x_spi_remove(struct spi_device *spi)
@@ -118,6 +160,10 @@ static int wm831x_spi_suspend(struct device *dev)
 {
        struct wm831x *wm831x = dev_get_drvdata(dev);
 
+       spin_lock(&wm831x->flag_lock);
+       wm831x->flag_suspend = 1;
+       spin_unlock(&wm831x->flag_lock);
+
        return wm831x_device_suspend(wm831x);
 }
 
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index 68f3671..a9a9449
@@ -535,9 +535,30 @@ config APANIC_PLABEL
         If your platform uses a different flash partition label for storing
         crashdumps, enter it here.
 
+config STE
+       bool "STE modem control driver"
+
+config MTK23D
+       bool "MTK6223D modem control driver"
+
+config FM580X
+       bool "FM rda580x driver"
+
+config MU509
+       bool "MU509 modem control driver"
+
+config MW100
+       bool "MW100 modem control driver"
+
+config RK29_NEWTON
+       bool "RK29_NEWTON misc driver"
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
+source "drivers/misc/rk29_modem/Kconfig"
+source "drivers/misc/gps/Kconfig"
+source "drivers/misc/mpu3050/Kconfig"
 source "drivers/misc/iwmc3200top/Kconfig"
 source "drivers/misc/ti-st/Kconfig"
 source "drivers/misc/lis3lv02d/Kconfig"
old mode 100755 (executable)
new mode 100644 (file)
index 2d43048..c4ed797
@@ -52,3 +52,12 @@ obj-y                                += carma/
 obj-$(CONFIG_WL127X_RFKILL)    += wl127x-rfkill.o
 obj-$(CONFIG_APANIC)           += apanic.o
 obj-$(CONFIG_SENSORS_AK8975)   += akm8975.o
+obj-$(CONFIG_MTK23D)           += mtk23d.o
+obj-$(CONFIG_FM580X)           += fm580x.o
+obj-$(CONFIG_MU509)            += mu509.o
+obj-$(CONFIG_MW100)            += MW100.o
+obj-$(CONFIG_STE)              += ste.o
+obj-$(CONFIG_RK29_SUPPORT_MODEM)       += rk29_modem/
+obj-$(CONFIG_GPS_GNS7560)      += gps/
+obj-y += mpu3050/
+obj-$(CONFIG_RK29_NEWTON)      += newton.o
index ca875f89da7a7ffe4dfde8eda532f26c800d50f9..4a9f48ac74802447b5d2397a7e819fe36ef36676 100644 (file)
@@ -193,8 +193,13 @@ static int apanic_proc_read(char *buffer, char **start, off_t offset,
                ctx->mtd->writesize,
                &len, ctx->bounce);
 
+#ifdef CONFIG_MTD_RKNAND
+       if (count > (ctx->mtd->writesize - page_offset))
+               count = ctx->mtd->writesize - page_offset;
+#else
        if (page_offset)
                count -= page_offset;
+#endif
        memcpy(buffer, ctx->bounce + page_offset, count);
 
        *start = count;
@@ -209,6 +214,11 @@ static int apanic_proc_read(char *buffer, char **start, off_t offset,
 static void mtd_panic_erase(void)
 {
        struct apanic_data *ctx = &drv_ctx;
+#ifdef CONFIG_MTD_RKNAND
+       size_t wlen;
+       memset(ctx->bounce, 0, ctx->mtd->writesize);
+       ctx->mtd->write(ctx->mtd, 0, ctx->mtd->writesize, &wlen, ctx->bounce);
+#else
        struct erase_info erase;
        DECLARE_WAITQUEUE(wait, current);
        wait_queue_head_t wait_q;
@@ -260,6 +270,7 @@ static void mtd_panic_erase(void)
                schedule();
                remove_wait_queue(&wait_q, &wait);
        }
+#endif
        printk(KERN_DEBUG "apanic: %s partition erased\n",
               CONFIG_APANIC_PLABEL);
 out:
@@ -331,14 +342,18 @@ static void mtd_panic_notify_add(struct mtd_info *mtd)
 
        if (hdr->magic != PANIC_MAGIC) {
                printk(KERN_INFO "apanic: No panic data available\n");
+#ifndef CONFIG_MTD_RKNAND
                mtd_panic_erase();
+#endif
                return;
        }
 
        if (hdr->version != PHDR_VERSION) {
                printk(KERN_INFO "apanic: Version mismatch (%d != %d)\n",
                       hdr->version, PHDR_VERSION);
+#ifndef CONFIG_MTD_RKNAND
                mtd_panic_erase();
+#endif
                return;
        }
 
@@ -378,8 +393,10 @@ static void mtd_panic_notify_add(struct mtd_info *mtd)
                }
        }
 
+#ifndef CONFIG_MTD_RKNAND
        if (!proc_entry_created)
                mtd_panic_erase();
+#endif
 
        return;
 out_err:
@@ -511,7 +528,7 @@ static int apanic(struct notifier_block *this, unsigned long event,
                printk(KERN_EMERG "Crash partition in use!\n");
                goto out;
        }
-       console_offset = ctx->mtd->writesize;
+       console_offset = ctx->mtd->erasesize;
 
        /*
         * Write out the console
index abb73c14316464b36c61e3872373d90d205a5149..b47acd333f350c499d0b7777425f3613bbdf26a9 100644 (file)
@@ -1087,8 +1087,8 @@ static long pmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                region.offset = pmem_start_addr(id, data);
                                region.len = pmem_len(id, data);
                        }
-                       printk(KERN_INFO "pmem: request for physical address of pmem region "
-                                       "from process %d.\n", current->pid);
+                       //printk(KERN_INFO "pmem: request for physical address of pmem region "
+                       //              "from process %d.\n", current->pid);
                        if (copy_to_user((void __user *)arg, &region,
                                                sizeof(struct pmem_region)))
                                return -EFAULT;
index c779503e75784c6815a1fe3fe1981b5e19fbd432..c8ddf2dfe9a009ea074a4e5911993dc7d81e49ed 100755 (executable)
@@ -521,6 +521,13 @@ static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
        return result;
 }
 
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) //Deleted by xbw@2011-03-21
+//static u32 get_card_status(struct mmc_card *card, struct request *req)
+//{
+//   return 0;
+//}
+
+#else
 static u32 get_card_status(struct mmc_card *card, struct request *req)
 {
        struct mmc_command cmd = {0};
@@ -532,10 +539,11 @@ static u32 get_card_status(struct mmc_card *card, struct request *req)
        cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
        err = mmc_wait_for_cmd(card->host, &cmd, 0);
        if (err)
-               printk(KERN_ERR "%s: error %d sending status command",
+               printk(KERN_DEBUG "%s: error %d sending status command",
                       req->rq_disk->disk_name, err);
        return cmd.resp[0];
 }
+#endif
 
 static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
 {
@@ -689,6 +697,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                brq.mrq.cmd = &brq.cmd;
                brq.mrq.data = &brq.data;
 
+               #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+               brq.cmd.retries = 2; //suppot retry read-write; added by xbw@2011-03-21
+               #endif
+
                brq.cmd.arg = blk_rq_pos(req);
                if (!mmc_card_blockaddr(card))
                        brq.cmd.arg <<= 9;
@@ -799,6 +811,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
 
                mmc_queue_bounce_post(mq);
 
+        #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+        //not turn CMD18 to CMD17. deleted by xbw at 2011-04-21
+
+        #else
+
                /*
                 * Check for errors here, but don't jump to cmd_err
                 * until later as we need to wait for the card to leave
@@ -808,7 +825,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                    brq.data.error || brq.stop.error) {
                        if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
                                /* Redo read one sector at a time */
-                               printk(KERN_WARNING "%s: retrying using single "
+                               printk(KERN_DEBUG "%s: retrying using single "
                                       "block read\n", req->rq_disk->disk_name);
                                disable_multi = 1;
                                continue;
@@ -817,6 +834,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                } else if (disable_multi == 1) {
                        disable_multi = 0;
                }
+        #endif
 
                if (brq.sbc.error) {
                        printk(KERN_ERR "%s: error %d sending SET_BLOCK_COUNT "
@@ -826,7 +844,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                }
 
                if (brq.cmd.error) {
-                       printk(KERN_ERR "%s: error %d sending read/write "
+                       printk(KERN_DEBUG "%s: error %d sending read/write "
                               "command, response %#x, card status %#x\n",
                               req->rq_disk->disk_name, brq.cmd.error,
                               brq.cmd.resp[0], status);
@@ -836,7 +854,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                        if (brq.data.error == -ETIMEDOUT && brq.mrq.stop)
                                /* 'Stop' response contains card status */
                                status = brq.mrq.stop->resp[0];
-                       printk(KERN_ERR "%s: error %d transferring data,"
+                       printk(KERN_DEBUG "%s: error %d transferring data,"
                               " sector %u, nr %u, card status %#x\n",
                               req->rq_disk->disk_name, brq.data.error,
                               (unsigned)blk_rq_pos(req),
@@ -844,12 +862,16 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                }
 
                if (brq.stop.error) {
-                       printk(KERN_ERR "%s: error %d sending stop command, "
+                       printk(KERN_DEBUG "%s: error %d sending stop command, "
                               "response %#x, card status %#x\n",
                               req->rq_disk->disk_name, brq.stop.error,
                               brq.stop.resp[0], status);
                }
 
+ #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+ //Deleted by xbw@2011-03-21
+
+ #else
                if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
                        do {
                                int err;
@@ -859,7 +881,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                                cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
                                err = mmc_wait_for_cmd(card->host, &cmd, 5);
                                if (err) {
-                                       printk(KERN_ERR "%s: error %d requesting status\n",
+                                       printk(KERN_DEBUG "%s: error %d requesting status\n",
                                               req->rq_disk->disk_name, err);
                                        goto cmd_err;
                                }
@@ -879,6 +901,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
                                goto cmd_err;
 #endif
                }
+#endif
 
                if (brq.cmd.error || brq.stop.error || brq.data.error) {
                        if (rq_data_dir(req) == READ) {
@@ -1063,6 +1086,11 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
        snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
                 "mmcblk%d%s", md->name_idx, subname ? subname : "");
 
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+       printk("%s..%d **** devidx=%d, dev_use[0]=%lu, disk_name=%s *** ==xbw[%s]==\n",\
+           __FUNCTION__,__LINE__, devidx, dev_use[0], md->disk->disk_name,mmc_hostname(card->host));
+#endif
+
        blk_queue_logical_block_size(md->queue.queue, 512);
        set_capacity(md->disk, size);
 
index 7c3444a37070de9fffd24839990a06c2433ceacc..b453ecc9710b120f4477a9365dc3cd1e439aedae 100755 (executable)
@@ -215,6 +215,9 @@ static void mmc_wait_done(struct mmc_request *mrq)
  */
 void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
 {
+       unsigned long datasize, waittime = 0xFFFF;
+       u32 multi, unit;
+
        DECLARE_COMPLETION_ONSTACK(complete);
 
        mrq->done_data = &complete;
@@ -222,7 +225,47 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
 
        mmc_start_request(host, mrq);
 
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+    if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) ) 
+    {
+        multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1;
+        waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //sdio; for cmd dead. Modifyed by xbw at 2011-06-02
+    }
+    else
+    {   
+        //calculate the timeout value for SDMMC; added by xbw at 2011-09-27
+        if(mrq->data)
+        {
+            unit = 3*(1<<20);// unit=3MB
+            datasize = mrq->data->blksz*mrq->data->blocks;
+            multi = datasize/unit;
+            multi += (datasize%unit)?1:0;
+            multi = (multi>0) ? multi : 1;
+            multi += (mrq->cmd->retries>0)?1:0;
+            waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //It should be longer than bottom driver's time,due to the sum of two cmd time.
+                                                                          //modifyed by xbw at 2011-10-08
+                                                                          //
+                                                                          //example:
+                                                                          //rk29_sdmmc_request_end..2336...   CMD12 wait busy timeout!!!!! ====xbw=[sd_mmc]====
+                                                                          //mmc_wait_for_req..236.. !!!!! wait for CMD25 timeout ===xbw[mmc0]===
+        }
+        else
+        {
+            multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1;
+            waittime = wait_for_completion_timeout(&complete,HZ*7*multi);
+        }
+    }
+    
+    if(waittime <= 1)
+    {
+        host->doneflag = 0;
+        mrq->cmd->error = -EIO;
+        printk("%s..%d.. !!!!! wait for CMD%d timeout ===xbw[%s]===\n",\
+            __FUNCTION__, __LINE__, mrq->cmd->opcode, mmc_hostname(host));
+    }
+#else
        wait_for_completion(&complete);
+#endif
 }
 
 EXPORT_SYMBOL(mmc_wait_for_req);
@@ -1869,6 +1912,11 @@ int mmc_resume_host(struct mmc_host *host)
                        }
                }
                BUG_ON(!host->bus_ops->resume);
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+        //panic if the card is being removed during the resume, deleted by xbw at 2011-06-20
+               host->bus_ops->resume(host);
+
+#else
                err = host->bus_ops->resume(host);
                if (err) {
                        printk(KERN_WARNING "%s: error %d during resume "
@@ -1876,6 +1924,7 @@ int mmc_resume_host(struct mmc_host *host)
                                            mmc_hostname(host), err);
                        err = 0;
                }
+#endif
        }
        host->pm_flags &= ~MMC_PM_KEEP_POWER;
        mmc_bus_put(host);
index aa7d1d79b8c554c143c004db5e3ef9565ca653dd..406f29efde3a8ac6f8be2772f263648fd1780686 100644 (file)
@@ -559,7 +559,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        /* The extra bit indicates that we support high capacity */
        err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
        if (err)
+       {
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+           printk("%s..%d..  ====*Identify the card as MMC , but OCR error, so fail to initialize.===xbw[%s]===\n",\
+               __FUNCTION__, __LINE__, mmc_hostname(host));
+#endif
                goto err;
+       }
 
        /*
         * For SPI, enable CRC as appropriate.
@@ -734,6 +740,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                if (max_dtr > card->ext_csd.hs_max_dtr)
                        max_dtr = card->ext_csd.hs_max_dtr;
        } else if (max_dtr > card->csd.max_dtr) {
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+        //in order to expand the compatibility of card. Added by xbw@2011-03-21
+               card->csd.max_dtr = (card->csd.max_dtr > MMC_FPP_FREQ) ? MMC_FPP_FREQ : (card->csd.max_dtr); 
+#endif
                max_dtr = card->csd.max_dtr;
        }
 
@@ -1012,6 +1022,9 @@ int mmc_attach_mmc(struct mmc_host *host)
 {
        int err;
        u32 ocr;
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+       int retry_times = 3;
+#endif
 
        BUG_ON(!host);
        WARN_ON(!host->claimed);
@@ -1062,10 +1075,34 @@ int mmc_attach_mmc(struct mmc_host *host)
                goto err;
 
        mmc_release_host(host);
+
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+//modifyed by xbw at 2011--04-11
+Retry_add:
+       err = mmc_add_card(host->card);
+       mmc_claim_host(host);
+       if (err)
+       {
+           //retry add the card; Added by xbw
+        if((--retry_times >= 0))
+        {        
+            printk("\n%s..%s..%d   ****error in add partition, so retry.  ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host));   
+            /* sleep some time */
+            set_current_state(TASK_INTERRUPTIBLE);
+            schedule_timeout(HZ/2);
+            
+            goto Retry_add;
+        }
+
+               goto remove_card;
+    
+       }
+#else
        err = mmc_add_card(host->card);
        mmc_claim_host(host);
        if (err)
                goto remove_card;
+#endif
 
        return 0;
 
index 5decf4972bcb7aacc41c23bcbeaa4df8d763e18d..550092d600ae50ef25bc670e8c18de44db2c620b 100755 (executable)
@@ -718,8 +718,13 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
 
 try_again:
        err = mmc_send_app_op_cond(host, ocr, rocr);
-       if (err)
+       if (err) {
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+           printk("%s..%d..  ====*Identify the card as SD , but OCR error, so fail to initialize.===xbw[%s]===\n", \
+               __FUNCTION__, __LINE__, mmc_hostname(host));
+#endif
                return err;
+       }
 
        /*
         * In case CCS and S18A in the response is set, start Signal Voltage
@@ -807,6 +812,13 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
                                printk(KERN_WARNING
                                       "%s: read switch failed (attempt %d)\n",
                                       mmc_hostname(host), retries);
+
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+                               if(0 == host->re_initialized_flags)
+                               {
+                                        break; //Added by xbw at 2011-06-21
+                               }
+#endif
                        }
                }
 #else
@@ -859,6 +871,11 @@ unsigned mmc_sd_get_max_clock(struct mmc_card *card)
                if (max_dtr > card->sw_caps.hs_max_dtr)
                        max_dtr = card->sw_caps.hs_max_dtr;
        } else if (max_dtr > card->csd.max_dtr) {
+
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+        //in order to expand the compatibility of card. Added by xbw@2011-03-21
+           card->csd.max_dtr = (card->csd.max_dtr > SD_FPP_FREQ) ? SD_FPP_FREQ : (card->csd.max_dtr); 
+#endif
                max_dtr = card->csd.max_dtr;
        }
 
@@ -1029,6 +1046,15 @@ static void mmc_sd_detect(struct mmc_host *host)
                err = mmc_send_status(host->card, NULL);
                if (err) {
                        retries--;
+
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+                 if(0 == host->re_initialized_flags)
+                       {
+                                retries = 0;
+                                break; //Added by xbw at 2011-06-21
+                       }
+#endif
+
                        udelay(5);
                        continue;
                }
@@ -1096,6 +1122,13 @@ static int mmc_sd_resume(struct mmc_host *host)
                               mmc_hostname(host), err, retries);
                        mdelay(5);
                        retries--;
+
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+                       if(0 == host->re_initialized_flags)
+                       {
+                                break; //Added by xbw at 2011-06-21
+                       }
+#endif
                        continue;
                }
                break;
@@ -1154,6 +1187,10 @@ int mmc_attach_sd(struct mmc_host *host)
 {
        int err;
        u32 ocr;
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+       int retry_times = 3;
+#endif
+
 #ifdef CONFIG_MMC_PARANOID_SD_INIT
        int retries;
 #endif
@@ -1227,6 +1264,14 @@ int mmc_attach_sd(struct mmc_host *host)
                err = mmc_sd_init_card(host, host->ocr, NULL);
                if (err) {
                        retries--;
+
+       #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+                       if(0 == host->re_initialized_flags)
+                       {
+                                retries = 0;
+                                break; //Added by xbw at 2011-06-21
+                       }
+       #endif
                        continue;
                }
                break;
@@ -1244,10 +1289,34 @@ int mmc_attach_sd(struct mmc_host *host)
 #endif
 
        mmc_release_host(host);
+
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+//modifyed by xbw at 2011--04-11
+Retry_add:
+       err = mmc_add_card(host->card);
+       mmc_claim_host(host);
+       if (err)
+       {
+           //retry add the card; Added by xbw
+        if((--retry_times >= 0))
+        {        
+            printk("\n%s..%s..%d   ****error in add partition, so retry.  ===xbw[%s]===\n",__FUNCTION__,__FILE__,__LINE__, mmc_hostname(host));   
+            /* sleep some time */
+            set_current_state(TASK_INTERRUPTIBLE);
+            schedule_timeout(HZ/2);
+            
+            goto Retry_add;
+        }
+
+               goto remove_card;
+    
+       }
+#else
        err = mmc_add_card(host->card);
        mmc_claim_host(host);
        if (err)
                goto remove_card;
+#endif
 
        return 0;
 
index 7da522e958a094d31299713c72dcfeded8af7184..689a465cd43d96e78425434dd3b477f52e036d2b 100755 (executable)
@@ -351,8 +351,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
         */
        if (!powered_resume) {
                err = mmc_send_io_op_cond(host, host->ocr, &ocr);
-               if (err)
+               if (err) {
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+           printk("%s..%d..  ====*Identify the card as SDIO , but OCR error, so fail to initialize.===xbw[%s]===\n", \
+               __FUNCTION__, __LINE__, mmc_hostname(host));
+#endif
                        goto err;
+               }
        }
 
        /*
@@ -405,6 +410,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
                if (err)
                        goto remove;
 
+#if !defined(CONFIG_SDMMC_RK29) || defined(CONFIG_SDMMC_RK29_OLD)
                /*
                 * Update oldcard with the new RCA received from the SDIO
                 * device -- we're doing this so that it's updated in the
@@ -412,6 +418,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
                 */
                if (oldcard)
                        oldcard->rca = card->rca;
+#endif
 
                mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
        }
@@ -932,6 +939,10 @@ int sdio_reset_comm(struct mmc_card *card)
        printk("%s():\n", __func__);
        mmc_claim_host(host);
 
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+       host->sdmmc_host_hw_init(mmc_priv(host));  //added by xbw , at 2011-10-18
+#endif
+
        mmc_go_idle(host);
 
        mmc_set_clock(host, host->f_min);
index 58a5cf73d6e9a0fa77646b5a4ca40c5f48a8f847..f626b3fcc9f5291cd3e76a9ebab21528bde1aee3 100644 (file)
@@ -2,6 +2,12 @@
 # Makefile for MMC/SD host controller drivers
 #
 
+ifeq ($(CONFIG_SDMMC_RK29_OLD),y)
+obj-$(CONFIG_SDMMC_RK29)       += rk29_sdmmc_old.o
+else
+obj-$(CONFIG_SDMMC_RK29)       += rk29_sdmmc.o
+endif
+
 obj-$(CONFIG_MMC_ARMMMCI)      += mmci.o
 obj-$(CONFIG_MMC_PXA)          += pxamci.o
 obj-$(CONFIG_MMC_IMX)          += imxmmc.o
index a338f31d289c76aa65d7d557b9265a74418ecc21..ae92103ddb65590733dcba19f4839211f12125b5 100755 (executable)
@@ -3177,8 +3177,12 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
     /*
         * We can do SGIO
        */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       mmc->max_segs = 64;
+#else
        mmc->max_phys_segs = 64;
        mmc->max_hw_segs = 64; 
+#endif
 
        /*
         * Block size can be up to 2048 bytes, but must be a power of two.
index 2e2e109de32c98b85d43d51343330732d7442c15..0685f70e701b7e0456c534b825c1109571d44cc7 100755 (executable)
@@ -1404,8 +1404,12 @@ static int rk29_sdmmc_probe(struct platform_device *pdev)
        mmc->f_max = host->bus_hz; 
        mmc->ocr_avail = pdata->host_ocr_avail;
        mmc->caps = pdata->host_caps;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       mmc->max_segs = 64;
+#else
        mmc->max_phys_segs = 64;
        mmc->max_hw_segs = 64;
+#endif
        mmc->max_blk_size = 4096; 
        mmc->max_blk_count = 65535; 
        mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
index 483e8a977102bbcff3aff57b2e37dba17d8e7653..5effa3d67160b13b4f2ecfeccc6cc3577575a684 100755 (executable)
@@ -310,7 +310,11 @@ static int rk29xxnand_add_partitions(struct rknand_info *nand_info)
         rknand_parts[num_partitions - 1].size = rknand_mtd.size - rknand_parts[num_partitions - 1].offset;\r
         \r
                g_num_partitions = num_partitions;\r
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))\r
+               return mtd_device_register(&rknand_mtd, rknand_parts, num_partitions);\r
+#else\r
                return add_mtd_partitions(&(rknand_mtd), rknand_parts, num_partitions);\r
+#endif\r
     } \r
 #endif \r
        return 0;\r
index f1d88c571bc4a6bc883804f11e45416c5795fadc..991df931d4aa9ac8d3fba0b70517710b6ab036e1 100644 (file)
@@ -17,280 +17,53 @@ menuconfig WLAN
 
 if WLAN
 
-config PCMCIA_RAYCS
-       tristate "Aviator/Raytheon 2.4GHz wireless support"
-       depends on PCMCIA
-       select WIRELESS_EXT
-       select WEXT_SPY
-       select WEXT_PRIV
+config WLAN_80211
+       bool "Wireless LAN (IEEE 802.11)"
+       depends on NETDEVICES
        ---help---
-         Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
-         (PC-card) wireless Ethernet networking card to your computer.
-         Please read the file <file:Documentation/networking/ray_cs.txt> for
-         details.
+         Say Y if you have any 802.11 wireless LAN hardware.
+
+         This option does not affect the kernel build, it only
+         lets you choose drivers.
+
+choice
+       prompt "WiFi device driver support"
+       default WIFI_NONE
+
+       config WIFI_NONE
+         bool "No WiFi"
+
+       config BCM4329
+         depends on WLAN_80211 && MMC
+         select WIRELESS_EXT
+         select WEXT_PRIV
+         select IEEE80211
+         select FW_LOADER
+         bool "Broadcom BCM4329 WiFi/BT Combo SDIO"
+         ---help---
+           A library for Broadcom BCM4329 SDIO WLAN/BT combo devices.
+           So far, the following modules have been verified:
+             (1) Samsung    SWL-B23
+
+       config MV8686
+         depends on WLAN_80211 && MMC
+         select WIRELESS_EXT
+         select IEEE80211
+         select FW_LOADER
+         bool "Marvell MV8686 SDIO"
+         ---help---
+           A library for Marvell 8686 SDIO WLAN devices.
+           So far, the following modules have been verified:
+             (1) Samsung    SWL-2480
+             (2) Azurewave  AW-GH321
+             (3) USI        WM-G-MR-09
+             (4) Murata     SP-8HEP-P
+
+source "drivers/net/wireless/bcm4319/Kconfig"
+source "drivers/net/wireless/rtl8192c/Kconfig"
+endchoice
+
+#source "drivers/net/wireless/bcm4329/Kconfig"
+
+endif
 
-         To compile this driver as a module, choose M here: the module will be
-         called ray_cs.  If unsure, say N.
-
-config LIBERTAS_THINFIRM
-       tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
-       depends on MAC80211
-       select FW_LOADER
-       ---help---
-         A library for Marvell Libertas 8xxx devices using thinfirm.
-
-config LIBERTAS_THINFIRM_DEBUG
-       bool "Enable full debugging output in the Libertas thin firmware module."
-       depends on LIBERTAS_THINFIRM
-       ---help---
-         Debugging support.
-
-config LIBERTAS_THINFIRM_USB
-       tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
-       depends on LIBERTAS_THINFIRM && USB
-       ---help---
-         A driver for Marvell Libertas 8388 USB devices using thinfirm.
-
-config AIRO
-       tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
-       depends on ISA_DMA_API && (PCI || BROKEN)
-       select WIRELESS_EXT
-       select CRYPTO
-       select WEXT_SPY
-       select WEXT_PRIV
-       ---help---
-         This is the standard Linux driver to support Cisco/Aironet ISA and
-         PCI 802.11 wireless cards.
-         It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
-         - with or without encryption) as well as card before the Cisco
-         acquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
-
-         This driver support both the standard Linux Wireless Extensions
-         and Cisco proprietary API, so both the Linux Wireless Tools and the
-         Cisco Linux utilities can be used to configure the card.
-
-         The driver can be compiled as a module and will be named "airo".
-
-config ATMEL
-      tristate "Atmel at76c50x chipset  802.11b support"
-      depends on (PCI || PCMCIA)
-      select WIRELESS_EXT
-      select WEXT_PRIV
-      select FW_LOADER
-      select CRC32
-       ---help---
-        A driver 802.11b wireless cards based on the Atmel fast-vnet
-        chips. This driver supports standard Linux wireless extensions.
-
-        Many  cards based on this chipset do not have flash memory
-        and need their firmware loaded at start-up. If yours is
-        one of these, you will need to provide a firmware image
-        to be loaded into the card by the driver. The Atmel
-        firmware package can be downloaded from
-        <http://www.thekelleys.org.uk/atmel>
-
-config PCI_ATMEL
-      tristate "Atmel at76c506 PCI cards"
-      depends on ATMEL && PCI
-       ---help---
-        Enable support for PCI and mini-PCI cards containing the
-        Atmel at76c506 chip.
-
-config PCMCIA_ATMEL
-       tristate "Atmel at76c502/at76c504 PCMCIA cards"
-       depends on ATMEL && PCMCIA
-       select WIRELESS_EXT
-       select FW_LOADER
-       select CRC32
-       ---help---
-         Enable support for PCMCIA cards containing the
-         Atmel at76c502 and at76c504 chips.
-
-config AT76C50X_USB
-        tristate "Atmel at76c503/at76c505/at76c505a USB cards"
-        depends on MAC80211 && USB
-        select FW_LOADER
-        ---help---
-          Enable support for USB Wireless devices using Atmel at76c503,
-          at76c505 or at76c505a chips.
-
-config AIRO_CS
-       tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
-       depends on PCMCIA && (BROKEN || !M32R)
-       select WIRELESS_EXT
-       select WEXT_SPY
-       select WEXT_PRIV
-       select CRYPTO
-       select CRYPTO_AES
-       ---help---
-         This is the standard Linux driver to support Cisco/Aironet PCMCIA
-         802.11 wireless cards.  This driver is the same as the Aironet
-         driver part of the Linux Pcmcia package.
-         It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
-         - with or without encryption) as well as card before the Cisco
-         acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
-         supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom
-         802.11b cards.
-
-         This driver support both the standard Linux Wireless Extensions
-         and Cisco proprietary API, so both the Linux Wireless Tools and the
-         Cisco Linux utilities can be used to configure the card.
-
-config PCMCIA_WL3501
-       tristate "Planet WL3501 PCMCIA cards"
-       depends on EXPERIMENTAL && PCMCIA
-       select WIRELESS_EXT
-       select WEXT_SPY
-       help
-         A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet.
-         It has basic support for Linux wireless extensions and initial
-         micro support for ethtool.
-
-config PRISM54
-       tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
-       depends on PCI && EXPERIMENTAL
-       select WIRELESS_EXT
-       select WEXT_SPY
-       select WEXT_PRIV
-       select FW_LOADER
-       ---help---
-         This enables support for FullMAC PCI/Cardbus prism54 devices. This
-         driver is now deprecated in favor for the SoftMAC driver, p54pci.
-         p54pci supports FullMAC PCI/Cardbus devices as well. For details on
-         the scheduled removal of this driver on the kernel see the feature
-         removal schedule:
-
-         Documentation/feature-removal-schedule.txt
-
-         For more information refer to the p54 wiki:
-
-         http://wireless.kernel.org/en/users/Drivers/p54
-
-         Note: You need a motherboard with DMA support to use any of these cards
-
-         When built as module you get the module prism54
-
-config USB_ZD1201
-       tristate "USB ZD1201 based Wireless device support"
-       depends on USB
-       select WIRELESS_EXT
-       select WEXT_PRIV
-       select FW_LOADER
-       ---help---
-         Say Y if you want to use wireless LAN adapters based on the ZyDAS
-         ZD1201 chip.
-
-         This driver makes the adapter appear as a normal Ethernet interface,
-         typically on wlan0.
-
-         The zd1201 device requires external firmware to be loaded.
-         This can be found at http://linux-lc100020.sourceforge.net/
-
-         To compile this driver as a module, choose M here: the
-         module will be called zd1201.
-
-config USB_NET_RNDIS_WLAN
-       tristate "Wireless RNDIS USB support"
-       depends on USB && EXPERIMENTAL
-       depends on CFG80211
-       select USB_USBNET
-       select USB_NET_CDCETHER
-       select USB_NET_RNDIS_HOST
-       ---help---
-         This is a driver for wireless RNDIS devices.
-         These are USB based adapters found in devices such as:
-
-         Buffalo WLI-U2-KG125S
-         U.S. Robotics USR5421
-         Belkin F5D7051
-         Linksys WUSB54GSv2
-         Linksys WUSB54GSC
-         Asus WL169gE
-         Eminent EM4045
-         BT Voyager 1055
-         Linksys WUSB54GSv1
-         U.S. Robotics USR5420
-         BUFFALO WLI-USB-G54
-
-         All of these devices are based on Broadcom 4320 chip which is the
-         only wireless RNDIS chip known to date.
-
-         If you choose to build a module, it'll be called rndis_wlan.
-
-source "drivers/net/wireless/rtl818x/Kconfig"
-
-config ADM8211
-       tristate "ADMtek ADM8211 support"
-       depends on MAC80211 && PCI && EXPERIMENTAL
-       select CRC32
-       select EEPROM_93CX6
-       ---help---
-         This driver is for ADM8211A, ADM8211B, and ADM8211C based cards.
-         These are PCI/mini-PCI/Cardbus 802.11b chips found in cards such as:
-
-         Xterasys Cardbus XN-2411b
-         Blitz NetWave Point PC
-         TrendNet 221pc
-         Belkin F5D6001
-         SMC 2635W
-         Linksys WPC11 v1
-         Fiberline FL-WL-200X
-         3com Office Connect (3CRSHPW796)
-         Corega WLPCIB-11
-         SMC 2602W V2 EU
-         D-Link DWL-520 Revision C
-
-         However, some of these cards have been replaced with other chips
-         like the RTL8180L (Xterasys Cardbus XN-2411b, Belkin F5D6001) or
-         the Ralink RT2400 (SMC2635W) without a model number change.
-
-         Thanks to Infineon-ADMtek for their support of this driver.
-
-config MAC80211_HWSIM
-       tristate "Simulated radio testing tool for mac80211"
-       depends on MAC80211
-       ---help---
-         This driver is a developer testing tool that can be used to test
-         IEEE 802.11 networking stack (mac80211) functionality. This is not
-         needed for normal wireless LAN usage and is only for testing. See
-         Documentation/networking/mac80211_hwsim for more information on how
-         to use this tool.
-
-         To compile this driver as a module, choose M here: the module will be
-         called mac80211_hwsim.  If unsure, say N.
-
-config MWL8K
-       tristate "Marvell 88W8xxx PCI/PCIe Wireless support"
-       depends on MAC80211 && PCI && EXPERIMENTAL
-       ---help---
-         This driver supports Marvell TOPDOG 802.11 wireless cards.
-
-         To compile this driver as a module, choose M here: the module
-         will be called mwl8k.  If unsure, say N.
-
-config WIFI_CONTROL_FUNC
-       bool "Enable WiFi control function abstraction"
-       help
-         Enables Power/Reset/Carddetect function abstraction
-
-source "drivers/net/wireless/ath/Kconfig"
-source "drivers/net/wireless/b43/Kconfig"
-source "drivers/net/wireless/b43legacy/Kconfig"
-source "drivers/net/wireless/bcm4329/Kconfig"
-source "drivers/net/wireless/bcmdhd/Kconfig"
-source "drivers/net/wireless/hostap/Kconfig"
-source "drivers/net/wireless/ipw2x00/Kconfig"
-source "drivers/net/wireless/iwlwifi/Kconfig"
-source "drivers/net/wireless/iwlegacy/Kconfig"
-source "drivers/net/wireless/iwmc3200wifi/Kconfig"
-source "drivers/net/wireless/libertas/Kconfig"
-source "drivers/net/wireless/orinoco/Kconfig"
-source "drivers/net/wireless/p54/Kconfig"
-source "drivers/net/wireless/rt2x00/Kconfig"
-source "drivers/net/wireless/rtlwifi/Kconfig"
-source "drivers/net/wireless/wl1251/Kconfig"
-source "drivers/net/wireless/wl12xx/Kconfig"
-source "drivers/net/wireless/zd1211rw/Kconfig"
-source "drivers/net/wireless/mwifiex/Kconfig"
-
-endif # WLAN
index 8ceae0a8ba0fa48a142cdcd14453a2c1fad6ab5d..f463629aa9c227bc7960969fa9495c81ebaf18e9 100644 (file)
@@ -1,63 +1,9 @@
 #
 # Makefile for the Linux Wireless network device drivers.
 #
-
-obj-$(CONFIG_IPW2100) += ipw2x00/
-obj-$(CONFIG_IPW2200) += ipw2x00/
-
-obj-$(CONFIG_HERMES)           += orinoco/
-
-obj-$(CONFIG_AIRO)             += airo.o
-obj-$(CONFIG_AIRO_CS)          += airo_cs.o airo.o
-
-obj-$(CONFIG_ATMEL)             += atmel.o
-obj-$(CONFIG_PCI_ATMEL)         += atmel_pci.o 
-obj-$(CONFIG_PCMCIA_ATMEL)      += atmel_cs.o
-
-obj-$(CONFIG_AT76C50X_USB)      += at76c50x-usb.o
-
-obj-$(CONFIG_PRISM54)          += prism54/
-
-obj-$(CONFIG_HOSTAP)           += hostap/
-obj-$(CONFIG_B43)              += b43/
-obj-$(CONFIG_B43LEGACY)                += b43legacy/
-obj-$(CONFIG_ZD1211RW)         += zd1211rw/
-obj-$(CONFIG_RTL8180)          += rtl818x/
-obj-$(CONFIG_RTL8187)          += rtl818x/
-obj-$(CONFIG_RTLWIFI)          += rtlwifi/
-
-# 16-bit wireless PCMCIA client drivers
-obj-$(CONFIG_PCMCIA_RAYCS)     += ray_cs.o
-obj-$(CONFIG_PCMCIA_WL3501)    += wl3501_cs.o
-
-obj-$(CONFIG_USB_NET_RNDIS_WLAN)       += rndis_wlan.o
-
-obj-$(CONFIG_USB_ZD1201)       += zd1201.o
-obj-$(CONFIG_LIBERTAS)         += libertas/
-
-obj-$(CONFIG_LIBERTAS_THINFIRM)        += libertas_tf/
-
-obj-$(CONFIG_ADM8211)  += adm8211.o
-
-obj-$(CONFIG_MWL8K)    += mwl8k.o
-
-obj-$(CONFIG_IWLAGN)   += iwlwifi/
-obj-$(CONFIG_IWLWIFI_LEGACY)   += iwlegacy/
-obj-$(CONFIG_RT2X00)   += rt2x00/
-
-obj-$(CONFIG_P54_COMMON)       += p54/
-
-obj-$(CONFIG_ATH_COMMON)       += ath/
-
-obj-$(CONFIG_MAC80211_HWSIM)   += mac80211_hwsim.o
-
-obj-$(CONFIG_WL1251)   += wl1251/
-obj-$(CONFIG_WL12XX)   += wl12xx/
-obj-$(CONFIG_WL12XX_PLATFORM_DATA)     += wl12xx/
-
-obj-$(CONFIG_IWM)      += iwmc3200wifi/
-
-obj-$(CONFIG_MWIFIEX)  += mwifiex/
-
-obj-$(CONFIG_BCM4329)  += bcm4329/
-obj-$(CONFIG_BCMDHD)   += bcmdhd/
+obj-y += wifi_sys/rkwifi_sys_iface.o
+obj-$(CONFIG_BCM4329)   += bcm4329/
+obj-$(CONFIG_MV8686)   += mv8686/
+obj-$(CONFIG_BCM4319)   += bcm4319/
+obj-$(CONFIG_RTL8192CU)   += rtl8192c/
+#obj-m += wlan/
index ca5760d32385d886cae591f477b2bde753eb9f37..aa4355a6225e1b951c6bbbddb21ca6c8003bd6fa 100644 (file)
@@ -22,6 +22,6 @@ config BCM4329_FW_PATH
 config BCM4329_NVRAM_PATH
        depends on BCM4329
        string "NVRAM path"
-       default "/proc/calibration"
+       default "/system/etc/firmware/nvram_B23.txt"
        ---help---
          Path to the calibration file.
old mode 100644 (file)
new mode 100755 (executable)
index 5a662be..fd04754
@@ -3,13 +3,16 @@ DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2         \
        -DUNRELEASEDCHIP -Dlinux -DDHD_SDALIGN=64 -DMAX_HDR_READ=64           \
        -DDHD_FIRSTREAD=64 -DDHD_GPL -DDHD_SCHED -DBDC -DTOE -DDHD_BCMEVENTS  \
        -DSHOW_EVENTS -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS      \
-       -Wall -Wstrict-prototypes -Werror -DOOB_INTR_ONLY -DCUSTOMER_HW2      \
-       -DDHD_USE_STATIC_BUF -DMMC_SDIO_ABORT -DDHD_DEBUG_TRAP -DSOFTAP       \
+       -Wall -Wstrict-prototypes -Werror -DCUSTOMER_HW2      \
+       -DDHD_USE_STATIC_BUF -DDHD_DEBUG_TRAP -DSOFTAP -DSDIO_ISR_THREAD      \
        -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT        \
-       -DGET_CUSTOM_MAC_ENABLE -DSET_RANDOM_MAC_SOFTAP -DCSCAN -DHW_OOB      \
-       -DKEEP_ALIVE -DPNO_SUPPORT                                            \
+       -DGET_CUSTOM_MAC_ENABLE -DSET_RANDOM_MAC_SOFTAP -DCSCAN   \
+        -DKEEP_ALIVE -DCONFIG_US_NON_DFS_CHANNELS_ONLY   \
        -Idrivers/net/wireless/bcm4329 -Idrivers/net/wireless/bcm4329/include
 
+#options defines dependent on platform board and applicantion requirements: 
+#-DOOB_INTR_ONLY -DMMC_SDIO_ABORT -DHW_OOB
+
 DHDOFILES = dhd_linux.o linux_osl.o bcmutils.o dhd_common.o dhd_custom_gpio.o \
        wl_iw.o siutils.o sbutils.o aiutils.o hndpmu.o bcmwifi.o dhd_sdio.o   \
        dhd_linux_sched.o dhd_cdc.o bcmsdh_sdmmc.o bcmsdh.o bcmsdh_linux.o    \
index 6d6097b78f7d3018b70ba8da864e5c0bbe8437fd..cdb2c5e1f1ecf714b377580195218d14e42cca86 100644 (file)
@@ -301,7 +301,7 @@ int bcmsdh_remove(struct device *dev)
        MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
        osl_detach(osh);
 
-#if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY)
+#if !defined(BCMLXSDMMC)
        dev_set_drvdata(dev, NULL);
 #endif /* !defined(BCMLXSDMMC) */
 
@@ -636,7 +636,7 @@ int bcmsdh_register_oob_intr(void * dhdp)
                if (error)
                        return -ENODEV;
 
-               enable_irq_wake(sdhcinfo->oob_irq);
+               set_irq_wake(sdhcinfo->oob_irq, 1);
                sdhcinfo->oob_irq_registered = TRUE;
        }
 
@@ -661,12 +661,10 @@ void bcmsdh_unregister_oob_intr(void)
 {
        SDLX_MSG(("%s: Enter\n", __FUNCTION__));
 
-       if (sdhcinfo->oob_irq_registered) {
-               disable_irq_wake(sdhcinfo->oob_irq);
-               disable_irq(sdhcinfo->oob_irq); /* just in case.. */
-               free_irq(sdhcinfo->oob_irq, NULL);
-               sdhcinfo->oob_irq_registered = FALSE;
-       }
+       set_irq_wake(sdhcinfo->oob_irq, 0);
+       disable_irq(sdhcinfo->oob_irq); /* just in case.. */
+       free_irq(sdhcinfo->oob_irq, NULL);
+       sdhcinfo->oob_irq_registered = FALSE;
 }
 #endif /* defined(OOB_INTR_ONLY) */
 /* Module parameters specific to each host-controller driver */
index 5a1a46c93571c0516f6f2c4ed827e38260fd4261..8992a4267f9f78ab6047a3f929dc4fef3a9f55d5 100644 (file)
@@ -82,6 +82,7 @@ PBCMSDH_SDMMC_INSTANCE gInstance;
 
 extern int bcmsdh_probe(struct device *dev);
 extern int bcmsdh_remove(struct device *dev);
+struct device sdmmc_dev;
 
 static int bcmsdh_sdmmc_probe(struct sdio_func *func,
                               const struct sdio_device_id *id)
@@ -101,7 +102,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
                if(func->device == 0x4) { /* 4318 */
                        gInstance->func[2] = NULL;
                        sd_trace(("NIC found, calling bcmsdh_probe...\n"));
-                       ret = bcmsdh_probe(&func->dev);
+                       ret = bcmsdh_probe(&sdmmc_dev);
                }
        }
 
@@ -109,7 +110,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func,
 
        if (func->num == 2) {
                sd_trace(("F2 found, calling bcmsdh_probe...\n"));
-               ret = bcmsdh_probe(&func->dev);
+               ret = bcmsdh_probe(&sdmmc_dev);
        }
 
        return ret;
@@ -125,7 +126,7 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func)
 
        if (func->num == 2) {
                sd_trace(("F2 found, calling bcmsdh_remove...\n"));
-               bcmsdh_remove(&func->dev);
+               bcmsdh_remove(&sdmmc_dev);
        }
 }
 
@@ -249,8 +250,10 @@ int sdio_function_init(void)
        if (!gInstance)
                return -ENOMEM;
 
+       bzero(&sdmmc_dev, sizeof(sdmmc_dev));
        error = sdio_register_driver(&bcmsdh_sdmmc_driver);
 
+
        return error;
 }
 
@@ -262,6 +265,7 @@ void sdio_function_cleanup(void)
 {
        sd_trace(("%s Enter\n", __FUNCTION__));
 
+
        sdio_unregister_driver(&bcmsdh_sdmmc_driver);
 
        if (gInstance)
diff --git a/drivers/net/wireless/bcm4329/bcmspibrcm.c b/drivers/net/wireless/bcm4329/bcmspibrcm.c
new file mode 100644 (file)
index 0000000..0f131a4
--- /dev/null
@@ -0,0 +1,1726 @@
+/*
+ * Broadcom BCMSDH to gSPI Protocol Conversion Layer
+ *
+ * Copyright (C) 2010, Broadcom Corporation
+ * All Rights Reserved.
+ * 
+ * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
+ * the contents of this file may not be disclosed to third parties, copied
+ * or duplicated in any form, in whole or in part, without the prior
+ * written permission of Broadcom Corporation.
+ *
+ * $Id: bcmspibrcm.c,v 1.11.2.10.2.9.6.11 2009/05/21 13:21:57 Exp $
+ */
+
+#define HSMODE
+
+#include <typedefs.h>
+
+#include <bcmdevs.h>
+#include <bcmendian.h>
+#include <bcmutils.h>
+#include <osl.h>
+#include <hndsoc.h>
+#include <siutils.h>
+#include <sbchipc.h>
+#include <sbsdio.h>
+#include <spid.h>
+
+#include <bcmsdbus.h>  /* bcmsdh to/from specific controller APIs */
+#include <sdiovar.h>   /* ioctl/iovars */
+#include <sdio.h>
+
+#include <pcicfg.h>
+
+
+#include <bcmspibrcm.h>
+#include <bcmspi.h>
+
+#define F0_RESPONSE_DELAY      16
+#define F1_RESPONSE_DELAY      16
+#define F2_RESPONSE_DELAY      F0_RESPONSE_DELAY
+
+#define CMDLEN         4
+
+#define DWORDMODE_ON (sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 2) && (sd->dwordmode == TRUE)
+
+/* Globals */
+uint sd_msglevel = 0;
+
+uint sd_hiok = FALSE;          /* Use hi-speed mode if available? */
+uint sd_sdmode = SDIOH_MODE_SPI;               /* Use SD4 mode by default */
+uint sd_f2_blocksize = 64;             /* Default blocksize */
+
+
+uint sd_divisor = 2;
+uint sd_power = 1;             /* Default to SD Slot powered ON */
+uint sd_clock = 1;             /* Default to SD Clock turned ON */
+uint sd_crc = 0;               /* Default to SPI CRC Check turned OFF */
+
+uint8  spi_outbuf[SPI_MAX_PKT_LEN];
+uint8  spi_inbuf[SPI_MAX_PKT_LEN];
+
+/* 128bytes buffer is enough to clear data-not-available and program response-delay F0 bits
+ * assuming we will not exceed F0 response delay > 100 bytes at 48MHz.
+ */
+#define BUF2_PKT_LEN   128
+uint8  spi_outbuf2[BUF2_PKT_LEN];
+uint8  spi_inbuf2[BUF2_PKT_LEN];
+
+/* Prototypes */
+static bool bcmspi_test_card(sdioh_info_t *sd);
+static bool bcmspi_host_device_init_adapt(sdioh_info_t *sd);
+static int bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode);
+static int bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
+                           uint32 *data, uint32 datalen);
+static int bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr,
+                              int regsize, uint32 *data);
+static int bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr,
+                               int regsize, uint32 data);
+static int bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr,
+                               uint8 *data);
+static int bcmspi_driver_init(sdioh_info_t *sd);
+static int bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
+                          uint32 addr, int nbytes, uint32 *data);
+static int bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize,
+                                 uint32 *data);
+static void bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer);
+static int bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg);
+
+/*
+ *  Public entry points & extern's
+ */
+extern sdioh_info_t *
+sdioh_attach(osl_t *osh, void *bar0, uint irq)
+{
+       sdioh_info_t *sd;
+
+       sd_trace(("%s\n", __FUNCTION__));
+       if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) {
+               sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh)));
+               return NULL;
+       }
+       bzero((char *)sd, sizeof(sdioh_info_t));
+       sd->osh = osh;
+       if (spi_osinit(sd) != 0) {
+               sd_err(("%s: spi_osinit() failed\n", __FUNCTION__));
+               MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+               return NULL;
+       }
+
+       sd->bar0 = bar0;
+       sd->irq = irq;
+       sd->intr_handler = NULL;
+       sd->intr_handler_arg = NULL;
+       sd->intr_handler_valid = FALSE;
+
+       /* Set defaults */
+       sd->use_client_ints = TRUE;
+       sd->sd_use_dma = FALSE; /* DMA Not supported */
+
+       /* Spi device default is 16bit mode, change to 4 when device is changed to 32bit
+        * mode
+        */
+       sd->wordlen = 2;
+
+       if (!spi_hw_attach(sd)) {
+               sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__));
+               spi_osfree(sd);
+               MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+               return (NULL);
+       }
+
+       if (bcmspi_driver_init(sd) != SUCCESS) {
+               sd_err(("%s: bcmspi_driver_init() failed()\n", __FUNCTION__));
+               spi_hw_detach(sd);
+               spi_osfree(sd);
+               MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+               return (NULL);
+       }
+
+       if (spi_register_irq(sd, irq) != SUCCESS) {
+               sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq));
+               spi_hw_detach(sd);
+               spi_osfree(sd);
+               MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+               return (NULL);
+       }
+
+       sd_trace(("%s: Done\n", __FUNCTION__));
+
+       return sd;
+}
+
+extern SDIOH_API_RC
+sdioh_detach(osl_t *osh, sdioh_info_t *sd)
+{
+       sd_trace(("%s\n", __FUNCTION__));
+       if (sd) {
+               sd_err(("%s: detaching from hardware\n", __FUNCTION__));
+               spi_free_irq(sd->irq, sd);
+               spi_hw_detach(sd);
+               spi_osfree(sd);
+               MFREE(sd->osh, sd, sizeof(sdioh_info_t));
+       }
+       return SDIOH_API_RC_SUCCESS;
+}
+
+/* Configure callback to client when we recieve client interrupt */
+extern SDIOH_API_RC
+sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
+{
+       sd_trace(("%s: Entering\n", __FUNCTION__));
+       sd->intr_handler = fn;
+       sd->intr_handler_arg = argh;
+       sd->intr_handler_valid = TRUE;
+       return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_interrupt_deregister(sdioh_info_t *sd)
+{
+       sd_trace(("%s: Entering\n", __FUNCTION__));
+       sd->intr_handler_valid = FALSE;
+       sd->intr_handler = NULL;
+       sd->intr_handler_arg = NULL;
+       return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff)
+{
+       sd_trace(("%s: Entering\n", __FUNCTION__));
+       *onoff = sd->client_intr_enabled;
+       return SDIOH_API_RC_SUCCESS;
+}
+
+#if defined(DHD_DEBUG)
+extern bool
+sdioh_interrupt_pending(sdioh_info_t *sd)
+{
+       return 0;
+}
+#endif
+
+extern SDIOH_API_RC
+sdioh_query_device(sdioh_info_t *sd)
+{
+       /* Return a BRCM ID appropriate to the dongle class */
+       return (sd->num_funcs > 1) ? BCM4329_D11NDUAL_ID : BCM4318_D11G_ID;
+}
+
+/* Provide dstatus bits of spi-transaction for dhd layers. */
+extern uint32
+sdioh_get_dstatus(sdioh_info_t *sd)
+{
+       return sd->card_dstatus;
+}
+
+extern void
+sdioh_chipinfo(sdioh_info_t *sd, uint32 chip, uint32 chiprev)
+{
+       sd->chip = chip;
+       sd->chiprev = chiprev;
+}
+
+extern void
+sdioh_dwordmode(sdioh_info_t *sd, bool set)
+{
+       uint8 reg = 0;
+       int status;
+
+       if ((status = sdioh_request_byte(sd, SDIOH_READ, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
+            SUCCESS) {
+               sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
+               return;
+       }
+
+       if (set) {
+               reg |= DWORD_PKT_LEN_EN;
+               sd->dwordmode = TRUE;
+               sd->client_block_size[SPI_FUNC_2] = 4096; /* h2spi's limit is 4KB, we support 8KB */
+       } else {
+               reg &= ~DWORD_PKT_LEN_EN;
+               sd->dwordmode = FALSE;
+               sd->client_block_size[SPI_FUNC_2] = 2048;
+       }
+
+       if ((status = sdioh_request_byte(sd, SDIOH_WRITE, SPI_FUNC_0, SPID_STATUS_ENABLE, &reg)) !=
+            SUCCESS) {
+               sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__));
+               return;
+       }
+}
+
+
+uint
+sdioh_query_iofnum(sdioh_info_t *sd)
+{
+       return sd->num_funcs;
+}
+
+/* IOVar table */
+enum {
+       IOV_MSGLEVEL = 1,
+       IOV_BLOCKMODE,
+       IOV_BLOCKSIZE,
+       IOV_DMA,
+       IOV_USEINTS,
+       IOV_NUMINTS,
+       IOV_NUMLOCALINTS,
+       IOV_HOSTREG,
+       IOV_DEVREG,
+       IOV_DIVISOR,
+       IOV_SDMODE,
+       IOV_HISPEED,
+       IOV_HCIREGS,
+       IOV_POWER,
+       IOV_CLOCK,
+       IOV_SPIERRSTATS,
+       IOV_RESP_DELAY_ALL
+};
+
+const bcm_iovar_t sdioh_iovars[] = {
+       {"sd_msglevel", IOV_MSGLEVEL,   0,      IOVT_UINT32,    0 },
+       {"sd_blocksize", IOV_BLOCKSIZE, 0,      IOVT_UINT32,    0 }, /* ((fn << 16) | size) */
+       {"sd_dma",      IOV_DMA,        0,      IOVT_BOOL,      0 },
+       {"sd_ints",     IOV_USEINTS,    0,      IOVT_BOOL,      0 },
+       {"sd_numints",  IOV_NUMINTS,    0,      IOVT_UINT32,    0 },
+       {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32,   0 },
+       {"sd_hostreg",  IOV_HOSTREG,    0,      IOVT_BUFFER,    sizeof(sdreg_t) },
+       {"sd_devreg",   IOV_DEVREG,     0,      IOVT_BUFFER,    sizeof(sdreg_t) },
+       {"sd_divisor",  IOV_DIVISOR,    0,      IOVT_UINT32,    0 },
+       {"sd_power",    IOV_POWER,      0,      IOVT_UINT32,    0 },
+       {"sd_clock",    IOV_CLOCK,      0,      IOVT_UINT32,    0 },
+       {"sd_mode",     IOV_SDMODE,     0,      IOVT_UINT32,    100},
+       {"sd_highspeed",        IOV_HISPEED,    0,      IOVT_UINT32,    0},
+       {"spi_errstats", IOV_SPIERRSTATS, 0, IOVT_BUFFER, sizeof(struct spierrstats_t) },
+       {"spi_respdelay",       IOV_RESP_DELAY_ALL,     0,      IOVT_BOOL,      0 },
+       {NULL, 0, 0, 0, 0 }
+};
+
+int
+sdioh_iovar_op(sdioh_info_t *si, const char *name,
+               void *params, int plen, void *arg, int len, bool set)
+{
+       const bcm_iovar_t *vi = NULL;
+       int bcmerror = 0;
+       int val_size;
+       int32 int_val = 0;
+       bool bool_val;
+       uint32 actionid;
+/*
+       sdioh_regs_t *regs;
+*/
+
+       ASSERT(name);
+       ASSERT(len >= 0);
+
+       /* Get must have return space; Set does not take qualifiers */
+       ASSERT(set || (arg && len));
+       ASSERT(!set || (!params && !plen));
+
+       sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name));
+
+       if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) {
+               bcmerror = BCME_UNSUPPORTED;
+               goto exit;
+       }
+
+       if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0)
+               goto exit;
+
+       /* Set up params so get and set can share the convenience variables */
+       if (params == NULL) {
+               params = arg;
+               plen = len;
+       }
+
+       if (vi->type == IOVT_VOID)
+               val_size = 0;
+       else if (vi->type == IOVT_BUFFER)
+               val_size = len;
+       else
+               val_size = sizeof(int);
+
+       if (plen >= (int)sizeof(int_val))
+               bcopy(params, &int_val, sizeof(int_val));
+
+       bool_val = (int_val != 0) ? TRUE : FALSE;
+
+       actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+       switch (actionid) {
+       case IOV_GVAL(IOV_MSGLEVEL):
+               int_val = (int32)sd_msglevel;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_MSGLEVEL):
+               sd_msglevel = int_val;
+               break;
+
+       case IOV_GVAL(IOV_BLOCKSIZE):
+               if ((uint32)int_val > si->num_funcs) {
+                       bcmerror = BCME_BADARG;
+                       break;
+               }
+               int_val = (int32)si->client_block_size[int_val];
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_GVAL(IOV_DMA):
+               int_val = (int32)si->sd_use_dma;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_DMA):
+               si->sd_use_dma = (bool)int_val;
+               break;
+
+       case IOV_GVAL(IOV_USEINTS):
+               int_val = (int32)si->use_client_ints;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_USEINTS):
+               break;
+
+       case IOV_GVAL(IOV_DIVISOR):
+               int_val = (uint32)sd_divisor;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_DIVISOR):
+               sd_divisor = int_val;
+               if (!spi_start_clock(si, (uint16)sd_divisor)) {
+                       sd_err(("%s: set clock failed\n", __FUNCTION__));
+                       bcmerror = BCME_ERROR;
+               }
+               break;
+
+       case IOV_GVAL(IOV_POWER):
+               int_val = (uint32)sd_power;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_POWER):
+               sd_power = int_val;
+               break;
+
+       case IOV_GVAL(IOV_CLOCK):
+               int_val = (uint32)sd_clock;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_CLOCK):
+               sd_clock = int_val;
+               break;
+
+       case IOV_GVAL(IOV_SDMODE):
+               int_val = (uint32)sd_sdmode;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_SDMODE):
+               sd_sdmode = int_val;
+               break;
+
+       case IOV_GVAL(IOV_HISPEED):
+               int_val = (uint32)sd_hiok;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_HISPEED):
+               sd_hiok = int_val;
+
+               if (!bcmspi_set_highspeed_mode(si, (bool)sd_hiok)) {
+                       sd_err(("%s: Failed changing highspeed mode to %d.\n",
+                               __FUNCTION__, sd_hiok));
+                       bcmerror = BCME_ERROR;
+                       return ERROR;
+               }
+               break;
+
+       case IOV_GVAL(IOV_NUMINTS):
+               int_val = (int32)si->intrcount;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_GVAL(IOV_NUMLOCALINTS):
+               int_val = (int32)si->local_intrcount;
+               bcopy(&int_val, arg, val_size);
+               break;
+       case IOV_GVAL(IOV_DEVREG):
+       {
+               sdreg_t *sd_ptr = (sdreg_t *)params;
+               uint8 data;
+
+               if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) {
+                       bcmerror = BCME_SDIO_ERROR;
+                       break;
+               }
+
+               int_val = (int)data;
+               bcopy(&int_val, arg, sizeof(int_val));
+               break;
+       }
+
+       case IOV_SVAL(IOV_DEVREG):
+       {
+               sdreg_t *sd_ptr = (sdreg_t *)params;
+               uint8 data = (uint8)sd_ptr->value;
+
+               if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) {
+                       bcmerror = BCME_SDIO_ERROR;
+                       break;
+               }
+               break;
+       }
+
+
+       case IOV_GVAL(IOV_SPIERRSTATS):
+       {
+               bcopy(&si->spierrstats, arg, sizeof(struct spierrstats_t));
+               break;
+       }
+
+       case IOV_SVAL(IOV_SPIERRSTATS):
+       {
+               bzero(&si->spierrstats, sizeof(struct spierrstats_t));
+               break;
+       }
+
+       case IOV_GVAL(IOV_RESP_DELAY_ALL):
+               int_val = (int32)si->resp_delay_all;
+               bcopy(&int_val, arg, val_size);
+               break;
+
+       case IOV_SVAL(IOV_RESP_DELAY_ALL):
+               si->resp_delay_all = (bool)int_val;
+               int_val = STATUS_ENABLE|INTR_WITH_STATUS;
+               if (si->resp_delay_all)
+                       int_val |= RESP_DELAY_ALL;
+               else {
+                       if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_RESPONSE_DELAY, 1,
+                            F1_RESPONSE_DELAY) != SUCCESS) {
+                               sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
+                               bcmerror = BCME_SDIO_ERROR;
+                               break;
+                       }
+               }
+
+               if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_STATUS_ENABLE, 1, int_val)
+                    != SUCCESS) {
+                       sd_err(("%s: Unable to set response delay.\n", __FUNCTION__));
+                       bcmerror = BCME_SDIO_ERROR;
+                       break;
+               }
+               break;
+
+       default:
+               bcmerror = BCME_UNSUPPORTED;
+               break;
+       }
+exit:
+
+       return bcmerror;
+}
+
+extern SDIOH_API_RC
+sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
+{
+       SDIOH_API_RC status;
+       /* No lock needed since sdioh_request_byte does locking */
+       status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data);
+       return status;
+}
+
+extern SDIOH_API_RC
+sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data)
+{
+       /* No lock needed since sdioh_request_byte does locking */
+       SDIOH_API_RC status;
+
+       if ((fnc_num == SPI_FUNC_1) && (addr == SBSDIO_FUNC1_FRAMECTRL)) {
+               uint8 dummy_data;
+               status = sdioh_cfg_read(sd, fnc_num, addr, &dummy_data);
+               if (status) {
+                       sd_err(("sdioh_cfg_read() failed.\n"));
+                       return status;
+               }
+       }
+
+       status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data);
+       return status;
+}
+
+extern SDIOH_API_RC
+sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length)
+{
+       uint32 count;
+       int offset;
+       uint32 cis_byte;
+       uint16 *cis = (uint16 *)cisd;
+       uint bar0 = SI_ENUM_BASE;
+       int status;
+       uint8 data;
+
+       sd_trace(("%s: Func %d\n", __FUNCTION__, func));
+
+       spi_lock(sd);
+
+       /* Set sb window address to 0x18000000 */
+       data = (bar0 >> 8) & SBSDIO_SBADDRLOW_MASK;
+       status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, &data);
+       if (status == SUCCESS) {
+               data = (bar0 >> 16) & SBSDIO_SBADDRMID_MASK;
+               status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, &data);
+       } else {
+               sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
+               spi_unlock(sd);
+               return (BCME_ERROR);
+       }
+       if (status == SUCCESS) {
+               data = (bar0 >> 24) & SBSDIO_SBADDRHIGH_MASK;
+               status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, &data);
+       } else {
+               sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__));
+               spi_unlock(sd);
+               return (BCME_ERROR);
+       }
+
+       offset =  CC_OTP; /* OTP offset in chipcommon. */
+       for (count = 0; count < length/2; count++) {
+               if (bcmspi_card_regread (sd, SDIO_FUNC_1, offset, 2, &cis_byte) < 0) {
+                       sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__));
+                       spi_unlock(sd);
+                       return (BCME_ERROR);
+               }
+
+               *cis = (uint16)cis_byte;
+               cis++;
+               offset += 2;
+       }
+
+       spi_unlock(sd);
+
+       return (BCME_OK);
+}
+
+extern SDIOH_API_RC
+sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte)
+{
+       int status;
+       uint32 cmd_arg;
+       uint32 dstatus;
+       uint32 data = (uint32)(*byte);
+
+       spi_lock(sd);
+
+       cmd_arg = 0;
+       cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+       cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);       /* Incremental access */
+       cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+       cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, rw == SDIOH_READ ? 0 : 1);
+       cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
+
+       sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+       sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, rw, func,
+                regaddr, data));
+
+       if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma,
+                                     cmd_arg, &data, 1)) != SUCCESS) {
+               spi_unlock(sd);
+               return status;
+       }
+
+       if (rw == SDIOH_READ)
+               *byte = (uint8)data;
+
+       bcmspi_cmd_getdstatus(sd, &dstatus);
+       if (dstatus)
+               sd_trace(("dstatus =0x%x\n", dstatus));
+
+       spi_unlock(sd);
+       return SDIOH_API_RC_SUCCESS;
+}
+
+extern SDIOH_API_RC
+sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr,
+                   uint32 *word, uint nbytes)
+{
+       int status;
+
+       spi_lock(sd);
+
+       if (rw == SDIOH_READ)
+               status = bcmspi_card_regread(sd, func, addr, nbytes, word);
+       else
+               status = bcmspi_card_regwrite(sd, func, addr, nbytes, *word);
+
+       spi_unlock(sd);
+       return (status == SUCCESS ?  SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
+}
+
+extern SDIOH_API_RC
+sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func,
+                     uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt)
+{
+       int len;
+       int buflen = (int)buflen_u;
+       bool fifo = (fix_inc == SDIOH_DATA_FIX);
+
+       spi_lock(sd);
+
+       ASSERT(reg_width == 4);
+       ASSERT(buflen_u < (1 << 30));
+       ASSERT(sd->client_block_size[func]);
+
+       sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n",
+                __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W',
+                buflen_u, sd->r_cnt, sd->t_cnt, pkt));
+
+       /* Break buffer down into blocksize chunks. */
+       while (buflen > 0) {
+               len = MIN(sd->client_block_size[func], buflen);
+               if (bcmspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) {
+                       sd_err(("%s: bcmspi_card_buf %s failed\n",
+                               __FUNCTION__, rw == SDIOH_READ ? "Read" : "Write"));
+                       spi_unlock(sd);
+                       return SDIOH_API_RC_FAIL;
+               }
+               buffer += len;
+               buflen -= len;
+               if (!fifo)
+                       addr += len;
+       }
+       spi_unlock(sd);
+       return SDIOH_API_RC_SUCCESS;
+}
+
+/* This function allows write to gspi bus when another rd/wr function is deep down the call stack.
+ * Its main aim is to have simpler spi writes rather than recursive writes.
+ * e.g. When there is a need to program response delay on the fly after detecting the SPI-func
+ * this call will allow to program the response delay.
+ */
+static int
+bcmspi_card_byterewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 byte)
+{
+       uint32 cmd_arg;
+       uint32 datalen = 1;
+       uint32 hostlen;
+
+       cmd_arg = 0;
+
+       cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
+       cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);       /* Incremental access */
+       cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+       cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+       cmd_arg = SFIELD(cmd_arg, SPI_LEN, datalen);
+
+       sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+
+
+       /* Set up and issue the SPI command.  MSByte goes out on bus first.  Increase datalen
+        * according to the wordlen mode(16/32bit) the device is in.
+        */
+       ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
+       datalen = ROUNDUP(datalen, sd->wordlen);
+
+       /* Start by copying command in the spi-outbuffer */
+       if (sd->wordlen == 4) { /* 32bit spid */
+               *(uint32 *)spi_outbuf2 = bcmswap32(cmd_arg);
+               if (datalen & 0x3)
+                       datalen += (4 - (datalen & 0x3));
+       } else if (sd->wordlen == 2) { /* 16bit spid */
+               *(uint16 *)spi_outbuf2 = bcmswap16(cmd_arg & 0xffff);
+               *(uint16 *)&spi_outbuf2[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16);
+               if (datalen & 0x1)
+                       datalen++;
+       } else {
+               sd_err(("%s: Host is %d bit spid, could not create SPI command.\n",
+                       __FUNCTION__, 8 * sd->wordlen));
+               return ERROR;
+       }
+
+       /* for Write, put the data into the output buffer  */
+       if (datalen != 0) {
+                       if (sd->wordlen == 4) { /* 32bit spid */
+                               *(uint32 *)&spi_outbuf2[CMDLEN] = bcmswap32(byte);
+                       } else if (sd->wordlen == 2) { /* 16bit spid */
+                               *(uint16 *)&spi_outbuf2[CMDLEN] = bcmswap16(byte & 0xffff);
+                               *(uint16 *)&spi_outbuf2[CMDLEN + 2] =
+                                       bcmswap16((byte & 0xffff0000) >> 16);
+                       }
+       }
+
+       /* +4 for cmd, +4 for dstatus */
+       hostlen = datalen + 8;
+       hostlen += (4 - (hostlen & 0x3));
+       spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, hostlen);
+
+       /* Last 4bytes are dstatus.  Device is configured to return status bits. */
+       if (sd->wordlen == 4) { /* 32bit spid */
+               sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
+       } else if (sd->wordlen == 2) { /* 16bit spid */
+               sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) |
+                                  (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16));
+       } else {
+               sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
+                       __FUNCTION__, 8 * sd->wordlen));
+               return ERROR;
+       }
+
+       if (sd->card_dstatus)
+               sd_trace(("dstatus after byte rewrite = 0x%x\n", sd->card_dstatus));
+
+       return (BCME_OK);
+}
+
+/* Program the response delay corresponding to the spi function */
+static int
+bcmspi_prog_resp_delay(sdioh_info_t *sd, int func, uint8 resp_delay)
+{
+       if (sd->resp_delay_all == FALSE)
+               return (BCME_OK);
+
+       if (sd->prev_fun == func)
+               return (BCME_OK);
+
+       if (F0_RESPONSE_DELAY == F1_RESPONSE_DELAY)
+               return (BCME_OK);
+
+       bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_RESPONSE_DELAY, resp_delay);
+
+       /* Remember function for which to avoid reprogramming resp-delay in next iteration */
+       sd->prev_fun = func;
+
+       return (BCME_OK);
+
+}
+
+#define GSPI_RESYNC_PATTERN    0x0
+
+/* A resync pattern is a 32bit MOSI line with all zeros. Its a special command in gSPI.
+ * It resets the spi-bkplane logic so that all F1 related ping-pong buffer logic is
+ * synchronised and all queued resuests are cancelled.
+ */
+static int
+bcmspi_resync_f1(sdioh_info_t *sd)
+{
+       uint32 cmd_arg = GSPI_RESYNC_PATTERN, data = 0, datalen = 0;
+
+
+       /* Set up and issue the SPI command.  MSByte goes out on bus first.  Increase datalen
+        * according to the wordlen mode(16/32bit) the device is in.
+        */
+       ASSERT(sd->wordlen == 4 || sd->wordlen == 2);
+       datalen = ROUNDUP(datalen, sd->wordlen);
+
+       /* Start by copying command in the spi-outbuffer */
+       *(uint32 *)spi_outbuf2 = cmd_arg;
+
+       /* for Write, put the data into the output buffer  */
+       *(uint32 *)&spi_outbuf2[CMDLEN] = data;
+
+       /* +4 for cmd, +4 for dstatus */
+       spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, datalen + 8);
+
+       /* Last 4bytes are dstatus.  Device is configured to return status bits. */
+       if (sd->wordlen == 4) { /* 32bit spid */
+               sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]);
+       } else if (sd->wordlen == 2) { /* 16bit spid */
+               sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) |
+                                  (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16));
+       } else {
+               sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n",
+                       __FUNCTION__, 8 * sd->wordlen));
+               return ERROR;
+       }
+
+       if (sd->card_dstatus)
+               sd_trace(("dstatus after resync pattern write = 0x%x\n", sd->card_dstatus));
+
+       return (BCME_OK);
+}
+
+uint32 dstatus_count = 0;
+
+static int
+bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg)
+{
+       uint32 dstatus = sd->card_dstatus;
+       struct spierrstats_t *spierrstats = &sd->spierrstats;
+       int err = SUCCESS;
+
+       sd_trace(("cmd = 0x%x, dstatus = 0x%x\n", cmd_arg, dstatus));
+
+       /* Store dstatus of last few gSPI transactions */
+       spierrstats->dstatus[dstatus_count % NUM_PREV_TRANSACTIONS] = dstatus;
+       spierrstats->spicmd[dstatus_count % NUM_PREV_TRANSACTIONS] = cmd_arg;
+       dstatus_count++;
+
+       if (sd->card_init_done == FALSE)
+               return err;
+
+       if (dstatus & STATUS_DATA_NOT_AVAILABLE) {
+               spierrstats->dna++;
+               sd_trace(("Read data not available on F1 addr = 0x%x\n",
+                       GFIELD(cmd_arg, SPI_REG_ADDR)));
+               /* Clear dna bit */
+               bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, DATA_UNAVAILABLE);
+       }
+
+       if (dstatus & STATUS_UNDERFLOW) {
+               spierrstats->rdunderflow++;
+               sd_err(("FIFO underflow happened due to current F2 read command.\n"));
+       }
+
+       if (dstatus & STATUS_OVERFLOW) {
+               spierrstats->wroverflow++;
+               sd_err(("FIFO overflow happened due to current (F1/F2) write command.\n"));
+               if ((sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 0)) {
+                       bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, F1_OVERFLOW);
+                       bcmspi_resync_f1(sd);
+                       sd_err(("Recovering from F1 FIFO overflow.\n"));
+               } else {
+                       err = ERROR_OF;
+               }
+       }
+
+       if (dstatus & STATUS_F2_INTR) {
+               spierrstats->f2interrupt++;
+               sd_trace(("Interrupt from F2.  SW should clear corresponding IntStatus bits\n"));
+       }
+
+       if (dstatus & STATUS_F3_INTR) {
+               spierrstats->f3interrupt++;
+               sd_err(("Interrupt from F3.  SW should clear corresponding IntStatus bits\n"));
+       }
+
+       if (dstatus & STATUS_HOST_CMD_DATA_ERR) {
+               spierrstats->hostcmddataerr++;
+               sd_err(("Error in CMD or Host data, detected by CRC/Checksum (optional)\n"));
+       }
+
+       if (dstatus & STATUS_F2_PKT_AVAILABLE) {
+               spierrstats->f2pktavailable++;
+               sd_trace(("Packet is available/ready in F2 TX FIFO\n"));
+               sd_trace(("Packet length = %d\n", sd->dwordmode ?
+                        ((dstatus & STATUS_F2_PKT_LEN_MASK) >> (STATUS_F2_PKT_LEN_SHIFT - 2)) :
+                        ((dstatus & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT)));
+       }
+
+       if (dstatus & STATUS_F3_PKT_AVAILABLE) {
+               spierrstats->f3pktavailable++;
+               sd_err(("Packet is available/ready in F3 TX FIFO\n"));
+               sd_err(("Packet length = %d\n",
+                       (dstatus & STATUS_F3_PKT_LEN_MASK) >> STATUS_F3_PKT_LEN_SHIFT));
+       }
+
+       return err;
+}
+
+extern int
+sdioh_abort(sdioh_info_t *sd, uint func)
+{
+       return 0;
+}
+
+int
+sdioh_start(sdioh_info_t *sd, int stage)
+{
+       return SUCCESS;
+}
+
+int
+sdioh_stop(sdioh_info_t *sd)
+{
+       return SUCCESS;
+}
+
+
+
+/*
+ * Private/Static work routines
+ */
+static int
+bcmspi_host_init(sdioh_info_t *sd)
+{
+
+       /* Default power on mode */
+       sd->sd_mode = SDIOH_MODE_SPI;
+       sd->polled_mode = TRUE;
+       sd->host_init_done = TRUE;
+       sd->card_init_done = FALSE;
+       sd->adapter_slot = 1;
+
+       return (SUCCESS);
+}
+
+static int
+get_client_blocksize(sdioh_info_t *sd)
+{
+       uint32 regdata[2];
+       int status;
+
+       /* Find F1/F2/F3 max packet size */
+       if ((status = bcmspi_card_regread(sd, 0, SPID_F1_INFO_REG,
+                                        8, regdata)) != SUCCESS) {
+               return status;
+       }
+
+       sd_trace(("pkt_size regdata[0] = 0x%x, regdata[1] = 0x%x\n",
+               regdata[0], regdata[1]));
+
+       sd->client_block_size[1] = (regdata[0] & F1_MAX_PKT_SIZE) >> 2;
+       sd_trace(("Func1 blocksize = %d\n", sd->client_block_size[1]));
+       ASSERT(sd->client_block_size[1] == BLOCK_SIZE_F1);
+
+       sd->client_block_size[2] = ((regdata[0] >> 16) & F2_MAX_PKT_SIZE) >> 2;
+       sd_trace(("Func2 blocksize = %d\n", sd->client_block_size[2]));
+       ASSERT(sd->client_block_size[2] == BLOCK_SIZE_F2);
+
+       sd->client_block_size[3] = (regdata[1] & F3_MAX_PKT_SIZE) >> 2;
+       sd_trace(("Func3 blocksize = %d\n", sd->client_block_size[3]));
+       ASSERT(sd->client_block_size[3] == BLOCK_SIZE_F3);
+
+       return 0;
+}
+
+static int
+bcmspi_client_init(sdioh_info_t *sd)
+{
+       uint32  status_en_reg = 0;
+       sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot));
+
+#ifdef HSMODE
+       if (!spi_start_clock(sd, (uint16)sd_divisor)) {
+               sd_err(("spi_start_clock failed\n"));
+               return ERROR;
+       }
+#else
+       /* Start at ~400KHz clock rate for initialization */
+       if (!spi_start_clock(sd, 128)) {
+               sd_err(("spi_start_clock failed\n"));
+               return ERROR;
+       }
+#endif /* HSMODE */
+
+       if (!bcmspi_host_device_init_adapt(sd)) {
+               sd_err(("bcmspi_host_device_init_adapt failed\n"));
+               return ERROR;
+       }
+
+       if (!bcmspi_test_card(sd)) {
+               sd_err(("bcmspi_test_card failed\n"));
+               return ERROR;
+       }
+
+       sd->num_funcs = SPI_MAX_IOFUNCS;
+
+       get_client_blocksize(sd);
+
+       /* Apply resync pattern cmd with all zeros to reset spi-bkplane F1 logic */
+       bcmspi_resync_f1(sd);
+
+       sd->dwordmode = FALSE;
+
+       bcmspi_card_regread(sd, 0, SPID_STATUS_ENABLE, 1, &status_en_reg);
+
+       sd_trace(("%s: Enabling interrupt with dstatus \n", __FUNCTION__));
+       status_en_reg |= INTR_WITH_STATUS;
+
+
+       if (bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_STATUS_ENABLE, 1,
+           status_en_reg & 0xff) != SUCCESS) {
+               sd_err(("%s: Unable to set response delay for all fun's.\n", __FUNCTION__));
+               return ERROR;
+       }
+
+
+#ifndef HSMODE
+       /* After configuring for High-Speed mode, set the desired clock rate. */
+       if (!spi_start_clock(sd, 4)) {
+               sd_err(("spi_start_clock failed\n"));
+               return ERROR;
+       }
+#endif /* HSMODE */
+
+       sd->card_init_done = TRUE;
+
+
+       return SUCCESS;
+}
+
+static int
+bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode)
+{
+       uint32 regdata;
+       int status;
+
+       if ((status = bcmspi_card_regread(sd, 0, SPID_CONFIG,
+                                        4, &regdata)) != SUCCESS)
+               return status;
+
+       sd_trace(("In %s spih-ctrl = 0x%x \n", __FUNCTION__, regdata));
+
+
+       if (hsmode == TRUE) {
+               sd_trace(("Attempting to enable High-Speed mode.\n"));
+
+               if (regdata & HIGH_SPEED_MODE) {
+                       sd_trace(("Device is already in High-Speed mode.\n"));
+                       return status;
+               } else {
+                       regdata |= HIGH_SPEED_MODE;
+                       sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
+                       if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
+                                                         4, regdata)) != SUCCESS) {
+                               return status;
+                       }
+               }
+       } else {
+               sd_trace(("Attempting to disable High-Speed mode.\n"));
+
+               if (regdata & HIGH_SPEED_MODE) {
+                       regdata &= ~HIGH_SPEED_MODE;
+                       sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG));
+                       if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG,
+                                                         4, regdata)) != SUCCESS)
+                               return status;
+               }
+                else {
+                       sd_trace(("Device is already in Low-Speed mode.\n"));
+                       return status;
+               }
+       }
+
+       spi_controller_highspeed_mode(sd, hsmode);
+
+       return TRUE;
+}
+
+#define bcmspi_find_curr_mode(sd) { \
+       sd->wordlen = 2; \
+       status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
+       regdata &= 0xff; \
+       if ((regdata == 0xad) || (regdata == 0x5b) || \
+           (regdata == 0x5d) || (regdata == 0x5a)) \
+               break; \
+       sd->wordlen = 4; \
+       status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, &regdata); \
+       regdata &= 0xff; \
+       if ((regdata == 0xad) || (regdata == 0x5b) || \
+           (regdata == 0x5d) || (regdata == 0x5a)) \
+               break; \
+       sd_trace(("Silicon testability issue: regdata = 0x%x." \
+                 " Expected 0xad, 0x5a, 0x5b or 0x5d.\n", regdata));   \
+       OSL_DELAY(100000); \
+}
+
+#define INIT_ADAPT_LOOP                100
+
+/* Adapt clock-phase-speed-bitwidth between host and device */
+static bool
+bcmspi_host_device_init_adapt(sdioh_info_t *sd)
+{
+       uint32 wrregdata, regdata = 0;
+       int status;
+       int i;
+
+       /* Due to a silicon testability issue, the first command from the Host
+        * to the device will get corrupted (first bit will be lost). So the
+        * Host should poll the device with a safe read request. ie: The Host
+        * should try to read F0 addr 0x14 using the Fixed address mode
+        * (This will prevent a unintended write command to be detected by device)
+        */
+       for (i = 0; i < INIT_ADAPT_LOOP; i++) {
+               /* If device was not power-cycled it will stay in 32bit mode with
+                * response-delay-all bit set.  Alternate the iteration so that
+                * read either with or without response-delay for F0 to succeed.
+                */
+               bcmspi_find_curr_mode(sd);
+               sd->resp_delay_all = (i & 0x1) ? TRUE : FALSE;
+
+               bcmspi_find_curr_mode(sd);
+               sd->dwordmode = TRUE;
+
+               bcmspi_find_curr_mode(sd);
+               sd->dwordmode = FALSE;
+       }
+
+       /* Bail out, device not detected */
+       if (i == INIT_ADAPT_LOOP)
+               return FALSE;
+
+       /* Softreset the spid logic */
+       if ((sd->dwordmode) || (sd->wordlen == 4)) {
+               bcmspi_card_regwrite(sd, 0, SPID_RESET_BP, 1, RESET_ON_WLAN_BP_RESET|RESET_SPI);
+               bcmspi_card_regread(sd, 0, SPID_RESET_BP, 1, &regdata);
+               sd_trace(("reset reg read = 0x%x\n", regdata));
+               sd_trace(("dwordmode = %d, wordlen = %d, resp_delay_all = %d\n", sd->dwordmode,
+                      sd->wordlen, sd->resp_delay_all));
+               /* Restore default state after softreset */
+               sd->wordlen = 2;
+               sd->dwordmode = FALSE;
+       }
+
+       if (sd->wordlen == 4) {
+               if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) !=
+                    SUCCESS)
+                               return FALSE;
+               if (regdata == TEST_RO_DATA_32BIT_LE) {
+                       sd_trace(("Spid is already in 32bit LE mode. Value read = 0x%x\n",
+                                 regdata));
+                       sd_trace(("Spid power was left on.\n"));
+               } else {
+                       sd_err(("Spid power was left on but signature read failed."
+                               " Value read = 0x%x\n", regdata));
+                       return FALSE;
+               }
+       } else {
+               sd->wordlen = 2;
+
+#define CTRL_REG_DEFAULT       0x00010430 /* according to the host m/c */
+
+               wrregdata = (CTRL_REG_DEFAULT);
+               sd->resp_delay_all = TRUE;
+               if (sd->resp_delay_all == TRUE) {
+                       /* Enable response delay for all */
+                       wrregdata |= (RESP_DELAY_ALL << 16);
+                       /* Program response delay value */
+                       wrregdata &= 0xffff00ff;
+                       wrregdata |= (F1_RESPONSE_DELAY << 8);
+                       sd->prev_fun = SPI_FUNC_1;
+                       bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
+               }
+
+               if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
+                       return FALSE;
+               sd_trace(("(we are still in 16bit mode) 32bit READ LE regdata = 0x%x\n", regdata));
+
+#ifndef HSMODE
+               wrregdata |= (CLOCK_PHASE | CLOCK_POLARITY);
+               wrregdata &= ~HIGH_SPEED_MODE;
+               bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
+#endif /* HSMODE */
+
+               for (i = 0; i < INIT_ADAPT_LOOP; i++) {
+                       if ((regdata == 0xfdda7d5b) || (regdata == 0xfdda7d5a)) {
+                               sd_trace(("0xfeedbead was leftshifted by 1-bit.\n"));
+                               if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4,
+                                    &regdata)) != SUCCESS)
+                                       return FALSE;
+                       }
+                       OSL_DELAY(1000);
+               }
+
+
+               /* Change to host controller intr-polarity of active-low */
+               wrregdata &= ~INTR_POLARITY;
+               sd_trace(("(we are still in 16bit mode) 32bit Write LE reg-ctrl-data = 0x%x\n",
+                       wrregdata));
+               /* Change to 32bit mode */
+               wrregdata |= WORD_LENGTH_32;
+               bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata);
+
+               /* Change command/data packaging in 32bit LE mode */
+               sd->wordlen = 4;
+
+               if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
+                       return FALSE;
+
+               if (regdata == TEST_RO_DATA_32BIT_LE) {
+                       sd_trace(("Read spid passed. Value read = 0x%x\n", regdata));
+                       sd_trace(("Spid had power-on cycle OR spi was soft-resetted \n"));
+               } else {
+                       sd_err(("Stale spid reg values read as it was kept powered. Value read ="
+                         "0x%x\n", regdata));
+                       return FALSE;
+               }
+       }
+
+
+       return TRUE;
+}
+
+static bool
+bcmspi_test_card(sdioh_info_t *sd)
+{
+       uint32 regdata;
+       int status;
+
+       if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, &regdata)) != SUCCESS)
+               return FALSE;
+
+       if (regdata == (TEST_RO_DATA_32BIT_LE))
+               sd_trace(("32bit LE regdata = 0x%x\n", regdata));
+       else {
+               sd_trace(("Incorrect 32bit LE regdata = 0x%x\n", regdata));
+               return FALSE;
+       }
+
+
+#define RW_PATTERN1    0xA0A1A2A3
+#define RW_PATTERN2    0x4B5B6B7B
+
+       regdata = RW_PATTERN1;
+       if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
+               return FALSE;
+       regdata = 0;
+       if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
+               return FALSE;
+       if (regdata != RW_PATTERN1) {
+               sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
+                       RW_PATTERN1, regdata));
+               return FALSE;
+       } else
+               sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
+
+       regdata = RW_PATTERN2;
+       if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS)
+               return FALSE;
+       regdata = 0;
+       if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, &regdata)) != SUCCESS)
+               return FALSE;
+       if (regdata != RW_PATTERN2) {
+               sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n",
+                       RW_PATTERN2, regdata));
+               return FALSE;
+       } else
+               sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata));
+
+       return TRUE;
+}
+
+static int
+bcmspi_driver_init(sdioh_info_t *sd)
+{
+       sd_trace(("%s\n", __FUNCTION__));
+       if ((bcmspi_host_init(sd)) != SUCCESS) {
+               return ERROR;
+       }
+
+       if (bcmspi_client_init(sd) != SUCCESS) {
+               return ERROR;
+       }
+
+       return SUCCESS;
+}
+
+/* Read device reg */
+static int
+bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
+{
+       int status;
+       uint32 cmd_arg, dstatus;
+
+       ASSERT(regsize);
+
+       if (func == 2)
+               sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
+
+       cmd_arg = 0;
+       cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
+       cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);       /* Incremental access */
+       cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+       cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+       cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
+
+       sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+       sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func,
+                regaddr, *data));
+
+       if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize))
+           != SUCCESS)
+               return status;
+
+       bcmspi_cmd_getdstatus(sd, &dstatus);
+       if (dstatus)
+               sd_trace(("dstatus =0x%x\n", dstatus));
+
+       return SUCCESS;
+}
+
+static int
+bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data)
+{
+
+       int status;
+       uint32 cmd_arg;
+       uint32 dstatus;
+
+       ASSERT(regsize);
+
+       if (func == 2)
+               sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n"));
+
+       cmd_arg = 0;
+       cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0);
+       cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0);       /* Fixed access */
+       cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+       cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+       cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize);
+
+       sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+
+       if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize))
+           != SUCCESS)
+               return status;
+
+       sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func,
+                regaddr, *data));
+
+       bcmspi_cmd_getdstatus(sd, &dstatus);
+       sd_trace(("dstatus =0x%x\n", dstatus));
+       return SUCCESS;
+}
+
+/* write a device register */
+static int
+bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data)
+{
+       int status;
+       uint32 cmd_arg, dstatus;
+
+       ASSERT(regsize);
+
+       cmd_arg = 0;
+
+       cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
+       cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);       /* Incremental access */
+       cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+       cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+       cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize);
+
+       sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+       sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 1, func,
+                regaddr, data));
+
+
+       if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, regsize))
+           != SUCCESS)
+               return status;
+
+       bcmspi_cmd_getdstatus(sd, &dstatus);
+       if (dstatus)
+               sd_trace(("dstatus =0x%x\n", dstatus));
+
+       return SUCCESS;
+}
+
+/* write a device register - 1 byte */
+static int
+bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 *byte)
+{
+       int status;
+       uint32 cmd_arg;
+       uint32 dstatus;
+       uint32 data = (uint32)(*byte);
+
+       cmd_arg = 0;
+       cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+       cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);       /* Incremental access */
+       cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr);
+       cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1);
+       cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1);
+
+       sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+       sd_trace(("%s: func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, func,
+                regaddr, data));
+
+       if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma,
+                                     cmd_arg, &data, 1)) != SUCCESS) {
+               return status;
+       }
+
+       bcmspi_cmd_getdstatus(sd, &dstatus);
+       if (dstatus)
+               sd_trace(("dstatus =0x%x\n", dstatus));
+
+       return SUCCESS;
+}
+
+void
+bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer)
+{
+       *dstatus_buffer = sd->card_dstatus;
+}
+
+/* 'data' is of type uint32 whereas other buffers are of type uint8 */
+static int
+bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg,
+                uint32 *data, uint32 datalen)
+{
+       uint32  i, j;
+       uint8   resp_delay = 0;
+       int     err = SUCCESS;
+       uint32  hostlen;
+       uint32 spilen = 0;
+       uint32 dstatus_idx = 0;
+       uint16 templen, buslen, len, *ptr = NULL;
+
+       sd_trace(("spi cmd = 0x%x\n", cmd_arg));
+
+       if (DWORDMODE_ON) {
+               spilen = GFIELD(cmd_arg, SPI_LEN);
+               if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_0) ||
+                   (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_1))
+                       dstatus_idx = spilen * 3;
+
+               if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
+                   (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
+                       spilen = spilen << 2;
+                       dstatus_idx = (spilen % 16) ? (16 - (spilen % 16)) : 0;
+                       /* convert len to mod16 size */
+                       spilen = ROUNDUP(spilen, 16);
+                       cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
+               }
+       }
+
+       /* Set up and issue the SPI command.  MSByte goes out on bus first.  Increase datalen
+        * according to the wordlen mode(16/32bit) the device is in.
+        */
+       if (sd->wordlen == 4) { /* 32bit spid */
+               *(uint32 *)spi_outbuf = bcmswap32(cmd_arg);
+               if (datalen & 0x3)
+                       datalen += (4 - (datalen & 0x3));
+       } else if (sd->wordlen == 2) { /* 16bit spid */
+               *(uint16 *)spi_outbuf = bcmswap16(cmd_arg & 0xffff);
+               *(uint16 *)&spi_outbuf[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16);
+               if (datalen & 0x1)
+                       datalen++;
+               if (datalen < 4)
+                       datalen = ROUNDUP(datalen, 4);
+       } else {
+               sd_err(("Host is %d bit spid, could not create SPI command.\n",
+                       8 * sd->wordlen));
+               return ERROR;
+       }
+
+       /* for Write, put the data into the output buffer */
+       if (GFIELD(cmd_arg, SPI_RW_FLAG) == 1) {
+               /* We send len field of hw-header always a mod16 size, both from host and dongle */
+               if (DWORDMODE_ON) {
+                       if (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) {
+                               ptr = (uint16 *)&data[0];
+                               templen = *ptr;
+                               /* ASSERT(*ptr == ~*(ptr + 1)); */
+                               templen = ROUNDUP(templen, 16);
+                               *ptr = templen;
+                               sd_trace(("actual tx len = %d\n", (uint16)(~*(ptr+1))));
+                       }
+               }
+
+               if (datalen != 0) {
+                       for (i = 0; i < datalen/4; i++) {
+                               if (sd->wordlen == 4) { /* 32bit spid */
+                                       *(uint32 *)&spi_outbuf[i * 4 + CMDLEN] =
+                                               bcmswap32(data[i]);
+                               } else if (sd->wordlen == 2) { /* 16bit spid */
+                                       *(uint16 *)&spi_outbuf[i * 4 + CMDLEN] =
+                                               bcmswap16(data[i] & 0xffff);
+                                       *(uint16 *)&spi_outbuf[i * 4 + CMDLEN + 2] =
+                                               bcmswap16((data[i] & 0xffff0000) >> 16);
+                               }
+                       }
+               }
+       }
+
+       /* Append resp-delay number of bytes and clock them out for F0/1/2 reads. */
+       if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) {
+               int func = GFIELD(cmd_arg, SPI_FUNCTION);
+               switch (func) {
+                       case 0:
+                               resp_delay = sd->resp_delay_all ? F0_RESPONSE_DELAY : 0;
+                               break;
+                       case 1:
+                               resp_delay = F1_RESPONSE_DELAY;
+                               break;
+                       case 2:
+                               resp_delay = sd->resp_delay_all ? F2_RESPONSE_DELAY : 0;
+                               break;
+                       default:
+                               ASSERT(0);
+                               break;
+               }
+               /* Program response delay */
+               bcmspi_prog_resp_delay(sd, func, resp_delay);
+       }
+
+       /* +4 for cmd and +4 for dstatus */
+       hostlen = datalen + 8 + resp_delay;
+       hostlen += dstatus_idx;
+       hostlen += (4 - (hostlen & 0x3));
+       spi_sendrecv(sd, spi_outbuf, spi_inbuf, hostlen);
+
+       /* for Read, get the data into the input buffer */
+       if (datalen != 0) {
+               if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) { /* if read cmd */
+                       for (j = 0; j < datalen/4; j++) {
+                               if (sd->wordlen == 4) { /* 32bit spid */
+                                       data[j] = bcmswap32(*(uint32 *)&spi_inbuf[j * 4 +
+                                                   CMDLEN + resp_delay]);
+                               } else if (sd->wordlen == 2) { /* 16bit spid */
+                                       data[j] = (bcmswap16(*(uint16 *)&spi_inbuf[j * 4 +
+                                                   CMDLEN + resp_delay])) |
+                                                ((bcmswap16(*(uint16 *)&spi_inbuf[j * 4 +
+                                                   CMDLEN + resp_delay + 2])) << 16);
+                               }
+                       }
+
+                       if ((DWORDMODE_ON) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
+                               ptr = (uint16 *)&data[0];
+                               templen = *ptr;
+                               buslen = len = ~(*(ptr + 1));
+                               buslen = ROUNDUP(buslen, 16);
+                               /* populate actual len in hw-header */
+                               if (templen == buslen)
+                                       *ptr = len;
+                       }
+               }
+       }
+
+       /* Restore back the len field of the hw header */
+       if (DWORDMODE_ON) {
+               if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) &&
+                   (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) {
+                       ptr = (uint16 *)&data[0];
+                       *ptr = (uint16)(~*(ptr+1));
+               }
+       }
+
+       dstatus_idx += (datalen + CMDLEN + resp_delay);
+       /* Last 4bytes are dstatus.  Device is configured to return status bits. */
+       if (sd->wordlen == 4) { /* 32bit spid */
+               sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf[dstatus_idx]);
+       } else if (sd->wordlen == 2) { /* 16bit spid */
+               sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx]) |
+                                  (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx + 2]) << 16));
+       } else {
+               sd_err(("Host is %d bit machine, could not read SPI dstatus.\n",
+                       8 * sd->wordlen));
+               return ERROR;
+       }
+       if (sd->card_dstatus == 0xffffffff) {
+               sd_err(("looks like not a GSPI device or device is not powered.\n"));
+       }
+
+       err = bcmspi_update_stats(sd, cmd_arg);
+
+       return err;
+
+}
+
+static int
+bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo,
+                uint32 addr, int nbytes, uint32 *data)
+{
+       int status;
+       uint32 cmd_arg;
+       bool write = rw == SDIOH_READ ? 0 : 1;
+       uint retries = 0;
+
+       bool enable;
+       uint32  spilen;
+
+       cmd_arg = 0;
+
+       ASSERT(nbytes);
+       ASSERT(nbytes <= sd->client_block_size[func]);
+
+       if (write) sd->t_cnt++; else sd->r_cnt++;
+
+       if (func == 2) {
+               /* Frame len check limited by gSPI. */
+               if ((nbytes > 2000) && write) {
+                       sd_trace((">2KB write: F2 wr of %d bytes\n", nbytes));
+               }
+               /* ASSERT(nbytes <= 2048); Fix bigger len gspi issue and uncomment. */
+               /* If F2 fifo on device is not ready to receive data, don't do F2 transfer */
+               if (write) {
+                       uint32 dstatus;
+                       /* check F2 ready with cached one */
+                       bcmspi_cmd_getdstatus(sd, &dstatus);
+                       if ((dstatus & STATUS_F2_RX_READY) == 0) {
+                               retries = WAIT_F2RXFIFORDY;
+                               enable = 0;
+                               while (retries-- && !enable) {
+                                       OSL_DELAY(WAIT_F2RXFIFORDY_DELAY * 1000);
+                                       bcmspi_card_regread(sd, SPI_FUNC_0, SPID_STATUS_REG, 4,
+                                                          &dstatus);
+                                       if (dstatus & STATUS_F2_RX_READY)
+                                               enable = TRUE;
+                               }
+                               if (!enable) {
+                                       struct spierrstats_t *spierrstats = &sd->spierrstats;
+                                       spierrstats->f2rxnotready++;
+                                       sd_err(("F2 FIFO is not ready to receive data.\n"));
+                                       return ERROR;
+                               }
+                               sd_trace(("No of retries on F2 ready %d\n",
+                                       (WAIT_F2RXFIFORDY - retries)));
+                       }
+               }
+       }
+
+       /* F2 transfers happen on 0 addr */
+       addr = (func == 2) ? 0 : addr;
+
+       /* In pio mode buffer is read using fixed address fifo in func 1 */
+       if ((func == 1) && (fifo))
+               cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0);
+       else
+               cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1);
+
+       cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func);
+       cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, addr);
+       cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, write);
+       spilen = sd->data_xfer_count = MIN(sd->client_block_size[func], nbytes);
+       if ((sd->dwordmode == TRUE) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) {
+               /* convert len to mod4 size */
+               spilen = spilen + ((spilen & 0x3) ? (4 - (spilen & 0x3)): 0);
+               cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2));
+       } else
+               cmd_arg = SFIELD(cmd_arg, SPI_LEN, spilen);
+
+       if ((func == 2) && (fifo == 1)) {
+               sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
+                         __FUNCTION__, write ? "Wr" : "Rd", func, "INCR",
+                         addr, nbytes, sd->r_cnt, sd->t_cnt));
+       }
+
+       sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg));
+       sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n",
+                __FUNCTION__, write ? "Wd" : "Rd", func, "INCR",
+                addr, nbytes, sd->r_cnt, sd->t_cnt));
+
+
+       if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg,
+            data, nbytes)) != SUCCESS) {
+               sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__,
+                       (write ? "write" : "read")));
+               return status;
+       }
+
+       /* gSPI expects that hw-header-len is equal to spi-command-len */
+       if ((func == 2) && (rw == SDIOH_WRITE) && (sd->dwordmode == FALSE)) {
+               ASSERT((uint16)sd->data_xfer_count == (uint16)(*data & 0xffff));
+               ASSERT((uint16)sd->data_xfer_count == (uint16)(~((*data & 0xffff0000) >> 16)));
+       }
+
+       if ((nbytes > 2000) && !write) {
+               sd_trace((">2KB read: F2 rd of %d bytes\n", nbytes));
+       }
+
+       return SUCCESS;
+}
+
+/* Reset and re-initialize the device */
+int
+sdioh_sdio_reset(sdioh_info_t *si)
+{
+       si->card_init_done = FALSE;
+       return bcmspi_client_init(si);
+}
index 95b334fd62f2702158ac9b6cb11dcb45c67d895b..2be7ea08a40c6806e67727c5f316f9d3f77df368 100644 (file)
@@ -24,7 +24,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.9 2011/01/14 22:40:45 Exp $
+ * $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.7 2010/11/12 22:48:36 Exp $
  */
 
 /****************
@@ -165,7 +165,7 @@ typedef struct dhd_pub {
        char * pktfilter[100];
        int pktfilter_count;
 
-       wl_country_t dhd_cspec;         /* Current Locale info */
+       uint8 country_code[WLC_CNTRY_BUF_SZ];
        char eventmask[WL_EVENTING_MASK_LEN];
 
 } dhd_pub_t;
@@ -180,7 +180,7 @@ typedef struct dhd_pub {
                                wait_event_interruptible_timeout(a, FALSE, HZ/100); \
                        } \
                }       while (0)
-       #define DHD_PM_RESUME_WAIT(a)           _DHD_PM_RESUME_WAIT(a, 200)
+       #define DHD_PM_RESUME_WAIT(a)           _DHD_PM_RESUME_WAIT(a, 30)
        #define DHD_PM_RESUME_WAIT_FOREVER(a)   _DHD_PM_RESUME_WAIT(a, ~0)
        #define DHD_PM_RESUME_RETURN_ERROR(a)   do { if (dhd_mmc_suspend) return a; } while (0)
        #define DHD_PM_RESUME_RETURN            do { if (dhd_mmc_suspend) return; } while (0)
@@ -215,20 +215,6 @@ typedef struct dhd_pub {
 
 #define DHD_IF_VIF     0x01    /* Virtual IF (Hidden from user) */
 
-inline static void NETIF_ADDR_LOCK(struct net_device *dev)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
-       netif_addr_lock_bh(dev);
-#endif
-}
-
-inline static void NETIF_ADDR_UNLOCK(struct net_device *dev)
-{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
-       netif_addr_unlock_bh(dev);
-#endif
-}
-
 /* Wakelock Functions */
 extern int dhd_os_wake_lock(dhd_pub_t *pub);
 extern int dhd_os_wake_unlock(dhd_pub_t *pub);
@@ -449,16 +435,4 @@ extern char nv_path[MOD_PARAM_PATHLEN];
 extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
 extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
 
-/* dhd_commn arp offload wrapers */
-extern void dhd_arp_cleanup(dhd_pub_t *dhd);
-int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen);
-void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr);
-
-#define DHD_UNICAST_FILTER_NUM         0
-#define DHD_BROADCAST_FILTER_NUM       1
-#define DHD_MULTICAST4_FILTER_NUM      2
-#define DHD_MULTICAST6_FILTER_NUM      3
-extern int net_os_set_packet_filter(struct net_device *dev, int val);
-extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num);
-
 #endif /* _dhd_h_ */
index 61f6a6f393a977e96351b669f91204f67c4067d7..a68ad61c58b4f8d6596bb8e27f604d902b0e2c46 100644 (file)
@@ -41,6 +41,8 @@
 #include <dhd_bus.h>
 #include <dhd_dbg.h>
 
+uint8 wlan_mac_addr[ETHER_ADDR_LEN];
+
 extern int dhd_preinit_ioctls(dhd_pub_t *dhd);
 
 /* Packet alignment for most efficient SDIO (can change based on platform) */
@@ -502,6 +504,7 @@ dhd_prot_init(dhd_pub_t *dhd)
                return ret;
        }
        memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+        memcpy(wlan_mac_addr, buf, ETHER_ADDR_LEN);
 
        dhd_os_proto_unblock(dhd);
 
index f7cd372d68c808d83db952ffaf0ffbb33cc4c5af..47e29969126a107a6fbaeb2660f89946766683ff 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.25 2011-02-11 21:16:02 Exp $
+ * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.20 2010/12/20 23:37:28 Exp $
  */
 #include <typedefs.h>
 #include <osl.h>
@@ -39,6 +39,9 @@
 
 #include <wlioctl.h>
 
+#define CONFIG_BCM4329_FW_PATH   "/system/etc/firmware/fw_bcm4329.bin"
+#define CONFIG_BCM4329_NVRAM_PATH  "/system/etc/firmware/nvram_B23.txt"
+
 #ifdef SET_RANDOM_MAC_SOFTAP
 #include <linux/random.h>
 #include <linux/jiffies.h>
@@ -992,9 +995,6 @@ dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_
        wl_pkt_filter_enable_t  enable_parm;
        wl_pkt_filter_enable_t  * pkt_filterp;
 
-       if (!arg)
-               return;
-
        if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
                DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
                goto fail;
@@ -1068,9 +1068,6 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
        char                            *arg_save = 0, *arg_org = 0;
 #define BUF_SIZE               2048
 
-       if (!arg)
-               return;
-
        if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) {
                DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__));
                goto fail;
@@ -1226,82 +1223,6 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
 }
 #endif
 
-
-void dhd_arp_cleanup(dhd_pub_t *dhd)
-{
-#ifdef ARP_OFFLOAD_SUPPORT
-       int ret = 0;
-       int iov_len = 0;
-       char iovbuf[128];
-
-       if (dhd == NULL) return;
-
-       dhd_os_proto_block(dhd);
-
-       iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf));
-       if ((ret  = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0)
-               DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
-
-       iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf));
-       if ((ret  = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0)
-               DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
-
-       dhd_os_proto_unblock(dhd);
-
-#endif /* ARP_OFFLOAD_SUPPORT */
-}
-
-void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr)
-{
-#ifdef ARP_OFFLOAD_SUPPORT
-       int iov_len = 0;
-       char iovbuf[32];
-       int retcode;
-
-       dhd_os_proto_block(dhd);
-
-       iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, 4, iovbuf, sizeof(iovbuf));
-       retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len);
-
-       dhd_os_proto_unblock(dhd);
-
-       if (retcode)
-               DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n",
-               __FUNCTION__, retcode));
-       else
-               DHD_TRACE(("%s: ARP ipaddr entry added\n",
-               __FUNCTION__));
-#endif /* ARP_OFFLOAD_SUPPORT */
-}
-
-
-int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
-{
-#ifdef ARP_OFFLOAD_SUPPORT
-       int retcode;
-       int iov_len = 0;
-
-       if (!buf)
-               return -1;
-
-       dhd_os_proto_block(dhd);
-
-       iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen);
-       retcode = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, buflen);
-
-       dhd_os_proto_unblock(dhd);
-
-       if (retcode) {
-               DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n",
-               __FUNCTION__, retcode));
-
-               return -1;
-       }
-#endif /* ARP_OFFLOAD_SUPPORT */
-       return 0;
-}
-
-
 int
 dhd_preinit_ioctls(dhd_pub_t *dhd)
 {
@@ -1368,11 +1289,15 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        }
 #endif /* SET_RANDOM_MAC_SOFTAP */
 
-       /* Set Country code */
-       if (dhd->dhd_cspec.ccode[0] != 0) {
-               bcm_mkiovar("country", (char *)&dhd->dhd_cspec, \
-                       sizeof(wl_country_t), iovbuf, sizeof(iovbuf));
-               if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
+       /* Set Country code 
+         * "US" ---> 11 channels, this is default setting. 
+         * "EU" ---> 13 channels
+         * "JP" ---> 14 channels
+         */
+        strcpy(dhd->country_code, "EU");
+       if (dhd->country_code[0] != 0) {
+               if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY,
+                       dhd->country_code, sizeof(dhd->country_code)) < 0) {
                        DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__));
                }
        }
@@ -1979,7 +1904,6 @@ int dhd_pno_clean(dhd_pub_t *dhd)
 int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
 {
        char iovbuf[128];
-       uint8 bssid[6];
        int ret = -1;
 
        if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) {
@@ -1987,20 +1911,6 @@ int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
                return ret;
        }
 
-       memset(iovbuf, 0, sizeof(iovbuf));
-
-       /* Check if disassoc to enable pno */
-       if ((pfn_enabled) && \
-               ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_GET_BSSID, \
-                                (char *)&bssid, ETHER_ADDR_LEN)) == BCME_NOTASSOCIATED)) {
-               DHD_TRACE(("%s pno enable called in disassoc mode\n", __FUNCTION__));
-       }
-       else if (pfn_enabled) {
-               DHD_ERROR(("%s pno enable called in assoc mode ret=%d\n", \
-                       __FUNCTION__, ret));
-               return ret;
-       }
-
        /* Enable/disable PNO */
        if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) {
                if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) {
@@ -2019,8 +1929,7 @@ int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
 
 /* Function to execute combined scan */
 int
-dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, \
-                       int pno_repeat, int pno_freq_expo_max)
+dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr)
 {
        int err = -1;
        char iovbuf[128];
@@ -2065,23 +1974,12 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
        pfn_param.version = htod32(PFN_VERSION);
        pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
 
-       /* check and set extra pno params */
-       if ((pno_repeat != 0) || (pno_freq_expo_max != 0)) {
-               pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT);
-               pfn_param.repeat_scan = htod32(pno_repeat);
-               pfn_param.max_freq_adjust = htod32(pno_freq_expo_max);
-       }
-
        /* set up pno scan fr */
        if (scan_fr  != 0)
                pfn_param.scan_freq = htod32(scan_fr);
 
-       if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) {
-               DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC));
-               return err;
-       }
-       if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) {
-               DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC));
+       if (pfn_param.scan_freq > PNO_SCAN_MAX_FW) {
+               DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW));
                return err;
        }
 
@@ -2093,6 +1991,8 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
 
                pfn_element.bss_type = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
                pfn_element.auth = (DOT11_OPEN_SYSTEM);
+               pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
+               pfn_element.wsec = htod32(0);
                pfn_element.infra = htod32(1);
 
                memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len);
@@ -2108,9 +2008,8 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr,
                                return err;
                        }
                        else
-                               DHD_ERROR(("%s set OK with PNO time=%d repeat=%d max_adjust=%d\n", \
-                                       __FUNCTION__, pfn_param.scan_freq, \
-                                       pfn_param.repeat_scan, pfn_param.max_freq_adjust));
+                               DHD_ERROR(("%s set OK with PNO time=%d\n", __FUNCTION__, \
+                                                               pfn_param.scan_freq));
                }
                else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err));
        }
index 4d32863e29829c855a5f7357cd622c1efe428760..8c6ec470b8bd2efb54c5811f3fa90a1fffaeba27 100644 (file)
@@ -20,7 +20,7 @@
 * software in any way with any other Broadcom software provided under a license
 * other than the GPL, without Broadcom's express prior written consent.
 *
-* $Id: dhd_custom_gpio.c,v 1.1.4.8.4.4 2011/01/20 20:23:09 Exp $
+* $Id: dhd_custom_gpio.c,v 1.1.4.8.4.1 2010/09/02 23:13:16 Exp $
 */
 
 
@@ -47,7 +47,6 @@ int wifi_set_carddetect(int on);
 int wifi_set_power(int on, unsigned long msec);
 int wifi_get_irq_number(unsigned long *irq_flags_ptr);
 int wifi_get_mac_addr(unsigned char *buf);
-void *wifi_get_country_code(char *ccode);
 #endif
 
 #if defined(OOB_INTR_ONLY)
@@ -178,95 +177,3 @@ dhd_custom_get_mac_address(unsigned char *buf)
        return ret;
 }
 #endif /* GET_CUSTOM_MAC_ENABLE */
-
-/* Customized Locale table : OPTIONAL feature */
-const struct cntry_locales_custom translate_custom_table[] = {
-/* Table should be filled out based on custom platform regulatory requirement */
-#ifdef EXAMPLE_TABLE
-       {"",   "XY", 4},  /* universal */
-       {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
-       {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
-       {"EU", "EU", 5},  /* European union countries */
-       {"AT", "EU", 5},
-       {"BE", "EU", 5},
-       {"BG", "EU", 5},
-       {"CY", "EU", 5},
-       {"CZ", "EU", 5},
-       {"DK", "EU", 5},
-       {"EE", "EU", 5},
-       {"FI", "EU", 5},
-       {"FR", "EU", 5},
-       {"DE", "EU", 5},
-       {"GR", "EU", 5},
-       {"HU", "EU", 5},
-       {"IE", "EU", 5},
-       {"IT", "EU", 5},
-       {"LV", "EU", 5},
-       {"LI", "EU", 5},
-       {"LT", "EU", 5},
-       {"LU", "EU", 5},
-       {"MT", "EU", 5},
-       {"NL", "EU", 5},
-       {"PL", "EU", 5},
-       {"PT", "EU", 5},
-       {"RO", "EU", 5},
-       {"SK", "EU", 5},
-       {"SI", "EU", 5},
-       {"ES", "EU", 5},
-       {"SE", "EU", 5},
-       {"GB", "EU", 5},  /* input ISO "GB" to : EU regrev 05 */
-       {"IL", "IL", 0},
-       {"CH", "CH", 0},
-       {"TR", "TR", 0},
-       {"NO", "NO", 0},
-       {"KR", "XY", 3},
-       {"AU", "XY", 3},
-       {"CN", "XY", 3},  /* input ISO "CN" to : XY regrev 03 */
-       {"TW", "XY", 3},
-       {"AR", "XY", 3},
-       {"MX", "XY", 3}
-#endif /* EXAMPLE_TABLE */
-};
-
-
-/* Customized Locale convertor
-*  input : ISO 3166-1 country abbreviation
-*  output: customized cspec
-*/
-void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
-{
-#ifdef CUSTOMER_HW2
-       struct cntry_locales_custom *cloc_ptr;
-
-       if (!cspec)
-               return;
-
-       cloc_ptr = wifi_get_country_code(country_iso_code);
-       if (cloc_ptr) {
-               strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ);
-               cspec->rev = cloc_ptr->custom_locale_rev;
-       }
-       return;
-#else
-       int size, i;
-
-       size = ARRAYSIZE(translate_custom_table);
-
-       if (cspec == 0)
-               return;
-
-       if (size == 0)
-               return;
-
-       for (i = 0; i < size; i++) {
-               if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
-                       memcpy(cspec->ccode, translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
-                       cspec->rev = translate_custom_table[i].custom_locale_rev;
-                       return;
-               }
-       }
-       memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ);
-       cspec->rev = translate_custom_table[0].custom_locale_rev;
-       return;
-#endif
-}
index 5c1384bdc2154cedb28989937253febb287e884b..be7298846bc72f91bddf6c581c19653837b3d95b 100644 (file)
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.40 2011/02/03 19:55:18 Exp $
+ * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.35 2010/11/17 03:13:21 Exp $
  */
 
+#ifdef CONFIG_WIFI_CONTROL_FUNC
+#include <linux/platform_device.h>
+#endif
 #include <typedefs.h>
 #include <linuxver.h>
 #include <osl.h>
 #include <linux/ethtool.h>
 #include <linux/fcntl.h>
 #include <linux/fs.h>
-#include <linux/inetdevice.h>
-#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
+#include <wifi_version.h>
 #include <epivers.h>
 #include <bcmutils.h>
 #include <bcmendian.h>
 #ifdef CONFIG_HAS_WAKELOCK
 #include <linux/wakelock.h>
 #endif
-#ifdef CUSTOMER_HW2
-#include <linux/platform_device.h>
-#ifdef CONFIG_WIFI_CONTROL_FUNC
-#include <linux/wlan_plat.h>
-static struct wifi_platform_data *wifi_control_data = NULL;
-#endif
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+//#include <linux/wlan_plat.h>
+#include <mach/board.h>
+
 struct semaphore wifi_control_sem;
 
+struct dhd_bus *g_bus;
+
+extern void bcm4329_power_save_exit(void);
+extern void bcm4329_power_save_init(void);
+
+static struct wifi_platform_data *wifi_control_data = NULL;
 static struct resource *wifi_irqres = NULL;
 
 int wifi_get_irq_number(unsigned long *irq_flags_ptr)
@@ -86,22 +92,18 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr)
 int wifi_set_carddetect(int on)
 {
        printk("%s = %d\n", __FUNCTION__, on);
-#ifdef CONFIG_WIFI_CONTROL_FUNC
        if (wifi_control_data && wifi_control_data->set_carddetect) {
                wifi_control_data->set_carddetect(on);
        }
-#endif
        return 0;
 }
 
 int wifi_set_power(int on, unsigned long msec)
 {
        printk("%s = %d\n", __FUNCTION__, on);
-#ifdef CONFIG_WIFI_CONTROL_FUNC
        if (wifi_control_data && wifi_control_data->set_power) {
                wifi_control_data->set_power(on);
        }
-#endif
        if (msec)
                mdelay(msec);
        return 0;
@@ -110,11 +112,9 @@ int wifi_set_power(int on, unsigned long msec)
 int wifi_set_reset(int on, unsigned long msec)
 {
        DHD_TRACE(("%s = %d\n", __FUNCTION__, on));
-#ifdef CONFIG_WIFI_CONTROL_FUNC
        if (wifi_control_data && wifi_control_data->set_reset) {
                wifi_control_data->set_reset(on);
        }
-#endif
        if (msec)
                mdelay(msec);
        return 0;
@@ -125,38 +125,20 @@ int wifi_get_mac_addr(unsigned char *buf)
        DHD_TRACE(("%s\n", __FUNCTION__));
        if (!buf)
                return -EINVAL;
-#ifdef CONFIG_WIFI_CONTROL_FUNC
        if (wifi_control_data && wifi_control_data->get_mac_addr) {
                return wifi_control_data->get_mac_addr(buf);
        }
-#endif
        return -EOPNOTSUPP;
 }
 
-void *wifi_get_country_code(char *ccode)
-{
-       DHD_TRACE(("%s\n", __FUNCTION__));
-#ifdef CONFIG_WIFI_CONTROL_FUNC
-       if (!ccode)
-               return NULL;
-       if (wifi_control_data && wifi_control_data->get_country_code) {
-               return wifi_control_data->get_country_code(ccode);
-       }
-#endif
-       return NULL;
-}
-
 static int wifi_probe(struct platform_device *pdev)
 {
-#ifdef CONFIG_WIFI_CONTROL_FUNC
        struct wifi_platform_data *wifi_ctrl =
                (struct wifi_platform_data *)(pdev->dev.platform_data);
 
-       wifi_control_data = wifi_ctrl;
-#endif
-
        DHD_TRACE(("## %s\n", __FUNCTION__));
        wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq");
+       wifi_control_data = wifi_ctrl;
 
        wifi_set_power(1, 0);   /* Power On */
        wifi_set_carddetect(1); /* CardDetect (0->1) */
@@ -167,34 +149,26 @@ static int wifi_probe(struct platform_device *pdev)
 
 static int wifi_remove(struct platform_device *pdev)
 {
-#ifdef CONFIG_WIFI_CONTROL_FUNC
        struct wifi_platform_data *wifi_ctrl =
                (struct wifi_platform_data *)(pdev->dev.platform_data);
 
-       wifi_control_data = wifi_ctrl;
-#endif
        DHD_TRACE(("## %s\n", __FUNCTION__));
+       wifi_control_data = wifi_ctrl;
+
        wifi_set_power(0, 0);   /* Power Off */
        wifi_set_carddetect(0); /* CardDetect (1->0) */
 
        up(&wifi_control_sem);
        return 0;
 }
-
 static int wifi_suspend(struct platform_device *pdev, pm_message_t state)
 {
        DHD_TRACE(("##> %s\n", __FUNCTION__));
-#if defined(OOB_INTR_ONLY)
-       bcmsdh_oob_intr_set(0);
-#endif /* (OOB_INTR_ONLY) */
        return 0;
 }
 static int wifi_resume(struct platform_device *pdev)
 {
        DHD_TRACE(("##> %s\n", __FUNCTION__));
-#if defined(OOB_INTR_ONLY)
-       bcmsdh_oob_intr_set(1);
-#endif /* (OOB_INTR_ONLY) */
        return 0;
 }
 
@@ -219,14 +193,8 @@ void wifi_del_dev(void)
        DHD_TRACE(("## Unregister platform_driver_register\n"));
        platform_driver_unregister(&wifi_device);
 }
-#endif /* defined(CUSTOMER_HW2) */
-
-static int dhd_device_event(struct notifier_block *this, unsigned long event,
-                               void *ptr);
+#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
 
-static struct notifier_block dhd_notifier = {
-       .notifier_call = dhd_device_event
-};
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
 #include <linux/suspend.h>
@@ -412,7 +380,7 @@ uint dhd_roam = 1;
 uint dhd_radio_up = 1;
 
 /* Network inteface name */
-char iface_name[IFNAMSIZ];
+char iface_name[IFNAMSIZ] = "wlan0";
 module_param_string(iface_name, iface_name, IFNAMSIZ, 0);
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0))
@@ -800,13 +768,13 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
        ASSERT(dhd && dhd->iflist[ifidx]);
        dev = dhd->iflist[ifidx]->net;
 
-       NETIF_ADDR_LOCK(dev);
+       netif_addr_lock_bh(dev);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
        cnt = netdev_mc_count(dev);
 #else
        cnt = dev->mc_count;
 #endif
-       NETIF_ADDR_UNLOCK(dev);
+       netif_addr_unlock_bh(dev);
 
        /* Determine initial value of allmulti flag */
        allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE;
@@ -826,7 +794,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
        memcpy(bufp, &cnt, sizeof(cnt));
        bufp += sizeof(cnt);
 
-       NETIF_ADDR_LOCK(dev);
+       netif_addr_lock_bh(dev);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
        netdev_for_each_mc_addr(ha, dev) {
                if (!cnt)
@@ -836,12 +804,12 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
                cnt--;
        }
 #else
-       for (mclist = dev->mc_list; (mclist && (cnt > 0)); cnt--, mclist = mclist->next) {
+       for (mclist = dev->mc_list;(mclist && (cnt > 0)); cnt--, mclist = mclist->next) {
                memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN);
                bufp += ETHER_ADDR_LEN;
        }
 #endif
-       NETIF_ADDR_UNLOCK(dev);
+       netif_addr_unlock_bh(dev);
 
        memset(&ioc, 0, sizeof(ioc));
        ioc.cmd = WLC_SET_VAR;
@@ -1939,11 +1907,10 @@ dhd_open(struct net_device *net)
        wl_control_wl_start(net);
 
        ifidx = dhd_net2idx(dhd, net);
+        if (ifidx == DHD_BAD_IF)
+                return -1;
        DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx));
 
-       if (ifidx == DHD_BAD_IF)
-               return -1;
-
        if ((dhd->iflist[ifidx]) && (dhd->iflist[ifidx]->state == WLC_E_IF_DEL)) {
                DHD_ERROR(("%s: Error: called when IF already deleted\n", __FUNCTION__));
                return -1;
@@ -2044,7 +2011,6 @@ dhd_del_if(dhd_info_t *dhd, int ifidx)
        up(&dhd->sysioc_sem);
 }
 
-
 dhd_pub_t *
 dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 {
@@ -2187,6 +2153,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
         */
        memcpy(netdev_priv(net), &dhd, sizeof(dhd));
 
+#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
+       g_bus = bus;
+#endif
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
        register_pm_notifier(&dhd_sleep_pm_notifier);
 #endif /*  (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
@@ -2198,8 +2167,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
        register_early_suspend(&dhd->early_suspend);
 #endif
 
-       register_inetaddr_notifier(&dhd_notifier);
-
        return &dhd->pub;
 
 fail:
@@ -2225,15 +2192,12 @@ dhd_bus_start(dhd_pub_t *dhdp)
 
        DHD_TRACE(("%s: \n", __FUNCTION__));
 
-       dhd_os_sdlock(dhdp);
-
        /* try to download image and nvram to the dongle */
        if  (dhd->pub.busstate == DHD_BUS_DOWN) {
                if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
                                                fw_path, nv_path))) {
                        DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n",
                                   __FUNCTION__, fw_path, nv_path));
-                       dhd_os_sdunlock(dhdp);
                        return -1;
                }
        }
@@ -2243,9 +2207,8 @@ dhd_bus_start(dhd_pub_t *dhdp)
        dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms);
 
        /* Bring up the bus */
-       if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) {
+       if ((ret = dhd_bus_init(&dhd->pub, TRUE)) != 0) {
                DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret));
-               dhd_os_sdunlock(dhdp);
                return ret;
        }
 #if defined(OOB_INTR_ONLY)
@@ -2254,7 +2217,6 @@ dhd_bus_start(dhd_pub_t *dhdp)
                dhd->wd_timer_valid = FALSE;
                del_timer_sync(&dhd->timer);
                DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__));
-               dhd_os_sdunlock(dhdp);
                return -ENODEV;
        }
 
@@ -2267,12 +2229,9 @@ dhd_bus_start(dhd_pub_t *dhdp)
                dhd->wd_timer_valid = FALSE;
                del_timer_sync(&dhd->timer);
                DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__));
-               dhd_os_sdunlock(dhdp);
                return -ENODEV;
        }
 
-       dhd_os_sdunlock(dhdp);
-
 #ifdef EMBEDDED_PLATFORM
        bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
        dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
@@ -2304,12 +2263,9 @@ dhd_bus_start(dhd_pub_t *dhdp)
 /* enable dongle roaming event */
        setbit(dhdp->eventmask, WLC_E_ROAM);
 
-       dhdp->pktfilter_count = 4;
+       dhdp->pktfilter_count = 1;
        /* Setup filter to allow only unicast */
        dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00";
-       dhdp->pktfilter[1] = NULL;
-       dhdp->pktfilter[2] = NULL;
-       dhdp->pktfilter[3] = NULL;
 #endif /* EMBEDDED_PLATFORM */
 
        /* Bus is ready, do any protocol initialization */
@@ -2363,48 +2319,6 @@ static struct net_device_ops dhd_ops_virt = {
 };
 #endif
 
-static int dhd_device_event(struct notifier_block *this, unsigned long event,
-                               void *ptr)
-{
-       struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
-       dhd_info_t *dhd;
-       dhd_pub_t *dhd_pub;
-
-       if (!ifa)
-               return NOTIFY_DONE;
-
-       dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev);
-       dhd_pub = &dhd->pub;
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31))
-       if (ifa->ifa_dev->dev->netdev_ops == &dhd_ops_pri) {
-#else
-       if (ifa->ifa_dev->dev->open == &dhd_open) {
-#endif
-               switch (event) {
-               case NETDEV_UP:
-                       DHD_TRACE(("%s: [%s] Up IP: 0x%x\n",
-                           __FUNCTION__, ifa->ifa_label, ifa->ifa_address));
-
-                       dhd_arp_cleanup(dhd_pub);
-                       break;
-
-               case NETDEV_DOWN:
-                       DHD_TRACE(("%s: [%s] Down IP: 0x%x\n",
-                           __FUNCTION__, ifa->ifa_label, ifa->ifa_address));
-
-                       dhd_arp_cleanup(dhd_pub);
-                       break;
-
-               default:
-                       DHD_TRACE(("%s: [%s] Event: %lu\n",
-                           __FUNCTION__, ifa->ifa_label, event));
-                       break;
-               }
-       }
-       return NOTIFY_DONE;
-}
-
 int
 dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
 {
@@ -2478,7 +2392,6 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
               dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
               dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
 
-
 #if defined(CONFIG_WIRELESS_EXT)
 #if defined(CONFIG_FIRST_SCAN)
 #ifdef SOFTAP
@@ -2544,8 +2457,6 @@ dhd_detach(dhd_pub_t *dhdp)
                        dhd_if_t *ifp;
                        int i;
 
-                       unregister_inetaddr_notifier(&dhd_notifier);
-
 #if defined(CONFIG_HAS_EARLYSUSPEND)
                        if (dhd->early_suspend.suspend)
                                unregister_early_suspend(&dhd->early_suspend);
@@ -2610,8 +2521,8 @@ dhd_detach(dhd_pub_t *dhdp)
        }
 }
 
-static void __exit
-dhd_module_cleanup(void)
+void
+rockchip_wifi_exit_module(void)
 {
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
@@ -2621,15 +2532,17 @@ dhd_module_cleanup(void)
 #endif
        /* Call customer gpio to turn off power with WL_REG_ON signal */
        dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
+       bcm4329_power_save_exit();
 }
 
-static int __init
-dhd_module_init(void)
+int
+rockchip_wifi_init_module(void)
 {
        int error;
 
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
+       printk("BCM4329 Wi-Fi driver (Powered by Rockchip,Ver %s) init.\n", BCM4329_DRV_VERSION);
        /* Sanity check on the module parameters */
        do {
                /* Both watchdog and DPC as tasklets are ok */
@@ -2688,6 +2601,8 @@ dhd_module_init(void)
                goto fail_2;
        }
 #endif
+       bcm4329_power_save_init();
+
        return error;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27))
 fail_2:
@@ -2705,8 +2620,23 @@ fail_0:
        return error;
 }
 
-module_init(dhd_module_init);
-module_exit(dhd_module_cleanup);
+//module_init(dhd_module_init);
+//module_exit(dhd_module_cleanup);
+int mv88w8686_if_sdio_init_module(void)
+{
+       return rockchip_wifi_init_module();
+}
+
+void mv88w8686_if_sdio_exit_module(void)
+{
+       rockchip_wifi_exit_module();
+}
+
+EXPORT_SYMBOL(rockchip_wifi_init_module);
+EXPORT_SYMBOL(rockchip_wifi_exit_module);
+EXPORT_SYMBOL(mv88w8686_if_sdio_init_module);
+EXPORT_SYMBOL(mv88w8686_if_sdio_exit_module);
+
 
 /*
  * OS specific functions required to implement DHD driver in OS independent way
@@ -3080,35 +3010,6 @@ int net_os_set_dtim_skip(struct net_device *dev, int val)
        return 0;
 }
 
-int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num)
-{
-       dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
-       char *filterp = NULL;
-       int ret = 0;
-
-       if (!dhd || (num == DHD_UNICAST_FILTER_NUM))
-               return ret;
-       if (num >= dhd->pub.pktfilter_count)
-               return -EINVAL;
-       if (add_remove) {
-               switch (num) {
-               case DHD_BROADCAST_FILTER_NUM:
-                       filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF";
-                       break;
-               case DHD_MULTICAST4_FILTER_NUM:
-                       filterp = "102 0 0 0 0xFFFFFF 0x01005E";
-                       break;
-               case DHD_MULTICAST6_FILTER_NUM:
-                       filterp = "103 0 0 0 0xFFFF 0x3333";
-                       break;
-               default:
-                       return -EINVAL;
-               }
-       }
-       dhd->pub.pktfilter[num] = filterp;
-       return ret;
-}
-
 int net_os_set_packet_filter(struct net_device *dev, int val)
 {
        dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
@@ -3162,12 +3063,11 @@ dhd_dev_pno_enable(struct net_device *dev,  int pfn_enabled)
 
 /* Linux wrapper to call common dhd_pno_set */
 int
-dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid,
-               ushort scan_fr, int pno_repeat, int pno_freq_expo_max)
+dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ushort  scan_fr)
 {
        dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
 
-       return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max));
+       return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr));
 }
 
 /* Linux wrapper to get  pno status */
@@ -3195,20 +3095,20 @@ int net_os_send_hang_message(struct net_device *dev)
        return ret;
 }
 
-void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec)
+void dhd_bus_country_set(struct net_device *dev, char *country_code)
 {
        dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
 
        if (dhd && dhd->pub.up)
-               memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t));
+               strncpy(dhd->pub.country_code, country_code, WLC_CNTRY_BUF_SZ);
 }
 
 char *dhd_bus_country_get(struct net_device *dev)
 {
        dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev);
 
-       if (dhd && (dhd->pub.dhd_cspec.ccode[0] != 0))
-               return dhd->pub.dhd_cspec.ccode;
+       if (dhd && (dhd->pub.country_code[0] != 0))
+               return dhd->pub.country_code;
        return NULL;
 }
 
index 1380dd389cf62e1fd1f8cc22ea8cf0ef7e9232e2..78dff1c489b8a8d31b82c122b14ca9c26f141a02 100644 (file)
@@ -428,6 +428,7 @@ static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start);
 
 #ifdef DHD_DEBUG_TRAP
 static int dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size);
+static int dhdsdio_mem_dump(dhd_bus_t *bus);
 #endif /* DHD_DEBUG_TRAP */
 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
 
@@ -1844,6 +1845,11 @@ dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size)
                DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
        }
 
+       if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
+                       /* Mem dump to a file on device */
+                       dhdsdio_mem_dump(bus);
+       }
+
 done:
        if (mbuffer)
                MFREE(bus->dhd->osh, mbuffer, msize);
@@ -1852,6 +1858,60 @@ done:
 
        return bcmerror;
 }
+
+static int
+dhdsdio_mem_dump(dhd_bus_t *bus)
+{
+       int ret = 0;
+       int size; /* Full mem size */
+       int start = 0; /* Start address */
+       int read_size = 0; /* Read size of each iteration */
+       uint8 *buf = NULL, *databuf = NULL;
+
+       /* Get full mem size */
+       size = bus->ramsize;
+       buf = MALLOC(bus->dhd->osh, size);
+       if (!buf) {
+               printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size);
+               return -1;
+       }
+
+       /* Read mem content */
+       printf("Dump dongle memory");
+       databuf = buf;
+       while (size)
+       {
+               read_size = MIN(MEMBLOCK, size);
+               if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size)))
+               {
+                       printf("%s: Error membytes %d\n", __FUNCTION__, ret);
+                       if (buf) {
+                               MFREE(bus->dhd->osh, buf, size);
+                       }
+                       return -1;
+               }
+               printf(".");
+
+               /* Decrement size and increment start address */
+               size -= read_size;
+               start += read_size;
+               databuf += read_size;
+       }
+       printf("Done\n");
+
+#ifdef DHD_DEBUG
+       /* free buf before return !!! */
+       if (write_to_file(bus->dhd, buf, bus->ramsize))
+       {
+               printf("%s: Error writing to files\n", __FUNCTION__);
+               return -1;
+       }
+       /* buf free handled in write_to_file, not here */
+#else
+       MFREE(bus->dhd->osh, buf, size);
+#endif
+       return 0;
+}
 #endif /* DHD_DEBUG_TRAP */
 
 #ifdef DHD_DEBUG
index cd66a9501cb61b214bd09493182c43771bbf724f..23ee514a7b6b8422fc9c90317533fe5703344ad1 100644 (file)
 
 #define        EPI_RC_NUMBER           248
 
-#define        EPI_INCREMENTAL_NUMBER  23
+#define        EPI_INCREMENTAL_NUMBER  18
 
 #define        EPI_BUILD_NUMBER        0
 
-#define        EPI_VERSION             4, 218, 248, 23
+#define        EPI_VERSION             4, 218, 248, 18
 
-#define        EPI_VERSION_NUM         0x04daf817
+#define        EPI_VERSION_NUM         0x04daf812
 
 
-#define        EPI_VERSION_STR         "4.218.248.23"
-#define        EPI_ROUTER_VERSION_STR  "4.219.248.23"
+#define        EPI_VERSION_STR         "4.218.248.18"
+#define        EPI_ROUTER_VERSION_STR  "4.219.248.18"
 
 #endif 
index 00c61f10782f608acf41d64788e341616b17430d..cd7725a70db41d3fdd4f509fe9ba706b0747f38d 100644 (file)
@@ -24,7 +24,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: wlioctl.h,v 1.601.4.15.2.14.2.62.4.3 2011/02/09 23:31:02 Exp $
+ * $Id: wlioctl.h,v 1.601.4.15.2.14.2.62.4.1 2010/11/17 03:09:28 Exp $
  */
 
 
@@ -254,11 +254,6 @@ typedef struct wl_join_params {
 
 #define WLC_CNTRY_BUF_SZ       4               
 
-typedef struct wl_country {
-       char country_abbrev[WLC_CNTRY_BUF_SZ];
-       int32 rev;
-       char ccode[WLC_CNTRY_BUF_SZ];
-} wl_country_t;
 
 typedef enum sup_auth_status {
        
@@ -862,7 +857,7 @@ typedef struct wl_ioctl {
 #define PM_MAX 1
 #define PM_FAST 2
 
-#define LISTEN_INTERVAL                        10
+#define LISTEN_INTERVAL                        20
 
 #define        INTERFERE_NONE  0       
 #define        NON_WLAN        1       
@@ -1314,16 +1309,12 @@ enum {
 #define ENABLE_BKGRD_SCAN_BIT  2
 #define IMMEDIATE_SCAN_BIT             3
 #define        AUTO_CONNECT_BIT                4
-#define        ENABLE_BD_SCAN_BIT              5
-#define ENABLE_ADAPTSCAN_BIT   6
 
 #define SORT_CRITERIA_MASK             0x01
 #define AUTO_NET_SWITCH_MASK   0x02
 #define ENABLE_BKGRD_SCAN_MASK 0x04
 #define IMMEDIATE_SCAN_MASK            0x08
 #define        AUTO_CONNECT_MASK               0x10
-#define ENABLE_BD_SCAN_MASK            0x20
-#define ENABLE_ADAPTSCAN_MASK  0x40
 
 #define PFN_VERSION                    1
 
@@ -1336,8 +1327,6 @@ typedef struct wl_pfn_param {
        int32 lost_network_timeout;     
        int16 flags;                    
        int16 rssi_margin;              
-       int32  repeat_scan;
-       int32  max_freq_adjust;
 } wl_pfn_param_t;
 
 typedef struct wl_pfn {
@@ -1347,12 +1336,14 @@ typedef struct wl_pfn {
        int32                   auth;                   
        uint32                  wpa_auth;               
        int32                   wsec;                   
+#ifdef WLPFN_AUTO_CONNECT
+       union {
+               wl_wsec_key_t   sec_key;                
+               wsec_pmk_t      wpa_sec_key;            
+       } pfn_security;
+#endif 
 } wl_pfn_t;
 
-#define PNO_SCAN_MAX_FW                508*1000
-#define PNO_SCAN_MAX_FW_SEC    PNO_SCAN_MAX_FW/1000
-#define PNO_SCAN_MIN_FW_SEC    10
-
 
 #define TOE_TX_CSUM_OL         0x00000001
 #define TOE_RX_CSUM_OL         0x00000002
index cf72a077bd9089a249a5332cbd05af2f969fe6aa..980416baf918c75482136812fcbe0b254959274a 100644 (file)
@@ -247,10 +247,8 @@ void*
 osl_pktget(osl_t *osh, uint len)
 {
        struct sk_buff *skb;
-       gfp_t flags;
 
-       flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
-       if ((skb = __dev_alloc_skb(len, flags))) {
+       if ((skb = dev_alloc_skb(len))) {
                skb_put(skb, len);
                skb->priority = 0;
 
index 434e584f830c2c6b5972a749afac356aac26c3fa..146dffd529764dab9e4257b9d633146e12cc6ca6 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.78 2011/02/11 21:27:52 Exp $
+ * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.69 2010/12/21 03:00:08 Exp $
  */
 
 
@@ -54,11 +54,10 @@ typedef const struct si_pub  si_t;
 #define WL_INFORM(x)
 #define WL_WSEC(x)
 #define WL_SCAN(x)
-#define WL_PNO(x)
 #define WL_TRACE_COEX(x)
 
 #include <wl_iw.h>
-
+#include <linux/wakelock.h>
 
 
 #ifndef IW_ENCODE_ALG_SM4
@@ -116,6 +115,10 @@ static int         g_onoff = G_WLAN_SET_ON;
 wl_iw_extra_params_t   g_wl_iw_params;
 static struct mutex    wl_cache_lock;
 
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+static bool use_non_dfs_channels = true;
+#endif
+
 extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status,
        uint32 reason, char* stringBuf, uint buflen);
 #include <bcmsdbus.h>
@@ -158,13 +161,12 @@ extern int dhd_wait_pend8021x(struct net_device *dev);
 #endif 
 
 static void *g_scan = NULL;
-static volatile uint g_scan_specified_ssid;
-static wlc_ssid_t g_specific_ssid;
+static volatile uint g_scan_specified_ssid;    
+static wlc_ssid_t g_specific_ssid;             
 
 static wlc_ssid_t g_ssid;
 
-bool btcoex_is_sco_active(struct net_device *dev);
-static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;
+static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl;  
 #if defined(CONFIG_FIRST_SCAN)
 static volatile uint g_first_broadcast_scan;
 static volatile uint g_first_counter_scans;
@@ -592,36 +594,6 @@ wl_iw_set_passive_scan(
        return error;
 }
 
-
-static int
-wl_iw_set_txpower(
-       struct net_device *dev,
-       struct iw_request_info *info,
-       union iwreq_data *wrqu,
-       char *extra
-)
-{
-       int error = 0;
-       char *p = extra;
-       int txpower = -1;
-
-       txpower = bcm_atoi(extra + strlen(TXPOWER_SET_CMD) + 1);
-       if ((txpower >= 0) && (txpower <= 127)) {
-               txpower |= WL_TXPWR_OVERRIDE;
-               txpower = htod32(txpower);
-
-               error = dev_wlc_intvar_set(dev, "qtxpower", txpower);
-               p += snprintf(p, MAX_WX_STRING, "OK");
-               WL_TRACE(("%s: set TXpower 0x%X is OK\n", __FUNCTION__, txpower));
-       } else {
-               WL_ERROR(("%s: set tx power failed\n", __FUNCTION__));
-               p += snprintf(p, MAX_WX_STRING, "FAIL");
-       }
-
-       wrqu->data.length = p - extra + 1;
-       return error;
-}
-
 static int
 wl_iw_get_macaddr(
        struct net_device *dev,
@@ -647,6 +619,31 @@ wl_iw_get_macaddr(
        return error;
 }
 
+static int
+wl_iw_set_country_code(struct net_device *dev, char *ccode)
+{
+       char country_code[WLC_CNTRY_BUF_SZ];
+       int ret = -1;
+
+       WL_TRACE(("%s\n", __FUNCTION__));
+       if (!ccode)
+               ccode = dhd_bus_country_get(dev);
+       strncpy(country_code, ccode, sizeof(country_code));
+       if (ccode && (country_code[0] != 0)) {
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+               if (use_non_dfs_channels && !strncmp(country_code, "US", 2))
+                       strncpy(country_code, "Q2", WLC_CNTRY_BUF_SZ);
+               if (!use_non_dfs_channels && !strncmp(country_code, "Q2", 2))
+                       strncpy(country_code, "US", WLC_CNTRY_BUF_SZ);
+#endif
+               ret = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, &country_code, sizeof(country_code));
+               if (ret >= 0) {
+                       WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
+                       dhd_bus_country_set(dev, &country_code[0]);
+               }
+       }
+       return ret;
+}
 
 static int
 wl_iw_set_country(
@@ -661,39 +658,25 @@ wl_iw_set_country(
        char *p = extra;
        int country_offset;
        int country_code_size;
-       wl_country_t cspec = {{0}, 0, {0}};
-       char smbuf[WLC_IOCTL_SMLEN];
 
-       cspec.rev = -1;
+       WL_TRACE(("%s\n", __FUNCTION__));
        memset(country_code, 0, sizeof(country_code));
-       memset(smbuf, 0, sizeof(smbuf));
 
        country_offset = strcspn(extra, " ");
        country_code_size = strlen(extra) - country_offset;
 
        if (country_offset != 0) {
-               strncpy(country_code, extra + country_offset +1,
+               strncpy(country_code, extra + country_offset + 1,
                        MIN(country_code_size, sizeof(country_code)));
-
-
-               memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
-               memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
-
-               get_customized_country_code((char *)&cspec.country_abbrev, &cspec);
-
-               if ((error = dev_iw_iovar_setbuf(dev, "country", &cspec, \
-                       sizeof(cspec), smbuf, sizeof(smbuf))) >= 0) {
+               error = wl_iw_set_country_code(dev, country_code);
+               if (error >= 0) {
                        p += snprintf(p, MAX_WX_STRING, "OK");
-                       WL_ERROR(("%s: set country for %s as %s rev %d is OK\n", \
-                               __FUNCTION__, country_code, cspec.ccode, cspec.rev));
-                       dhd_bus_country_set(dev, &cspec);
+                       WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code));
                        goto exit;
                }
        }
 
-       WL_ERROR(("%s: set country for %s as %s rev %d failed\n", \
-                       __FUNCTION__, country_code, cspec.ccode, cspec.rev));
-
+       WL_ERROR(("%s: set country %s failed code %d\n", __FUNCTION__, country_code, error));
        p += snprintf(p, MAX_WX_STRING, "FAIL");
 
 exit:
@@ -701,6 +684,33 @@ exit:
        return error;
 }
 
+static int
+wl_iw_get_country(
+        struct net_device *dev,
+        struct iw_request_info *info,
+        union iwreq_data *wrqu,
+        char *extra
+)
+{
+       char *ccode;
+       int current_channels;
+       
+       WL_TRACE(("%s\n", __FUNCTION__));
+
+       ccode = dhd_bus_country_get(dev);
+       if(ccode){
+               if(0 == strcmp(ccode, "Q2"))
+                       current_channels = 11;
+               else if(0 == strcmp(ccode, "EU"))
+                       current_channels = 13;
+               else if(0 == strcmp(ccode, "JP"))
+                       current_channels = 14;
+       }
+       sprintf(extra, "Scan-Channels = %d", current_channels);
+       printk("Get Channels return %d,(country code = %s)\n",current_channels, ccode); 
+       return 0;
+}
+
 #ifdef CUSTOMER_HW2
 static int
 wl_iw_set_power_mode(
@@ -755,40 +765,26 @@ wl_iw_set_power_mode(
 #endif
 
 
-bool btcoex_is_sco_active(struct net_device *dev)
+static bool btcoex_is_sco_active(struct net_device *dev)
 {
        int ioc_res = 0;
        bool res = false;
-       int sco_id_cnt = 0;
-       int param27;
-       int i;
-
-       for (i = 0; i < 12; i++) {
-
-               ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, &param27);
-
-               WL_TRACE_COEX(("%s, sample[%d], btc params: 27:%x\n",
-                       __FUNCTION__, i, param27));
+       int temp = 0;
 
-               if (ioc_res < 0) {
-                       WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__));
-                       break;
-               }
+       ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 4, &temp);
 
-               if ((param27 & 0x6) == 2) {
-                       sco_id_cnt++;
-               }
+       if (ioc_res == 0) {
+               WL_TRACE_COEX(("%s: read btc_params[4] = %x\n", __FUNCTION__, temp));
 
-               if (sco_id_cnt > 2) {
-                       WL_TRACE_COEX(("%s, sco/esco detected, pkt id_cnt:%d  samples:%d\n",
-                               __FUNCTION__, sco_id_cnt, i));
+               if ((temp > 0xea0) && (temp < 0xed8)) {
+                       WL_TRACE_COEX(("%s: BT SCO/eSCO is ACTIVE\n", __FUNCTION__));
                        res = true;
-                       break;
+               } else {
+                       WL_TRACE_COEX(("%s: BT SCO/eSCO is NOT detected\n", __FUNCTION__));
                }
-
-               msleep(5);
+       } else {
+               WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__));
        }
-
        return res;
 }
 
@@ -1074,6 +1070,21 @@ wl_iw_set_suspend(
        return ret;
 }
 
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+static int
+wl_iw_set_dfs_channels(
+       struct net_device *dev,
+       struct iw_request_info *info,
+       union iwreq_data *wrqu,
+       char *extra
+)
+{
+       use_non_dfs_channels = *(extra + strlen(SETDFSCHANNELS_CMD) + 1) - '0';
+       use_non_dfs_channels = (use_non_dfs_channels != 0) ? false : true;
+       wl_iw_set_country_code(dev, NULL);
+       return 0;
+}
+#endif
 
 int
 wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len)
@@ -1359,10 +1370,9 @@ wl_iw_set_pno_set(
        int nssid = 0;
        cmd_tlv_t *cmd_tlv_temp;
        char *str_ptr;
+       char *str_ptr_end;
        int tlv_size_left;
        int pno_time;
-       int pno_repeat;
-       int pno_freq_expo_max;
 
 #ifdef PNO_SET_DEBUG
        int i;
@@ -1376,10 +1386,6 @@ wl_iw_set_pno_set(
                                                        'G', 'O', 'O', 'G',
                                                        'T',
                                                        '1','E',
-                                                       'R',
-                                                       '2',
-                                                       'M',
-                                                       '2',
                                                        0x00
                                                        };
 #endif
@@ -1423,7 +1429,6 @@ wl_iw_set_pno_set(
 
        cmd_tlv_temp = (cmd_tlv_t *)str_ptr;
        memset(ssids_local, 0, sizeof(ssids_local));
-       pno_repeat = pno_freq_expo_max = 0;
 
        if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && \
                (cmd_tlv_temp->version == PNO_TLV_VERSION) && \
@@ -1444,28 +1449,9 @@ wl_iw_set_pno_set(
                                goto exit_proc;
                        }
                        str_ptr++;
-                       pno_time = simple_strtoul(str_ptr, &str_ptr, 16);
-                       WL_PNO(("%s: pno_time=%d\n", __FUNCTION__, pno_time));
-
-                       if (str_ptr[0] != 0) {
-                               if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) {
-                                       WL_ERROR(("%s pno repeat : corrupted field\n", \
-                                               __FUNCTION__));
-                                       goto exit_proc;
-                               }
-                               str_ptr++;
-                               pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16);
-                               WL_PNO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat));
-                               if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) {
-                                       WL_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n", \
-                                                       __FUNCTION__));
-                                       goto exit_proc;
-                               }
-                               str_ptr++;
-                               pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16);
-                               WL_PNO(("%s: pno_freq_expo_max=%d\n", \
-                                                       __FUNCTION__, pno_freq_expo_max));
-                       }
+                       pno_time = simple_strtoul(str_ptr, &str_ptr_end, 16);
+                       WL_ERROR((" got %d bytes left pno_time %d or %#x\n", \
+                                       tlv_size_left, pno_time, pno_time));
                }
        }
        else {
@@ -1473,7 +1459,7 @@ wl_iw_set_pno_set(
                goto exit_proc;
        }
 
-       res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max);
+       res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time);
 
 exit_proc:
        net_os_wake_unlock(dev);
@@ -1760,79 +1746,6 @@ int hstr_2_buf(const char *txt, u8 *buf, int len)
        return 0;
 }
 
-#if defined(SOFTAP) && defined(SOFTAP_TLV_CFG)
-
-static int wl_iw_softap_cfg_tlv(
-       struct net_device *dev,
-       struct iw_request_info *info,
-       union iwreq_data *wrqu,
-       char *extra
-)
-{
-       int res = -1;
-       char *str_ptr;
-       int tlv_size_left;
-
-
-#define SOFTAP_TLV_DEBUG  1
-#ifdef SOFTAP_TLV_DEBUG
-char softap_cmd_example[] = {
-
-       'S', 'O', 'F', 'T', 'A', 'P', 'S', 'E', 'T', ' ',
-
-       SOFTAP_TLV_PREFIX, SOFTAP_TLV_VERSION,
-       SOFTAP_TLV_SUBVERSION, SOFTAP_TLV_RESERVED,
-
-       TLV_TYPE_SSID,          9, 'B', 'R', 'C', 'M', ',', 'G', 'O', 'O', 'G',
-
-       TLV_TYPE_SECUR,         4, 'O', 'P', 'E', 'N',
-
-       TLV_TYPE_KEY,           4, 0x31, 0x32, 0x33, 0x34,
-
-       TLV_TYPE_CHANNEL,       4, 0x06, 0x00, 0x00, 0x00
-};
-#endif
-
-
-#ifdef SOFTAP_TLV_DEBUG
-       {
-       int i;
-       if (!(extra = kmalloc(sizeof(softap_cmd_example) +10, GFP_KERNEL)))
-               return -ENOMEM;
-       memcpy(extra, softap_cmd_example, sizeof(softap_cmd_example));
-       wrqu->data.length = sizeof(softap_cmd_example);
-       print_buf(extra, wrqu->data.length, 16);
-       for (i = 0; i < wrqu->data.length; i++)
-               printf("%c ", extra[i]);
-       printf("\n");
-       }
-#endif
-
-       WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n",
-               __FUNCTION__, info->cmd, info->flags,
-               wrqu->data.pointer, wrqu->data.length));
-
-       if (g_onoff == G_WLAN_SET_OFF) {
-               WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__));
-               return -1;
-       }
-
-       if (wrqu->data.length < (strlen(SOFTAP_SET_CMD) + sizeof(cmd_tlv_t))) {
-               WL_ERROR(("%s argument=%d  less %d\n", __FUNCTION__,
-                       wrqu->data.length, strlen(SOFTAP_SET_CMD) + sizeof(cmd_tlv_t)));
-               return -1;
-       }
-
-       str_ptr =  extra + strlen(SOFTAP_SET_CMD)+1; 
-       tlv_size_left = wrqu->data.length - (strlen(SOFTAP_SET_CMD)+1);
-
-       memset(&my_ap, 0, sizeof(my_ap));
-
-       return res;
-}
-#endif
-
-
 #ifdef SOFTAP
 int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg)
 {
@@ -3800,7 +3713,6 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end,
                        wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1);
                        wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len);
                        event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf);
-                       kfree(buf);
 #endif 
                        break;
                }
@@ -5842,7 +5754,7 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss
                WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type));
                WL_SCAN(("\n###################\n"));
        }
-#endif
+#endif 
 
        if (params_size > WLC_IOCTL_MEDLEN) {
                        WL_ERROR(("Set ISCAN for %s due to params_size=%d  \n", \
@@ -5882,11 +5794,6 @@ static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info
                return -1;
        }
 
-#ifdef PNO_SET_DEBUG
-       wl_iw_set_pno_set(dev, info, wrqu, extra);
-       return 0;
-#endif
-
        if (wrqu->data.length != 0) {
 
                char *str_ptr;
@@ -6414,8 +6321,16 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap)
        }
 
        if (strlen(ap->country_code)) {
-               WL_ERROR(("%s: Igonored: Country MUST be specified \
-                                 COUNTRY command with \n",     __FUNCTION__));
+               int error = 0;
+               if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY,
+                       ap->country_code, sizeof(ap->country_code))) >= 0) {
+                       WL_SOFTAP(("%s: set country %s OK\n",
+                               __FUNCTION__, ap->country_code));
+                       dhd_bus_country_set(dev, &ap->country_code[0]);
+               } else {
+                       WL_ERROR(("%s: ERROR:%d setting country %s\n",
+                               __FUNCTION__, error, ap->country_code));
+               }
        } else {
                WL_SOFTAP(("%s: Country code is not specified,"
                        " will use Radio's default\n",
@@ -7157,6 +7072,30 @@ int wl_iw_process_private_ascii_cmd(
 }
 #endif
 
+#define BCM4329_WAKELOCK_NAME "bcm4329_wifi_wakelock"
+
+static struct wake_lock bcm4329_suspend_lock;
+
+int bcm4329_wakelock_init = 0;
+
+void bcm4329_power_save_init(void)
+{
+        wake_lock_init(&bcm4329_suspend_lock, WAKE_LOCK_SUSPEND, BCM4329_WAKELOCK_NAME);
+        wake_lock(&bcm4329_suspend_lock);
+        
+       bcm4329_wakelock_init = 2;
+}
+
+void bcm4329_power_save_exit(void)
+{
+        bcm4329_wakelock_init = 0;
+        msleep(100);
+        
+       if (bcm4329_wakelock_init == 2)
+                wake_unlock(&bcm4329_suspend_lock);
+        wake_lock_destroy(&bcm4329_suspend_lock);
+}
+
 static int wl_iw_set_priv(
        struct net_device *dev,
        struct iw_request_info *info,
@@ -7182,6 +7121,11 @@ static int wl_iw_set_priv(
        
        if (dwrq->length && extra) {
                if (strnicmp(extra, "START", strlen("START")) == 0) {
+                       if (bcm4329_wakelock_init == 1)
+                        {
+                                wake_lock(&bcm4329_suspend_lock);
+                                bcm4329_wakelock_init = 2;
+                        }
                        wl_iw_control_wl_on(dev, info);
                        WL_TRACE(("%s, Received regular START command\n", __FUNCTION__));
                }
@@ -7213,8 +7157,16 @@ static int wl_iw_set_priv(
                        ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra);
                else if (strnicmp(extra, "COUNTRY", strlen("COUNTRY")) == 0)
                        ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra);
-               else if (strnicmp(extra, "STOP", strlen("STOP")) == 0)
+               else if (strnicmp(extra, "SCAN-CHANNELS", strlen("SCAN-CHANNELS")) == 0)
+                       ret = wl_iw_get_country(dev, info, (union iwreq_data *)dwrq, extra);
+               else if (strnicmp(extra, "STOP", strlen("STOP")) == 0){
                        ret = wl_iw_control_wl_off(dev, info);
+                       if (bcm4329_wakelock_init == 2)
+                        {
+                                wake_unlock(&bcm4329_suspend_lock);
+                                bcm4329_wakelock_init = 1;
+                        }
+               }
                else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0)
                        ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra);
                else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0)
@@ -7225,8 +7177,10 @@ static int wl_iw_set_priv(
                        ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra);
                else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0)
                        ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra);
-           else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0)
-                       ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra);
+#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY
+               else if (strnicmp(extra, SETDFSCHANNELS_CMD, strlen(SETDFSCHANNELS_CMD)) == 0)
+                       ret = wl_iw_set_dfs_channels(dev, info, (union iwreq_data *)dwrq, extra);
+#endif
 #if defined(PNO_SUPPORT)
                else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0)
                        ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra);
@@ -7236,40 +7190,21 @@ static int wl_iw_set_priv(
                        ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra);
 #endif
 #if defined(CSCAN)
-               else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
+           else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0)
                        ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra);
-#endif
+#endif 
 #ifdef CUSTOMER_HW2
                else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
                        ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
-               else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) {
-                       WL_TRACE_COEX(("%s:got Framwrork cmd: 'BTCOEXMODE'\n", __FUNCTION__));
+               else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0)
                        ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
-               }
 #else
                else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0)
                        ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra);
 #endif
                else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0)
                        ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra);
-               else if (strnicmp(extra, RXFILTER_START_CMD, strlen(RXFILTER_START_CMD)) == 0)
-                       ret = net_os_set_packet_filter(dev, 1);
-               else if (strnicmp(extra, RXFILTER_STOP_CMD, strlen(RXFILTER_STOP_CMD)) == 0)
-                       ret = net_os_set_packet_filter(dev, 0);
-               else if (strnicmp(extra, RXFILTER_ADD_CMD, strlen(RXFILTER_ADD_CMD)) == 0) {
-                       int filter_num = *(extra + strlen(RXFILTER_ADD_CMD) + 1) - '0';
-                       ret = net_os_rxfilter_add_remove(dev, TRUE, filter_num);
-               }
-               else if (strnicmp(extra, RXFILTER_REMOVE_CMD, strlen(RXFILTER_REMOVE_CMD)) == 0) {
-                       int filter_num = *(extra + strlen(RXFILTER_REMOVE_CMD) + 1) - '0';
-                       ret = net_os_rxfilter_add_remove(dev, FALSE, filter_num);
-               }
 #ifdef SOFTAP
-#ifdef SOFTAP_TLV_CFG
-               else if (strnicmp(extra, SOFTAP_SET_CMD, strlen(SOFTAP_SET_CMD)) == 0) {
-                   wl_iw_softap_cfg_tlv(dev, info, (union iwreq_data *)dwrq, extra);
-               }
-#endif
                else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) {
                        wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra);
                } else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) {
@@ -7790,10 +7725,9 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
        uint32 datalen = ntoh32(e->datalen);
        uint32 status =  ntoh32(e->status);
        uint32 toto;
-#if defined(ROAM_NOT_USED)
        static uint32 roam_no_success = 0;
        static bool roam_no_success_send = FALSE;
-#endif
+
        memset(&wrqu, 0, sizeof(wrqu));
        memset(extra, 0, sizeof(extra));
 
@@ -7864,14 +7798,10 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
                break;
        case WLC_E_ROAM:
                if (status == WLC_E_STATUS_SUCCESS) {
-                       WL_ASSOC(("%s: WLC_E_ROAM: success\n", __FUNCTION__));
-#if defined(ROAM_NOT_USED)
-                       roam_no_success_send = FALSE;
-                       roam_no_success = 0;
-#endif
-                       goto wl_iw_event_end;
+                       memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN);
+                       wrqu.addr.sa_family = ARPHRD_ETHER;
+                       cmd = SIOCGIWAP;
                }
-#if defined(ROAM_NOT_USED)
                else if (status == WLC_E_STATUS_NO_NETWORKS) {
                        roam_no_success++;
                        if ((roam_no_success == 5) && (roam_no_success_send == FALSE)) {
@@ -7886,7 +7816,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
                                goto wl_iw_event_end;
                        }
                }
-#endif
                break;
        case WLC_E_DEAUTH_IND:
        case WLC_E_DISASSOC_IND:
@@ -7942,10 +7871,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
                                wl_iw_send_priv_event(priv_dev, "AP_UP");
                        } else {
                                WL_TRACE(("STA_LINK_UP\n"));
-#if defined(ROAM_NOT_USED)
                                roam_no_success_send = FALSE;
                                roam_no_success = 0;
-#endif
                        }
 #endif
                        WL_TRACE(("Link UP\n"));
@@ -8073,6 +8000,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
 #endif
 
 #if WIRELESS_EXT > 14
+       
        memset(extra, 0, sizeof(extra));
        if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) {
                cmd = IWEVCUSTOM;
index ee6c699936ea0b7bd212e22159eb1ae2b3712ac7..928291fe589a58e801ce7e66e9653e68bf4d925c 100644 (file)
@@ -21,7 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
- * $Id: wl_iw.h,v 1.5.34.1.6.36.4.18 2011/02/10 19:33:12 Exp $
+ * $Id: wl_iw.h,v 1.5.34.1.6.36.4.15 2010/11/17 03:13:51 Exp $
  */
 
 
 #define PNOSETUP_SET_CMD                       "PNOSETUP "
 #define PNOENABLE_SET_CMD                      "PNOFORCE"
 #define PNODEBUG_SET_CMD                       "PNODEBUG"
-#define TXPOWER_SET_CMD                                "TXPOWER"
-#define RXFILTER_START_CMD                     "RXFILTER-START"
-#define RXFILTER_STOP_CMD                      "RXFILTER-STOP"
-#define RXFILTER_ADD_CMD                       "RXFILTER-ADD"
-#define RXFILTER_REMOVE_CMD                    "RXFILTER-REMOVE"
+#define SETDFSCHANNELS_CMD                     "SETDFSCHANNELS"
 
 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
@@ -66,12 +62,6 @@ typedef struct wl_iw_extra_params {
        int     target_channel;
 } wl_iw_extra_params_t;
 
-struct cntry_locales_custom {
-       char iso_abbrev[WLC_CNTRY_BUF_SZ];
-       char custom_locale[WLC_CNTRY_BUF_SZ];
-       int32 custom_locale_rev;
-};
-
 #define        WL_IW_RSSI_MINVAL       -200
 #define        WL_IW_RSSI_NO_SIGNAL    -91
 #define        WL_IW_RSSI_VERY_LOW     -80
@@ -143,13 +133,13 @@ typedef struct wl_iw_ss_cache {
 } wl_iw_ss_cache_t;
 
 typedef struct wl_iw_ss_cache_ctrl {
-       wl_iw_ss_cache_t *m_cache_head;
-       int m_link_down;
-       int m_timer_expired;
-       char m_active_bssid[ETHER_ADDR_LEN];
-       uint m_prev_scan_mode;
-       uint m_cons_br_scan_cnt;
-       struct timer_list *m_timer;
+       wl_iw_ss_cache_t *m_cache_head; 
+       int m_link_down;                
+       int m_timer_expired;            
+       char m_active_bssid[ETHER_ADDR_LEN];    
+       uint m_prev_scan_mode;  
+       uint m_cons_br_scan_cnt;        
+       struct timer_list *m_timer;     
 } wl_iw_ss_cache_ctrl_t;
 
 typedef enum broadcast_first_scan {
@@ -175,7 +165,7 @@ struct ap_profile {
 };
 
 
-#define MACLIST_MODE_DISABLED          0
+#define MACLIST_MODE_DISABLED  0
 #define MACLIST_MODE_DENY              1
 #define MACLIST_MODE_ALLOW             2
 struct mflist {
@@ -208,7 +198,8 @@ extern int net_os_wake_lock_timeout_enable(struct net_device *dev);
 extern int net_os_set_suspend_disable(struct net_device *dev, int val);
 extern int net_os_set_suspend(struct net_device *dev, int val);
 extern int net_os_set_dtim_skip(struct net_device *dev, int val);
-extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec);
+extern int net_os_set_packet_filter(struct net_device *dev, int val);
+extern void dhd_bus_country_set(struct net_device *dev, char *country_code);
 extern char *dhd_bus_country_get(struct net_device *dev);
 extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
 
@@ -230,15 +221,13 @@ extern int dhd_get_dtim_skip(dhd_pub_t *dhd);
 
 extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled);
 extern int dhd_pno_clean(dhd_pub_t *dhd);
-extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, \
-                                           ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
+extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort  scan_fr);
 extern int dhd_pno_get_status(dhd_pub_t *dhd);
 extern int dhd_dev_pno_reset(struct net_device *dev);
 extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, \
-                                int nssid, ushort  scan_fr, int pno_repeat, int pno_freq_expo_max);
+                                int nssid, ushort  scan_fr);
 extern int dhd_dev_pno_enable(struct net_device *dev,  int pfn_enabled);
 extern int dhd_dev_get_pno_status(struct net_device *dev);
-extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec);
 
 #define PNO_TLV_PREFIX                 'S'
 #define PNO_TLV_VERSION                        '1'
@@ -246,9 +235,8 @@ extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec);
 #define PNO_TLV_RESERVED               '0'
 #define PNO_TLV_TYPE_SSID_IE           'S'
 #define PNO_TLV_TYPE_TIME              'T'
-#define PNO_TLV_FREQ_REPEAT            'R'
-#define PNO_TLV_FREQ_EXPO_MAX  'M'
-#define PNO_EVENT_UP                   "PNO_EVENT"
+#define  PNO_EVENT_UP                  "PNO_EVENT"
+#define PNO_SCAN_MAX_FW                        508
 
 typedef struct cmd_tlv {
        char prefix;
@@ -257,19 +245,6 @@ typedef struct cmd_tlv {
        char reserved;
 } cmd_tlv_t;
 
-#ifdef SOFTAP_TLV_CFG
-#define SOFTAP_SET_CMD                         "SOFTAPSET "
-#define SOFTAP_TLV_PREFIX                      'A'
-#define SOFTAP_TLV_VERSION                     '1'
-#define SOFTAP_TLV_SUBVERSION                  '0'
-#define SOFTAP_TLV_RESERVED                    '0'
-
-#define TLV_TYPE_SSID                          'S'
-#define TLV_TYPE_SECUR                         'E'
-#define TLV_TYPE_KEY                           'K'
-#define TLV_TYPE_CHANNEL                       'C'
-#endif
-
 #if defined(CSCAN)
 
 typedef struct cscan_tlv {
@@ -304,6 +279,6 @@ extern int wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int
 
 extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num);
 
-#endif
+#endif 
 
-#endif
+#endif 
index ddf8cf5f3204032f835892487ba085e058f49c82..1fd5e93204d20646062cbdff08cd407f9596a03f 100755 (executable)
 #include <linux/mfd/wm831x/auxadc.h>
 #include <linux/mfd/wm831x/pmu.h>
 #include <linux/mfd/wm831x/pdata.h>
+#include <linux/mfd/wm831x/irq.h>
+
+#define WM831X_DEBUG
+#undef  WM831X_DEBUG
+
+#ifdef WM831X_DEBUG
+#define        WM_BATT_DBG(x...) printk(KERN_INFO x)
+#else
+#define        WM_BATT_DBG(x...)  do {} while (0)
+#endif
+
+#define WM831X_CHG_SYSLO_SHIFT   4
+#define WM831X_CHG_SYSOK_SHIFT   0
+#define WM831X_CHG_SYSLO_MASK  ~(0x7 << 4)
+#define WM831X_CHG_SYSOK_MASK  ~(0x7 << 0)
+
+#define batt_num   52
+
+static int batt_step_table[batt_num] = {
+       3400,3420,3440,3475,3505,3525,
+       3540,3557,3570,3580,3610,
+       3630,3640,3652,3662,3672,
+       3680,3687,3693,3699,3705,
+       3710,3714,3718,3722,3726,
+       3730,3734,3738,3742,3746,
+       3750,3756,3764,3774,3786,
+       3800,3808,3817,3827,3838,
+       3950,3964,3982,4002,4026,
+       4050,4074,4098,4123,4149,4178
+};
+
+static int batt_disp_table[batt_num] = {
+       0,1,2,3,5,7,
+       9,11,13,15,17,
+       19,21,23,25,27,
+       29,31,33,35,37,
+       39,41,43,45,47,
+       49,51,53,55,57,
+       59,61,63,65,67,
+       69,71,73,75,77,
+       79,81,83,85,87,
+       89,91,93,95,97,100
+};
+
+static int batt_chg_step_table[batt_num] = {
+       3530,3565,3600,3635,3655,3680,//+160
+       3700,3717,3734,3745,3755,//+150
+       3770,3778,3786,3795,3803,//+140
+       3810,3814,3818,3822,3825,//+130
+       3830,3832,3834,3836,3837,//+120
+       3840,3842,3844,3846,3847,//+110
+       3850,3857,3864,3871,3876,//+100
+       3890,3897,3904,3911,3918,//+90
+       4030,4047,4064,4080,4096,//+80
+       4120,4132,4144,4156,4170,4180//+70
+};
+
+
+
+#define TIMER_MS_COUNTS 1000
+struct wm_batt_priv_data {
+       int online;
+       int status;
+       int health;
+       int level;
+       int temp;
+       int voltage;
+};
 
 struct wm831x_power {
        struct wm831x *wm831x;
        struct power_supply wall;
        struct power_supply usb;
        struct power_supply battery;
+       struct work_struct batt_work;
+       struct timer_list timer;
+       struct wm_batt_priv_data batt_info;
+       struct wake_lock        syslo_wake;
+       int interval;
 };
 
+struct wm831x_power *g_wm831x_power;
+
+static int power_test_sysfs_init(void);
+extern void wm831x_batt_vol_level(struct wm831x_power *power, int batt_vol, int *level);
+static DEFINE_MUTEX(charging_mutex);
+
+int wm831x_read_on_pin_status(void)
+{
+       int ret;
+       
+       if(!g_wm831x_power)
+       {
+               printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
+               return -1;
+       }
+       
+       ret = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_ON_PIN_CONTROL);
+       if (ret < 0)
+               return ret;
+
+       return !(ret & WM831X_ON_PIN_STS) ? 1 : 0;
+}
+
 static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
                                     union power_supply_propval *val)
 {
@@ -43,18 +139,54 @@ static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
        return 0;
 }
 
+int wm831x_read_chg_status(void)
+{
+       int ret, usb_chg = 0, wall_chg = 0;
+       
+       if(!g_wm831x_power)
+       {
+               printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
+               return -1;
+       }
+       
+       ret = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_SYSTEM_STATUS);
+       if (ret < 0)
+               return ret;
+
+       if (ret & WM831X_PWR_USB)
+               usb_chg = 1;
+       if (ret & WM831X_PWR_WALL)
+               wall_chg = 1;
+
+       return ((usb_chg | wall_chg) ? 1 : 0);
+}
+
 static int wm831x_power_read_voltage(struct wm831x *wm831x,
                                     enum wm831x_auxadc src,
                                     union power_supply_propval *val)
 {
        int ret;
-
        ret = wm831x_auxadc_read_uv(wm831x, src);
        if (ret >= 0)
-               val->intval = ret;
+               val->intval = ret / 1000;
+       
+       return ret ;
+}
 
-       return ret;
+int wm831x_read_batt_voltage(void)
+{
+       int ret = 0;
+       
+       if(!g_wm831x_power)
+       {
+               printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
+               return -1;
+       }
+       
+       ret = wm831x_auxadc_read_uv(g_wm831x_power->wm831x, WM831X_AUX_BATT);
+       return ret / 1000;
 }
+//EXPORT_SYMBOL_GPL(wm831x_get_batt_voltage);
 
 /*********************************************************************
  *             WALL Power
@@ -190,13 +322,34 @@ static struct chg_map chg_times[] = {
        { 510, 15 << WM831X_CHG_TIME_SHIFT },
 };
 
+static struct chg_map chg_syslos[] = {
+       { 2800, 0 << WM831X_CHG_SYSLO_SHIFT},
+       { 2900, 1 << WM831X_CHG_SYSLO_SHIFT},
+       { 3000, 2 << WM831X_CHG_SYSLO_SHIFT},
+       { 3100, 3 << WM831X_CHG_SYSLO_SHIFT},
+       { 3200, 4 << WM831X_CHG_SYSLO_SHIFT},
+       { 3300, 5 << WM831X_CHG_SYSLO_SHIFT},
+       { 3400, 6 << WM831X_CHG_SYSLO_SHIFT},
+       { 3500, 7 << WM831X_CHG_SYSLO_SHIFT},
+};
+
+static struct chg_map chg_sysoks[] = {
+       { 2800, 0 << WM831X_CHG_SYSOK_SHIFT},
+       { 2900, 1 << WM831X_CHG_SYSOK_SHIFT},
+       { 3000, 2 << WM831X_CHG_SYSOK_SHIFT},
+       { 3100, 3 << WM831X_CHG_SYSOK_SHIFT},
+       { 3200, 4 << WM831X_CHG_SYSOK_SHIFT},
+       { 3300, 5 << WM831X_CHG_SYSOK_SHIFT},
+       { 3400, 6 << WM831X_CHG_SYSOK_SHIFT},
+       { 3500, 7 << WM831X_CHG_SYSOK_SHIFT},
+};
+
 static void wm831x_battey_apply_config(struct wm831x *wm831x,
                                       struct chg_map *map, int count, int val,
                                       int *reg, const char *name,
                                       const char *units)
 {
        int i;
-
        for (i = 0; i < count; i++)
                if (val == map[i].val)
                        break;
@@ -213,7 +366,7 @@ static void wm831x_config_battery(struct wm831x *wm831x)
 {
        struct wm831x_pdata *wm831x_pdata = wm831x->dev->platform_data;
        struct wm831x_battery_pdata *pdata;
-       int ret, reg1, reg2;
+       int ret, reg1, reg2, reg3;
 
        if (!wm831x_pdata || !wm831x_pdata->battery) {
                dev_warn(wm831x->dev,
@@ -225,6 +378,7 @@ static void wm831x_config_battery(struct wm831x *wm831x)
 
        reg1 = 0;
        reg2 = 0;
+       reg3 = 0;
 
        if (!pdata->enable) {
                dev_info(wm831x->dev, "Battery charger disabled\n");
@@ -258,6 +412,14 @@ static void wm831x_config_battery(struct wm831x *wm831x)
                                   pdata->timeout, &reg2,
                                   "charger timeout", "min");
 
+       wm831x_battey_apply_config(wm831x, chg_syslos, ARRAY_SIZE(chg_syslos),
+                                  pdata->syslo, &reg3,
+                                  "syslo voltage", "mV");
+
+       wm831x_battey_apply_config(wm831x, chg_sysoks, ARRAY_SIZE(chg_sysoks),
+                                  pdata->sysok, &reg3,
+                                  "sysok voltage", "mV");
+
        ret = wm831x_reg_unlock(wm831x);
        if (ret != 0) {
                dev_err(wm831x->dev, "Failed to unlock registers: %d\n", ret);
@@ -269,10 +431,10 @@ static void wm831x_config_battery(struct wm831x *wm831x)
                              WM831X_CHG_FAST_MASK |
                              WM831X_CHG_ITERM_MASK,
                              reg1);
-       if (ret != 0)
+       if (ret != 0) {
                dev_err(wm831x->dev, "Failed to set charger control 1: %d\n",
                        ret);
-
+       }
        ret = wm831x_set_bits(wm831x, WM831X_CHARGER_CONTROL_2,
                              WM831X_CHG_OFF_MSK |
                              WM831X_CHG_TIME_MASK |
@@ -280,9 +442,18 @@ static void wm831x_config_battery(struct wm831x *wm831x)
                              WM831X_CHG_TRKL_ILIM_MASK |
                              WM831X_CHG_VSEL_MASK,
                              reg2);
-       if (ret != 0)
+       if (ret != 0) {
                dev_err(wm831x->dev, "Failed to set charger control 2: %d\n",
                        ret);
+       }
+
+       ret = wm831x_set_bits(wm831x, WM831X_SYSVDD_CONTROL,
+                                         WM831X_CHG_SYSLO_MASK |
+                                                 WM831X_CHG_SYSOK_MASK,
+                                                 reg3);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to set sysvdd control reg: %d\n",ret);
+       }
 
        wm831x_reg_lock(wm831x);
 }
@@ -320,10 +491,53 @@ static int wm831x_bat_check_status(struct wm831x *wm831x, int *status)
 
        return 0;
 }
+int wm831x_read_bat_charging_status(void)
+{
+       int ret, status;
+       
+       if(!g_wm831x_power)
+       {
+               printk("err:%s:g_wm831x_power address is 0\n",__FUNCTION__);
+               return -1;
+       }
+       
+       ret = wm831x_bat_check_status(g_wm831x_power->wm831x, &status);
+       if (ret < 0)
+               return ret;
+       if (status == POWER_SUPPLY_STATUS_CHARGING) 
+               return 1;
+       return 0;
+}
 
 static int wm831x_bat_check_type(struct wm831x *wm831x, int *type)
 {
        int ret;
+#ifdef WM831X_DEBUG_0 
+       ret = wm831x_reg_read(wm831x, WM831X_POWER_STATE);
+       if (ret < 0)
+               return ret;
+       WM_BATT_DBG("%s: wm831x power status %#x\n", __FUNCTION__, ret);
+
+       ret = wm831x_reg_read(wm831x, WM831X_SYSTEM_STATUS);
+       if (ret < 0)
+               return ret;
+       WM_BATT_DBG("%s: wm831x system status %#x\n", __FUNCTION__, ret);
+
+       ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1);
+       if (ret < 0)
+               return ret;
+       WM_BATT_DBG("%s: wm831x charger control1 %#x\n", __FUNCTION__, ret);
+
+       ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_2);
+       if (ret < 0)
+               return ret;
+       WM_BATT_DBG("%s: wm831x charger control2 %#x\n", __FUNCTION__, ret);
+
+       ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
+       if (ret < 0)
+               return ret;
+       WM_BATT_DBG("%s: wm831x charger status %#x\n\n", __FUNCTION__, ret);
+#endif
 
        ret = wm831x_reg_read(wm831x, WM831X_CHARGER_STATUS);
        if (ret < 0)
@@ -396,20 +610,36 @@ static int wm831x_bat_get_prop(struct power_supply *psy,
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
                ret = wm831x_bat_check_status(wm831x, &val->intval);
+               //val->intval = wm831x_power->batt_info.status;
                break;
+       case POWER_SUPPLY_PROP_PRESENT:
        case POWER_SUPPLY_PROP_ONLINE:
-               ret = wm831x_power_check_online(wm831x, WM831X_PWR_SRC_BATT,
-                                               val);
+               //ret = wm831x_power_check_online(wm831x, WM831X_PWR_SRC_BATT, val);
+               val->intval = wm831x_power->batt_info.online;
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-               ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val);
+               //ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val);
+               val->intval = wm831x_power->batt_info.voltage*1000;//uV
                break;
        case POWER_SUPPLY_PROP_HEALTH:
-               ret = wm831x_bat_check_health(wm831x, &val->intval);
+               //ret = wm831x_bat_check_health(wm831x, &val->intval);
+               val->intval = wm831x_power->batt_info.health;
                break;
        case POWER_SUPPLY_PROP_CHARGE_TYPE:
                ret = wm831x_bat_check_type(wm831x, &val->intval);
                break;
+       case POWER_SUPPLY_PROP_CAPACITY:
+               //ret = wm831x_power_read_voltage(wm831x, WM831X_AUX_BATT, val);
+               //wm831x_batt_vol_level(wm831x_power, val->intval, &level);
+               //val->intval = level;
+               val->intval = wm831x_power->batt_info.level;
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               val->intval = 0;
+               break;
+       case POWER_SUPPLY_PROP_TECHNOLOGY:
+               val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+               break;
        default:
                ret = -EINVAL;
                break;
@@ -420,12 +650,16 @@ static int wm831x_bat_get_prop(struct power_supply *psy,
 
 static enum power_supply_property wm831x_bat_props[] = {
        POWER_SUPPLY_PROP_STATUS,
-       POWER_SUPPLY_PROP_ONLINE,
-       POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_TEMP,
        POWER_SUPPLY_PROP_CHARGE_TYPE,
 };
 
+#ifdef CONFIG_WM831X_WITH_BATTERY
 static const char *wm831x_bat_irqs[] = {
        "BATT HOT",
        "BATT COLD",
@@ -441,16 +675,18 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data)
 {
        struct wm831x_power *wm831x_power = data;
        struct wm831x *wm831x = wm831x_power->wm831x;
-
-       dev_dbg(wm831x->dev, "Battery status changed: %d\n", irq);
-
+       int irq0;
+       
+       irq0 = wm831x->irq_base + WM831X_IRQ_CHG_BATT_HOT + 1;
+       dev_crit(wm831x->dev, "battery changed: i=%d\n", irq-irq0);
+                       
        /* The battery charger is autonomous so we don't need to do
         * anything except kick user space */
        power_supply_changed(&wm831x_power->battery);
 
        return IRQ_HANDLED;
 }
-
+#endif
 
 /*********************************************************************
  *             Initialisation
@@ -463,8 +699,8 @@ static irqreturn_t wm831x_syslo_irq(int irq, void *data)
 
        /* Not much we can actually *do* but tell people for
         * posterity, we're probably about to run out of power. */
-       dev_crit(wm831x->dev, "SYSVDD under voltage\n");
-
+       dev_crit(wm831x->dev, "SYSVDD under voltage and wake lock 60s\n");
+       wake_lock_timeout(&wm831x_power->syslo_wake,60*HZ);//wait for android closing system
        return IRQ_HANDLED;
 }
 
@@ -474,7 +710,7 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
        struct wm831x *wm831x = wm831x_power->wm831x;
 
        dev_dbg(wm831x->dev, "Power source changed\n");
-
+       WM_BATT_DBG("%s:Power source changed\n", __FUNCTION__); 
        /* Just notify for everything - little harm in overnotifying. */
        power_supply_changed(&wm831x_power->battery);
        power_supply_changed(&wm831x_power->usb);
@@ -483,6 +719,289 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static void wm831x_batt_timer_handler(unsigned long data)
+{
+       struct wm831x_power *wm831x_power = (struct wm831x_power*)data;
+       schedule_work(&wm831x_power->batt_work);
+       mod_timer(&wm831x_power->timer, jiffies + msecs_to_jiffies(wm831x_power->interval));
+}
+
+void wm831x_batt_vol_level(struct wm831x_power *wm831x_power, int batt_vol, int *level)
+{
+       int i, ret, status;
+       static int chg_plus = 1000;
+       static int chg_minus = 1000;
+       static int chg_curr = 0;
+       static int chg_num = 60;
+       static int disp_plus = 1000;
+       static int disp_minus = 1000;
+       static int disp_curr = 0;
+       static int disp_num = 50;
+
+
+       *level = wm831x_power->batt_info.level;
+       ret = wm831x_bat_check_status(wm831x_power->wm831x, &status);
+       if (ret < 0) {
+               printk("%s: check bat status failer...err = %d\n", __FUNCTION__, ret);
+               return;
+       }
+
+       if (status == POWER_SUPPLY_STATUS_NOT_CHARGING 
+                       && batt_vol >= batt_step_table[batt_num-1]) {
+               *level = 100;
+               return;
+       }
+
+       if (status == POWER_SUPPLY_STATUS_CHARGING) 
+       {
+               disp_plus = 0;
+               disp_minus = 0;
+               disp_curr = 0;
+               
+               for(i = 0; i < batt_num; i++){        
+                       if((batt_chg_step_table[i] <= batt_vol) && 
+                                        (batt_chg_step_table[i+1] > batt_vol))
+                               break;     
+               }
+               *level = batt_disp_table[i];
+
+               if (batt_vol <= batt_chg_step_table[0])
+                       *level = 0;
+               if (batt_vol >= batt_chg_step_table[batt_num - 1])
+                       *level = 100;
+
+               // ³õʼ״̬
+               if ((chg_plus == 1000) && (chg_minus == 1000))
+               {
+                       *level = *level;
+                       chg_plus = 0;
+                       chg_minus = 0;
+                       chg_curr = 0;
+               }
+               else
+               {                       
+
+                       if (*level >= (wm831x_power->batt_info.level+1))
+                       {
+                               chg_minus = 0;
+                               chg_curr = 0;
+                               
+                               if (++chg_plus > chg_num)
+                               {
+                                       *level = wm831x_power->batt_info.level + 1;
+                                       chg_plus = 0;
+                                       
+                                       if(*level < 85)
+                                       chg_num = 60;
+                                       else 
+                                       chg_num = 20;
+                       
+                               }
+                               else
+                               {
+                                       *level = wm831x_power->batt_info.level;
+                               }               
+                       }
+
+                       else if (*level >= wm831x_power->batt_info.level)
+                       {
+                               chg_plus = 0;
+                               chg_minus = 0;
+
+                               if (++chg_curr > chg_num)
+                               {
+                                       *level = *level;
+                                       chg_curr = 0;
+                               }
+                               else
+                               {
+                                       *level = wm831x_power->batt_info.level;
+                               }
+                       }
+                       else if (*level < (wm831x_power->batt_info.level-1))    
+                       {
+                               chg_plus = 0;
+                               chg_curr = 0;
+                               
+                               if (++chg_minus > (chg_num<<1))
+                               {
+                                       *level = wm831x_power->batt_info.level - 1;
+                                       chg_minus = 0;
+
+                                       if(*level < 85)
+                                       chg_num = 60;
+                                       else 
+                                       chg_num = 20;
+
+                               }
+                               else
+                               {
+                                       *level = wm831x_power->batt_info.level;
+                               }
+                       }
+                       else
+                       {
+                               chg_plus = 0;
+                               chg_minus = 0;
+                               chg_curr = 0;
+                               *level = wm831x_power->batt_info.level;
+                       }
+               }
+               
+
+               if (*level >= 100)
+                       *level = 100;
+               if (*level < 0)
+                       *level = 0;
+       }
+       else 
+       {
+               chg_plus = 0;
+               chg_minus = 0;
+               chg_curr = 0;
+
+               for(i = 0; i < batt_num; i++){        
+                       if(batt_vol >= batt_step_table[i] && 
+                                        batt_vol < batt_step_table[i+1])
+                               break;     
+               }
+               *level = batt_disp_table[i];
+
+               if (batt_vol <= batt_step_table[0])
+                       *level = 0;
+               if (batt_vol >= batt_step_table[batt_num - 1])
+                       *level = 100;
+
+               // ³õʼ״̬
+               if ((disp_plus == 1000) && (disp_minus == 1000))
+               {
+                       *level = *level;
+                       disp_plus = 0;
+                       disp_minus = 0;
+                       disp_curr = 0;
+               }
+               else
+               {                       
+
+                       if (*level <= (wm831x_power->batt_info.level-1))        
+                       {
+                               disp_plus = 0;
+                               disp_curr = 0;
+                               
+                               if (++disp_minus > disp_num)
+                               {
+                                       *level = wm831x_power->batt_info.level - 1;
+                                       disp_minus = 0;
+
+                                       if((*level < 17) || (*level > 85))
+                                       disp_num = 10;
+                                       else
+                                       disp_num = 50;
+
+                               }
+                               else
+                               {
+                                       *level = wm831x_power->batt_info.level;
+                               }
+                       }
+                       else if (*level <= wm831x_power->batt_info.level)
+                       {
+                               disp_plus = 0;
+                               disp_minus = 0;
+
+                               if (++disp_curr > disp_num)
+                               {
+                                       *level = *level;
+                                       disp_curr = 0;
+                               }
+                               else
+                               {
+                                       *level = wm831x_power->batt_info.level;
+                               }
+                       }
+                       else if (*level >= (wm831x_power->batt_info.level+1))
+                       {
+                               disp_minus = 0;
+                               disp_curr = 0;
+                               
+                               if (++disp_plus > (disp_num<<1))
+                               {
+                                       *level = wm831x_power->batt_info.level + 1;
+                                       disp_plus = 0;
+                                       if((*level < 17) || (*level > 85))
+                                       disp_num = 10;
+                                       else
+                                       disp_num = 50;
+                               }
+                               else
+                               {
+                                       *level = wm831x_power->batt_info.level;
+                               }               
+                       }
+                       else
+                       {
+                               disp_plus = 0;
+                               disp_minus = 0;
+                               disp_curr = 0;
+                               *level = wm831x_power->batt_info.level;
+                       }
+               }
+
+               if (*level >= 100)
+                       *level = 100;
+               if (*level < 0)
+                       *level = 0;
+       }
+}
+
+static void wm831x_batt_work(struct work_struct *work)
+{
+       int online, status,health,level, ret; 
+    union power_supply_propval val;
+       struct wm831x_power *power = container_of(work, struct wm831x_power, batt_work);
+
+       ret = wm831x_power_check_online(power->wm831x, WM831X_PWR_SRC_BATT, &val);
+       if (ret < 0) {
+               printk("%s: check bat online failer...  err = %d\n", __FUNCTION__, ret);
+               return;
+       }
+       online = val.intval;
+
+       ret = wm831x_bat_check_status(power->wm831x, &status);
+       if (ret < 0) {
+               printk("%s: check bat status failer...  err = %d\n", __FUNCTION__, ret);
+               return;
+       }
+
+       ret = wm831x_bat_check_health(power->wm831x, &health);
+       if (ret < 0) {
+               printk("%s: check bat health failer...  err = %d\n", __FUNCTION__, ret);
+               return;
+       }
+
+       ret = wm831x_power_read_voltage(power->wm831x, WM831X_AUX_BATT, &val);
+       if (ret < 0) {
+               printk("%s: read bat voltage failer...err = %d\n", __FUNCTION__, ret);
+               return;
+       }
+       power->batt_info.voltage = val.intval;
+
+       wm831x_batt_vol_level(power, val.intval, &level);
+       //mod_timer(&power->timer, jiffies + msecs_to_jiffies(power->interval));
+
+       if (online != power->batt_info.online || status != power->batt_info.status
+                       || health != power->batt_info.health || level != power->batt_info.level)
+       {
+               power->batt_info.online = online;
+               power->batt_info.status = status;
+               power->batt_info.health = health;
+               power->batt_info.level  = level;
+
+               power_supply_changed(&power->battery);
+       }
+
+}
+
 static __devinit int wm831x_power_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
@@ -555,12 +1074,14 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
                goto err_syslo;
        }
 
+#ifdef CONFIG_WM831X_WITH_BATTERY
        for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
                irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
                ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
                                           IRQF_TRIGGER_RISING,
                                           wm831x_bat_irqs[i],
                                           power);
+               WM_BATT_DBG("%s: %s irq no %d\n", __FUNCTION__, wm831x_bat_irqs[i], irq);
                if (ret != 0) {
                        dev_err(&pdev->dev,
                                "Failed to request %s IRQ %d: %d\n",
@@ -568,9 +1089,27 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
                        goto err_bat_irq;
                }
        }
-
+#endif
+
+       power->interval = TIMER_MS_COUNTS;
+       power->batt_info.level = 100;
+       power->batt_info.voltage   = 4200;
+       power->batt_info.online    = 1;
+       power->batt_info.status    = POWER_SUPPLY_STATUS_DISCHARGING;
+       power->batt_info.health    = POWER_SUPPLY_HEALTH_GOOD;
+
+       wake_lock_init(&power->syslo_wake, WAKE_LOCK_SUSPEND, "wm831x_syslo_wake");
+       INIT_WORK(&power->batt_work, wm831x_batt_work);
+       setup_timer(&power->timer, wm831x_batt_timer_handler, (unsigned long)power);
+       power->timer.expires = jiffies + msecs_to_jiffies(1000);
+       add_timer(&power->timer);
+
+       g_wm831x_power = power;
+       printk("%s:wm831x_power initialized\n",__FUNCTION__);
+       power_test_sysfs_init();
        return ret;
-
+       
+#ifdef CONFIG_WM831X_WITH_BATTERY
 err_bat_irq:
        for (; i >= 0; i--) {
                irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
@@ -578,6 +1117,8 @@ err_bat_irq:
        }
        irq = platform_get_irq_byname(pdev, "PWR SRC");
        free_irq(irq, power);
+#endif
+
 err_syslo:
        irq = platform_get_irq_byname(pdev, "SYSLO");
        free_irq(irq, power);
@@ -596,12 +1137,12 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
 {
        struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
        int irq, i;
-
+#ifdef CONFIG_WM831X_WITH_BATTERY
        for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
                irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
                free_irq(irq, wm831x_power);
        }
-
+#endif
        irq = platform_get_irq_byname(pdev, "PWR SRC");
        free_irq(irq, wm831x_power);
 
@@ -615,14 +1156,36 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int wm831x_battery_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev);
+       flush_scheduled_work();
+       del_timer(&power->timer);
+       return 0;
+}
+
+static int wm831x_battery_resume(struct platform_device *dev)
+{
+       struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev);
+       power->timer.expires = jiffies + msecs_to_jiffies(power->interval);
+       add_timer(&power->timer);
+       return 0;
+}
+#else
+#define wm831x_battery_suspend NULL
+#define wm831x_battery_resume  NULL
+#endif
+
 static struct platform_driver wm831x_power_driver = {
        .probe = wm831x_power_probe,
        .remove = __devexit_p(wm831x_power_remove),
+       .suspend = wm831x_battery_suspend,
+       .resume = wm831x_battery_resume,
        .driver = {
                .name = "wm831x-power",
        },
 };
-
 static int __init wm831x_power_init(void)
 {
        return platform_driver_register(&wm831x_power_driver);
@@ -635,6 +1198,96 @@ static void __exit wm831x_power_exit(void)
 }
 module_exit(wm831x_power_exit);
 
+
+static ssize_t power_prop_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       ssize_t ret = 0;
+       int level, power_status, system_status, chg_ctl1, chg_ctl2, chg_status;
+    union power_supply_propval val;
+
+       if (!g_wm831x_power)
+               return -1;
+       power_status = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_POWER_STATE);
+       if (power_status < 0)
+               return power_status;
+       //printk("wm831x power status %#x\n", ret);
+
+       system_status = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_SYSTEM_STATUS);
+       if (system_status < 0)
+               return system_status;
+       //printk("wm831x system status %#x\n", ret);
+
+       chg_ctl1 = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_CHARGER_CONTROL_1);
+       if (chg_ctl1 < 0)
+               return chg_ctl1;
+       //printk("wm831x charger control1 %#x\n", ret);
+
+       chg_ctl2 = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_CHARGER_CONTROL_2);
+       if (chg_ctl2 < 0)
+               return chg_ctl2;
+       //printk("wm831x charger control2 %#x\n", ret);
+
+       chg_status = wm831x_reg_read(g_wm831x_power->wm831x, WM831X_CHARGER_STATUS);
+       if (chg_status < 0)
+               return chg_status;
+       //printk("wm831x charger status %#x\n", ret);
+
+       ret = wm831x_power_read_voltage(g_wm831x_power->wm831x, WM831X_AUX_BATT, &val);
+       if (ret < 0)
+               return ret;
+       wm831x_batt_vol_level(g_wm831x_power, val.intval, &level);
+       //printk("batt_vol = %d batt_level = %d\n", val.intval, level);
+       //
+       sprintf(buf, "power_status=%#x\n"
+                            "system_status=%#x\n"
+                                "chg_ctl1=%#x\n"
+                                "chg_ctl2=%#x\n"
+                                "chg_status=%#x\n"
+                                "batt_vol=%d\n"
+                                "batt_level=%d%%\n",
+                                power_status,
+                                system_status,
+                                chg_ctl1,
+                                chg_ctl2,
+                                chg_status,
+                                val.intval,
+                                level);
+       ret = strlen(buf) + 1;
+       return ret;
+}
+
+static DEVICE_ATTR(prop, 0444, power_prop_show, NULL);
+
+static struct kobject *power_test_kobj;
+
+static int power_test_sysfs_init(void)
+{
+       int ret ;
+       power_test_kobj = kobject_create_and_add("power_test_prop", NULL);
+       if (power_test_kobj == NULL) {
+               printk(KERN_ERR
+                      "power_test_sysfs_init:"\
+                      "subsystem_register failed\n");
+               ret = -ENOMEM;
+               goto err;
+       }
+       ret = sysfs_create_file(power_test_kobj, &dev_attr_prop.attr);
+       if (ret) {
+               printk(KERN_ERR
+                      "power_test_sysfs_init:"\
+                      "sysfs_create_group failed\n");
+               goto err1;
+       }
+
+       return 0 ;
+err1:
+       kobject_del(power_test_kobj);
+err:
+       return ret ;
+}
+
+
 MODULE_DESCRIPTION("Power supply driver for WM831x PMICs");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_LICENSE("GPL");
index b59159bf83805049573b32e69b43bcdc25926b41..bc147414a6b972d5795e5abb858c0b729b8a29af 100755 (executable)
@@ -132,13 +132,6 @@ config REGULATOR_TWL4030
          This driver supports the voltage regulators provided by
          this family of companion chips.
 
-config REGULATOR_TPS65910
-       bool "TI TPS69510x PMIC"
-       depends on TPS65910_CORE
-       help
-         This driver supports the voltage regulators provided by
-         this family of companion chips.
 config REGULATOR_WM831X
        tristate "Wolfson Microelcronics WM831x PMIC regulators"
        depends on MFD_WM831X
index 3932d2ec38f36f08ea209dfd50f0a32ba1b75121..5b98d6cd9803ad6a953936f0c32a4da643050b37 100755 (executable)
@@ -35,6 +35,10 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
 obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
+obj-$(CONFIG_RK2818_REGULATOR_LP8725) += rk2818_lp8725.o
+obj-$(CONFIG_RK2818_REGULATOR_CHARGE) += charge-regulator.o
+obj-$(CONFIG_RK29_PWM_REGULATOR) += rk29-pwm-regulator.o
+
 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
@@ -43,5 +47,6 @@ obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
+obj-$(CONFIG_REGULATOR_ACT8891) += act8891.o
 
 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
index d3e38790906ed889de2b78454516ec1410eb6466..90cbf1fa84a7c7ee513ffd3879eae498eba33fad 100755 (executable)
@@ -1785,6 +1785,24 @@ out:
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage);
 
+int regulator_set_suspend_voltage(struct regulator *regulator, int uV)
+{
+        struct regulator_dev *rdev = regulator->rdev;
+        int ret = 0;
+
+        if (rdev->desc->ops->set_suspend_voltage && uV > 0) {
+                ret = rdev->desc->ops->set_suspend_voltage(rdev, uV);
+                if (ret < 0) {
+                        printk(KERN_ERR "%s: failed to set voltage\n",
+                                __func__);
+                        return ret;
+                }
+        }
+
+        return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage);
+
 /**
  * regulator_set_voltage_time - get raise/fall time
  * @regulator: regulator source
index a0982e80985198004ae990218c38718d8616eec6..5ae9605aed1ac65a25ba890bd1d4be86c2126ce7 100755 (executable)
 #include <linux/mfd/wm831x/regulator.h>
 #include <linux/mfd/wm831x/pdata.h>
 
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+
 #define WM831X_BUCKV_MAX_SELECTOR 0x68
 #define WM831X_BUCKP_MAX_SELECTOR 0x66
 
@@ -35,7 +40,7 @@
 #define WM831X_DCDC_MODE_IDLE    2
 #define WM831X_DCDC_MODE_STANDBY 3
 
-#define WM831X_DCDC_MAX_NAME 6
+//#define WM831X_DCDC_MAX_NAME 6
 
 /* Register offsets in control block */
 #define WM831X_DCDC_CONTROL_1     0
@@ -47,7 +52,7 @@
 /*
  * Shared
  */
-
+#if 0
 struct wm831x_dcdc {
        char name[WM831X_DCDC_MAX_NAME];
        struct regulator_desc desc;
@@ -59,6 +64,7 @@ struct wm831x_dcdc {
        int on_vsel;
        int dvs_vsel;
 };
+#endif
 
 static int wm831x_dcdc_is_enabled(struct regulator_dev *rdev)
 {
@@ -302,6 +308,23 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
        return 0;
 }
 
+static int wm831x_buckv_read_voltage(struct regulator_dev *rdev)
+{
+       int vol_read;
+       int ret;
+       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
+       struct wm831x *wm831x = dcdc->wm831x;
+       int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
+
+       ret = wm831x_reg_read(wm831x, on_reg);
+       if (ret < 0)
+               return ret;
+       ret &= WM831X_DC1_ON_VSEL_MASK;
+       vol_read = (ret-8)*12500 + 600000;
+
+       return vol_read;
+}
+
 static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
                                    int min_uV, int max_uV, unsigned *selector)
 {
@@ -393,6 +416,71 @@ static u16 wm831x_dcdc_ilim[] = {
        125, 250, 375, 500, 625, 750, 875, 1000
 };
 
+static int wm831x_buckv_set_voltage_step(struct regulator_dev * rdev, int min_uV, int max_uV)
+{
+       int old_vol;
+       int new_min_uV,new_max_uV;
+       int diff_value,step;
+       int ret=0;
+
+       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
+       struct wm831x *wm831x = dcdc->wm831x;
+       struct wm831x_pdata *pdata = wm831x->dev->platform_data;
+
+       //if(strcmp(rdev->constraints->name,"DCDC2") != 0)
+       if(strcmp(pdata->dcdc[1]->consumer_supplies[1].supply,"vcore") != 0)
+       {
+               ret = wm831x_buckv_set_voltage(rdev,min_uV,max_uV);
+       }
+       else
+       {
+               old_vol = wm831x_buckv_read_voltage(rdev);
+
+               new_min_uV = old_vol;
+               new_max_uV = old_vol+max_uV-min_uV;
+
+               if(old_vol > min_uV) //reduce voltage
+               {
+                       diff_value = (old_vol - min_uV);
+
+                       for(step = 100000; step<=diff_value; step += 100000)
+                       {
+                               new_min_uV = old_vol-step;
+                               new_max_uV = old_vol+max_uV-min_uV-step;
+
+                               ret = wm831x_buckv_set_voltage(rdev,new_min_uV,new_max_uV);
+                               usleep_range(1000,1000);
+                       }
+
+                       if(new_min_uV > min_uV) //0<  old_vol - min_uV < 100000 ||0< new_min_uV  - min_uV < 1000000
+                       {
+                               ret = wm831x_buckv_set_voltage(rdev,min_uV,max_uV);
+                               usleep_range(1000,1000);
+                       }
+               }
+               else                    //rise  voltage
+               {
+                       diff_value = (min_uV- old_vol);
+
+                       for(step = 100000; step<=diff_value; step += 100000)
+                       {
+                               new_min_uV = old_vol + step;
+                               new_max_uV = old_vol+max_uV-min_uV+step;
+
+                               ret = wm831x_buckv_set_voltage(rdev,new_min_uV,new_max_uV);
+                               usleep_range(1000,1000);
+                       }
+                       if(new_min_uV < min_uV)//  min_uV - old_vol < 100000 || new_min_uV - old_vol < 100000
+                       {
+                               ret = wm831x_buckv_set_voltage(rdev,min_uV,max_uV);
+                               usleep_range(1000,1000);
+                       }
+               }
+       }
+
+       return ret;
+}
+
 static int wm831x_buckv_set_current_limit(struct regulator_dev *rdev,
                                           int min_uA, int max_uA)
 {
@@ -425,8 +513,18 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
        return wm831x_dcdc_ilim[val & WM831X_DC1_HC_THR_MASK];
 }
 
+static int wm831x_dcdc_set_suspend_enable(struct regulator_dev *rdev)
+{
+        return 0;
+}
+
+static int wm831x_dcdc_set_suspend_disable(struct regulator_dev *rdev)
+{
+        return 0;
+}
+
 static struct regulator_ops wm831x_buckv_ops = {
-       .set_voltage = wm831x_buckv_set_voltage,
+       .set_voltage = wm831x_buckv_set_voltage_step,
        .get_voltage_sel = wm831x_buckv_get_voltage_sel,
        .list_voltage = wm831x_buckv_list_voltage,
        .set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
@@ -440,6 +538,8 @@ static struct regulator_ops wm831x_buckv_ops = {
        .get_mode = wm831x_dcdc_get_mode,
        .set_mode = wm831x_dcdc_set_mode,
        .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
+       .set_suspend_enable = wm831x_dcdc_set_suspend_enable,
+       .set_suspend_disable = wm831x_dcdc_set_suspend_disable,
 };
 
 /*
@@ -703,6 +803,8 @@ static struct regulator_ops wm831x_buckp_ops = {
        .get_mode = wm831x_dcdc_get_mode,
        .set_mode = wm831x_dcdc_set_mode,
        .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
+       .set_suspend_enable = wm831x_dcdc_set_suspend_enable,
+       .set_suspend_disable = wm831x_dcdc_set_suspend_disable,
 };
 
 static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
@@ -1011,6 +1113,7 @@ static struct platform_driver wm831x_epe_driver = {
 static int __init wm831x_dcdc_init(void)
 {
        int ret;
+       printk("%s \n", __FUNCTION__);
        ret = platform_driver_register(&wm831x_buckv_driver);
        if (ret != 0)
                pr_err("Failed to register WM831x BUCKV driver: %d\n", ret);
index 01f27c7f4236bca00615e2f4521126f3ce87b702..99f214dd2286a3ab0c6eeb59fb2145c0bc13417d 100755 (executable)
@@ -25,8 +25,9 @@
 #include <linux/mfd/wm831x/regulator.h>
 #include <linux/mfd/wm831x/pdata.h>
 
-#define WM831X_ISINK_MAX_NAME 7
+//#define WM831X_ISINK_MAX_NAME 7
 
+#if 0
 struct wm831x_isink {
        char name[WM831X_ISINK_MAX_NAME];
        struct regulator_desc desc;
@@ -34,13 +35,14 @@ struct wm831x_isink {
        struct wm831x *wm831x;
        struct regulator_dev *regulator;
 };
+#endif
 
 static int wm831x_isink_enable(struct regulator_dev *rdev)
 {
        struct wm831x_isink *isink = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = isink->wm831x;
        int ret;
-
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);
        /* We have a two stage enable: first start the ISINK... */
        ret = wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_ENA,
                              WM831X_CS1_ENA);
@@ -52,7 +54,7 @@ static int wm831x_isink_enable(struct regulator_dev *rdev)
                              WM831X_CS1_DRIVE);
        if (ret != 0)
                wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_ENA, 0);
-
+       printk("%s:line=%d,ret=0x%x\n",__FUNCTION__,__LINE__,ret);
        return ret;
 
 }
@@ -62,7 +64,7 @@ static int wm831x_isink_disable(struct regulator_dev *rdev)
        struct wm831x_isink *isink = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = isink->wm831x;
        int ret;
-
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);
        ret = wm831x_set_bits(wm831x, isink->reg, WM831X_CS1_DRIVE, 0);
        if (ret < 0)
                return ret;
@@ -80,11 +82,11 @@ static int wm831x_isink_is_enabled(struct regulator_dev *rdev)
        struct wm831x_isink *isink = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = isink->wm831x;
        int ret;
-
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);
        ret = wm831x_reg_read(wm831x, isink->reg);
        if (ret < 0)
                return ret;
-
+       
        if ((ret & (WM831X_CS1_ENA | WM831X_CS1_DRIVE)) ==
            (WM831X_CS1_ENA | WM831X_CS1_DRIVE))
                return 1;
@@ -158,7 +160,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
        int ret, irq;
 
        dev_dbg(&pdev->dev, "Probing ISINK%d\n", id + 1);
-
+       printk("%s:line=%d\n",__FUNCTION__,__LINE__);
        if (pdata == NULL || pdata->isink[id] == NULL)
                return -ENODEV;
 
@@ -198,8 +200,15 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)
        }
 
        irq = platform_get_irq(pdev, 0);
+<<<<<<< HEAD
        ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
                                   IRQF_TRIGGER_RISING, isink->name, isink);
+=======
+       printk("%s:line=%d,irq=%d\n",__FUNCTION__,__LINE__,irq);
+       ret = wm831x_request_irq(wm831x, irq, wm831x_isink_irq,
+                                IRQF_TRIGGER_RISING, isink->name,
+                                isink);
+>>>>>>> parent of 15f7fab... temp revert rk change
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
                        irq, ret);
index 2220cf8defb1625a1c161f026cf5722fd7356ea2..214ac7200e4387faf2e42077f3c1293676048b50 100755 (executable)
@@ -25,7 +25,7 @@
 #include <linux/mfd/wm831x/regulator.h>
 #include <linux/mfd/wm831x/pdata.h>
 
-#define WM831X_LDO_MAX_NAME 6
+//#define WM831X_LDO_MAX_NAME 6
 
 #define WM831X_LDO_CONTROL       0
 #define WM831X_LDO_ON_CONTROL    1
@@ -34,6 +34,7 @@
 #define WM831X_ALIVE_LDO_ON_CONTROL    0
 #define WM831X_ALIVE_LDO_SLEEP_CONTROL 1
 
+#if 0
 struct wm831x_ldo {
        char name[WM831X_LDO_MAX_NAME];
        struct regulator_desc desc;
@@ -41,11 +42,12 @@ struct wm831x_ldo {
        struct wm831x *wm831x;
        struct regulator_dev *regulator;
 };
+#endif
 
 /*
  * Shared
  */
-
+extern int reboot_cmd_get(void);
 static int wm831x_ldo_is_enabled(struct regulator_dev *rdev)
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
@@ -68,7 +70,7 @@ static int wm831x_ldo_enable(struct regulator_dev *rdev)
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = ldo->wm831x;
        int mask = 1 << rdev_get_id(rdev);
-
+       //printk("%s,%x\n", __FUNCTION__,mask);
        return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, mask);
 }
 
@@ -77,7 +79,7 @@ static int wm831x_ldo_disable(struct regulator_dev *rdev)
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = ldo->wm831x;
        int mask = 1 << rdev_get_id(rdev);
-
+       //printk("%s\n", __FUNCTION__);
        return wm831x_set_bits(wm831x, WM831X_LDO_ENABLE, mask, 0);
 }
 
@@ -170,7 +172,7 @@ static int wm831x_gp_ldo_get_voltage_sel(struct regulator_dev *rdev)
        ret = wm831x_reg_read(wm831x, reg);
        if (ret < 0)
                return ret;
-
+       //printk("%s base=%x,ret=%x\n", __FUNCTION__,ldo->base,ret);
        ret &= WM831X_LDO1_ON_VSEL_MASK;
 
        return ret;
@@ -210,7 +212,7 @@ static int wm831x_gp_ldo_set_mode(struct regulator_dev *rdev,
        int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
        int ret;
 
-
+       printk("%s base=%x,mode=%x\n", __FUNCTION__,ldo->base,mode);
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
                ret = wm831x_set_bits(wm831x, on_reg,
@@ -290,6 +292,16 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
        return REGULATOR_MODE_NORMAL;
 }
 
+int wm831x_ldo_set_suspend_enable(struct regulator_dev *rdev)
+{
+
+        return 0;
+}
+int wm831x_ldo_set_suspend_disable(struct regulator_dev *rdev)
+{
+
+        return 0;
+}
 
 static struct regulator_ops wm831x_gp_ldo_ops = {
        .list_voltage = wm831x_gp_ldo_list_voltage,
@@ -304,6 +316,8 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
        .is_enabled = wm831x_ldo_is_enabled,
        .enable = wm831x_ldo_enable,
        .disable = wm831x_ldo_disable,
+       .set_suspend_enable = wm831x_ldo_set_suspend_enable,
+       .set_suspend_disable = wm831x_ldo_set_suspend_disable,
 };
 
 static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
@@ -316,7 +330,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
        int ret, irq;
 
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
-
+       printk("Probing LDO%d\n", id + 1);
        if (pdata == NULL || pdata->ldo[id] == NULL)
                return -ENODEV;
 
@@ -450,6 +464,7 @@ static int wm831x_aldo_set_voltage(struct regulator_dev *rdev,
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
        int reg = ldo->base + WM831X_LDO_ON_CONTROL;
 
+       printk("%s base=%x,min_uV=%d,%d\n", __FUNCTION__,ldo->base,min_uV,max_uV);
        return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV,
                                           selector);
 }
@@ -474,7 +489,7 @@ static int wm831x_aldo_get_voltage_sel(struct regulator_dev *rdev)
        ret = wm831x_reg_read(wm831x, reg);
        if (ret < 0)
                return ret;
-
+       printk("%s base=%x,ret=%x\n", __FUNCTION__,ldo->base,ret);
        ret &= WM831X_LDO7_ON_VSEL_MASK;
 
        return ret;
@@ -568,6 +583,8 @@ static struct regulator_ops wm831x_aldo_ops = {
        .is_enabled = wm831x_ldo_is_enabled,
        .enable = wm831x_ldo_enable,
        .disable = wm831x_ldo_disable,
+       .set_suspend_enable = wm831x_ldo_set_suspend_enable,
+       .set_suspend_disable = wm831x_ldo_set_suspend_disable,
 };
 
 static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
@@ -580,7 +597,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
        int ret, irq;
 
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
-
+       printk("Probing LDO%d--\n", id + 1);
        if (pdata == NULL || pdata->ldo[id] == NULL)
                return -ENODEV;
 
@@ -758,6 +775,8 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
        .is_enabled = wm831x_ldo_is_enabled,
        .enable = wm831x_ldo_enable,
        .disable = wm831x_ldo_disable,
+       .set_suspend_enable = wm831x_ldo_set_suspend_enable,
+       .set_suspend_disable = wm831x_ldo_set_suspend_disable,
 };
 
 static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
@@ -770,7 +789,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
        int ret;
 
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
-
+       printk("wm831x_alive_ldo_probe Probing LDO%d\n", id + 1);
        if (pdata == NULL || pdata->ldo[id] == NULL)
                return -ENODEV;
 
@@ -826,9 +845,64 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
        return 0;
 }
 
+static __devexit int wm831x_alive_ldo_shutdown(struct platform_device *pdev)   /*ZMF*/
+{
+       //struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
+#if 0
+       //close ldo in wm831x_last_deinit()
+       struct regulator* ldo;
+
+       //if (reboot_cmd_get())
+       //      return 0;
+       printk("%s\n", __FUNCTION__);
+
+       ldo = regulator_get(NULL, "ldo1");
+       regulator_disable(ldo);                 
+       regulator_put(ldo);
+       
+       ldo = regulator_get(NULL, "ldo2");
+       regulator_disable(ldo);                 
+       regulator_put(ldo);
+       
+       ldo = regulator_get(NULL, "ldo3");
+       regulator_disable(ldo);                 
+       regulator_put(ldo);
+       
+       ldo = regulator_get(NULL, "ldo4");
+       //regulator_disable(ldo);       
+       regulator_put(ldo);
+
+       ldo = regulator_get(NULL, "ldo5");
+       regulator_disable(ldo);                 
+       regulator_put(ldo);
+
+       ldo = regulator_get(NULL, "ldo6");
+       regulator_disable(ldo);                 
+       regulator_put(ldo);
+
+       ldo = regulator_get(NULL, "ldo7");
+       regulator_disable(ldo);                 
+       regulator_put(ldo);
+
+       ldo = regulator_get(NULL, "ldo8");
+       //regulator_disable(ldo);                       
+       regulator_put(ldo);
+
+       ldo = regulator_get(NULL, "ldo9");
+       regulator_disable(ldo);                 
+       regulator_put(ldo);
+
+       ldo = regulator_get(NULL, "ldo10");
+       regulator_disable(ldo);                                         
+       regulator_put(ldo);
+#endif
+       return 0;
+}
+
 static struct platform_driver wm831x_alive_ldo_driver = {
        .probe = wm831x_alive_ldo_probe,
        .remove = __devexit_p(wm831x_alive_ldo_remove),
+       .shutdown = __devexit_p(wm831x_alive_ldo_shutdown),
        .driver         = {
                .name   = "wm831x-alive-ldo",
                .owner  = THIS_MODULE,
@@ -838,7 +912,7 @@ static struct platform_driver wm831x_alive_ldo_driver = {
 static int __init wm831x_ldo_init(void)
 {
        int ret;
-
+       printk("%s \n", __FUNCTION__);  
        ret = platform_driver_register(&wm831x_gp_ldo_driver);
        if (ret != 0)
                pr_err("Failed to register WM831x GP LDO driver: %d\n", ret);
index 27c37743e2c9c33b3a046648a553b83ce56aad08..68a0c106eb6a981e0de7db8a397d525f215ac796 100755 (executable)
@@ -153,6 +153,21 @@ config RTC_DRV_88PM860X
          This driver can also be built as a module. If so, the module
          will be called rtc-88pm860x.
 
+config RTC_HYM8563
+        tristate "RK2818 or RK29 extern HYM8563 RTC"
+       depends on I2C_RK2818 || I2C_RK29
+        help
+          If you say yes here you will get support for the
+          HYM8563 I2C RTC chip.
+          This driver can also be built as a module. If so, the module
+          will be called rtc-HYM8563.
+
+config RTC_M41T66
+       tristate "ST M41T66"
+       depends on I2C_RK2818 || I2C_RK29
+       help
+         If you say Y here you will get support for the ST M41T66.
+
 config RTC_DRV_DS1307
        tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
        help
@@ -351,6 +366,16 @@ config RTC_DRV_S35390A
          This driver can also be built as a module. If so the module
          will be called rtc-s35390a.
 
+config RTC_DRV_S35392A
+       tristate "Seiko Instruments S-35392A"
+       select BITREVERSE
+       help
+         If you say yes here you will get support for the Seiko
+         Instruments S-35392A.
+
+         This driver can also be built as a module. If so the module
+         will be called rtc-s35392a.
+
 config RTC_DRV_FM3130
        tristate "Ramtron FM3130"
        help
index 7d2795810431c2f1b2f00df6233b93ac0549e342..a488d45cf72f38e8007f2618b61a08760244a52a 100755 (executable)
@@ -91,6 +91,7 @@ obj-$(CONFIG_RTC_DRV_RV3029C2)        += rtc-rv3029c2.o
 obj-$(CONFIG_RTC_DRV_RX8025)   += rtc-rx8025.o
 obj-$(CONFIG_RTC_DRV_RX8581)   += rtc-rx8581.o
 obj-$(CONFIG_RTC_DRV_S35390A)  += rtc-s35390a.o
+obj-$(CONFIG_RTC_DRV_S35392A)  += rtc-s35392a.o
 obj-$(CONFIG_RTC_DRV_S3C)      += rtc-s3c.o
 obj-$(CONFIG_RTC_DRV_SA1100)   += rtc-sa1100.o
 obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
@@ -110,3 +111,5 @@ obj-$(CONFIG_RTC_DRV_VT8500)        += rtc-vt8500.o
 obj-$(CONFIG_RTC_DRV_WM831X)   += rtc-wm831x.o
 obj-$(CONFIG_RTC_DRV_WM8350)   += rtc-wm8350.o
 obj-$(CONFIG_RTC_DRV_X1205)    += rtc-x1205.o
+obj-$(CONFIG_RTC_HYM8563)      += rtc-HYM8563.o
+obj-$(CONFIG_RTC_M41T66)       += rtc-m41t66.o
index e0e98dd1eac6cdc87ba9fbb7ba2abc05bcae21c3..9b40adda0132aff16819a079a5f89b840a57a802 100644 (file)
@@ -423,6 +423,7 @@ static int alarm_suspend(struct platform_device *pdev, pm_message_t state)
                if (rtc_current_time + 1 >= rtc_alarm_time) {
                        pr_alarm(SUSPEND, "alarm about to go off\n");
                        memset(&rtc_alarm, 0, sizeof(rtc_alarm));
+                       rtc_time_to_tm(0, &rtc_alarm.time);
                        rtc_alarm.enabled = 0;
                        rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
 
@@ -448,6 +449,7 @@ static int alarm_resume(struct platform_device *pdev)
        pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev);
 
        memset(&alarm, 0, sizeof(alarm));
+       rtc_time_to_tm(0, &alarm.time);
        alarm.enabled = 0;
        rtc_set_alarm(alarm_rtc_dev, &alarm);
 
@@ -461,6 +463,18 @@ static int alarm_resume(struct platform_device *pdev)
        return 0;
 }
 
+static void alarm_shutdown(struct platform_device *pdev)
+{
+       struct rtc_wkalrm alarm;
+
+       pr_alarm(FLOW, "alarm_shutdown(%p)\n", pdev);
+
+       memset(&alarm, 0, sizeof(alarm));
+       rtc_time_to_tm(0, &alarm.time);
+       alarm.enabled = 0;
+       rtc_set_alarm(alarm_rtc_dev, &alarm);
+}
+
 static struct rtc_task alarm_rtc_task = {
        .func = alarm_triggered_func
 };
@@ -520,6 +534,7 @@ static struct class_interface rtc_alarm_interface = {
 static struct platform_driver alarm_driver = {
        .suspend = alarm_suspend,
        .resume = alarm_resume,
+       .shutdown = alarm_shutdown,
        .driver = {
                .name = "alarm"
        }
index c949925e005527a9d01c10b81a34d8886c73e17c..ab18d469ddd8300e7815b058281271f2474a89de 100755 (executable)
@@ -401,16 +401,7 @@ static int __devinit hym8563_probe(struct i2c_client *client, const struct i2c_d
                return -ENOMEM;
        }
                
-       rtc = rtc_device_register(client->name, &client->dev,
-                                 &hym8563_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc)) {
-               rc = PTR_ERR(rtc);
-               rtc = NULL;
-               goto exit;
-       }
-
        hym8563->client = client;
-       hym8563->rtc = rtc;
        mutex_init(&hym8563->mutex);
        wake_lock_init(&hym8563->wake_lock, WAKE_LOCK_SUSPEND, "rtc_hym8563");
        INIT_WORK(&hym8563->work, hym8563_work_func);
@@ -447,6 +438,16 @@ static int __devinit hym8563_probe(struct i2c_client *client, const struct i2c_d
                goto exit;
        }       
        enable_irq_wake(hym8563->irq);
+
+       rtc = rtc_device_register(client->name, &client->dev,
+                                 &hym8563_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               rc = PTR_ERR(rtc);
+               rtc = NULL;
+               goto exit;
+       }
+       hym8563->rtc = rtc;
+
        return 0;
 
 exit:
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
deleted file mode 100644 (file)
index 8f10a63..0000000
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- * rtc-tps65910.c -- TPS65910 Real Time Clock interface
- *
- * Copyright (C) 2010 Mistral Solutions Pvt Ltd. <www.mistralsolutions.com>
- * Author: Umesh K <umeshk@mistralsolutions.com>
- *
- * Based on rtc-twl.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/i2c/tps65910.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-
-#if 0
-#define DBG(x...)      printk(KERN_INFO x)
-#else
-#define DBG(x...)
-#endif
-
-/* RTC Definitions */
-/* RTC_CTRL_REG bitfields */
-#define BIT_RTC_CTRL_REG_STOP_RTC_M            0x01
-#define BIT_RTC_CTRL_REG_ROUND_30S_M           0x02
-#define BIT_RTC_CTRL_REG_AUTO_COMP_M           0x04
-#define BIT_RTC_CTRL_REG_MODE_12_24_M          0x08
-#define BIT_RTC_CTRL_REG_TEST_MODE_M           0x10
-#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M      0x20
-#define BIT_RTC_CTRL_REG_GET_TIME_M            0x40
-#define BIT_RTC_CTRL_REG_RTC_V_OPT_M           0x80
-
-/* RTC_STATUS_REG bitfields */
-#define BIT_RTC_STATUS_REG_RUN_M               0x02
-#define BIT_RTC_STATUS_REG_1S_EVENT_M          0x04
-#define BIT_RTC_STATUS_REG_1M_EVENT_M          0x08
-#define BIT_RTC_STATUS_REG_1H_EVENT_M          0x10
-#define BIT_RTC_STATUS_REG_1D_EVENT_M          0x20
-#define BIT_RTC_STATUS_REG_ALARM_M             0x40
-#define BIT_RTC_STATUS_REG_POWER_UP_M          0x80
-
-/* RTC_INTERRUPTS_REG bitfields */
-#define BIT_RTC_INTERRUPTS_REG_EVERY_M         0x03
-#define BIT_RTC_INTERRUPTS_REG_IT_TIMER_M      0x04
-#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M      0x08
-
-/* DEVCTRL bitfields */
-#define BIT_RTC_PWDN                           0x40
-
-/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
-#define ALL_TIME_REGS                          6
-
-/*
- * Supports 1 byte read from TPS65910 RTC register.
- */
-static int tps65910_rtc_read_u8(u8 *data, u8 reg)
-{
-       int ret;
-
-       ret = tps65910_i2c_read_u8(TPS65910_I2C_ID0, data, reg);
-
-       if (ret < 0)
-               pr_err("tps65910_rtc: Could not read TPS65910"
-                               "register %X - error %d\n", reg, ret);
-       return ret;
-}
-
-/*
- * Supports 1 byte write to TPS65910 RTC registers.
- */
-static int tps65910_rtc_write_u8(u8 data, u8 reg)
-{
-       int ret;
-
-       ret = tps65910_i2c_write_u8(TPS65910_I2C_ID0, data, reg);
-       if (ret < 0)
-               pr_err("tps65910_rtc: Could not write TPS65910"
-                               "register %X - error %d\n", reg, ret);
-       return ret;
-}
-
-/*
- * Cache the value for timer/alarm interrupts register; this is
- * only changed by callers holding rtc ops lock (or resume).
- */
-static unsigned char rtc_irq_bits;
-
-/*
- * Enable 1/second update and/or alarm interrupts.
- */
-static int set_rtc_irq_bit(unsigned char bit)
-{
-       unsigned char val;
-       int ret;
-
-       val = rtc_irq_bits | bit;
-       val |= bit;
-       ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
-       if (ret == 0)
-               rtc_irq_bits = val;
-
-       return ret;
-}
-
-/*
- * Disable update and/or alarm interrupts.
- */
-static int mask_rtc_irq_bit(unsigned char bit)
-{
-       unsigned char val;
-       int ret;
-
-       val = rtc_irq_bits & ~bit;
-       ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
-       if (ret == 0)
-               rtc_irq_bits = val;
-
-       return ret;
-}
-
-static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
-{
-       int ret;
-
-       if (enabled)
-               ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
-       else
-               ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
-
-       return ret;
-}
-
-static int tps65910_rtc_update_irq_enable(struct device *dev, unsigned enabled)
-{
-       int ret;
-
-       if (enabled)
-               ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-       else
-               ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-
-       return ret;
-}
-
-#if 1 /* Debugging periodic interrupts */
-/*
- * We will just handle setting the frequency and make use the framework for
- * reading the periodic interupts.
- *
- * @freq: Current periodic IRQ freq:
- * bit 0: every second
- * bit 1: every minute
- * bit 2: every hour
- * bit 3: every day
- */
-
-static int tps65910_rtc_irq_set_freq(struct device *dev, int freq)
-{
-       struct rtc_device *rtc = dev_get_drvdata(dev);
-
-       if (freq < 0 || freq > 3)
-               return -EINVAL;
-
-       rtc->irq_freq = freq;
-       /* set rtc irq freq to user defined value */
-       set_rtc_irq_bit(freq);
-
-       return 0;
-}
-#endif
-
-/*
- * Gets current TPS65910 RTC time and date parameters.
- *
- * The RTC's time/alarm representation is not what gmtime(3) requires
- * Linux to use:
- *
- *  - Months are 1..12 vs Linux 0-11
- *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
- */
-static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
-       unsigned char rtc_data[ALL_TIME_REGS + 1];
-       int ret;
-       u8 save_control;
-
-       tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               return ret;
-
-       save_control &= ~BIT_RTC_CTRL_REG_RTC_V_OPT_M;
-
-       ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               return ret;
-
-       ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_MINUTES);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_HOURS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_DAYS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_MONTHS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_YEARS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-
-       tm->tm_sec = bcd2bin(rtc_data[0]);
-       tm->tm_min = bcd2bin(rtc_data[1]);
-       tm->tm_hour = bcd2bin(rtc_data[2]);
-       tm->tm_mday = bcd2bin(rtc_data[3]);
-       tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
-       tm->tm_year = bcd2bin(rtc_data[5]) + 100;
-       
-       DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
-       DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
-       DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
-       DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
-       DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
-       DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
-       DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
-
-       return ret;
-}
-
-static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
-       unsigned char save_control;
-       unsigned char rtc_data[ALL_TIME_REGS + 1];
-       int ret;
-
-       DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
-       DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
-       DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
-       DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
-       DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
-       DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
-       DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
-
-       rtc_data[1] = bin2bcd(tm->tm_sec);
-       rtc_data[2] = bin2bcd(tm->tm_min);
-       rtc_data[3] = bin2bcd(tm->tm_hour);
-       rtc_data[4] = bin2bcd(tm->tm_mday);
-       rtc_data[5] = bin2bcd(tm->tm_mon + 1);
-       rtc_data[6] = bin2bcd(tm->tm_year - 100);
-
-       /*Dummy read*/
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-
-       /* Stop RTC while updating the TC registers */
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               goto out;
-
-       save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
-
-       tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
-
-       /* update all the time registers in one shot */
-       ret = tps65910_rtc_write_u8(rtc_data[1], TPS65910_REG_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[2], TPS65910_REG_MINUTES);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[3], TPS65910_REG_HOURS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[4], TPS65910_REG_DAYS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[5], TPS65910_REG_MONTHS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[6], TPS65910_REG_YEARS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-
-       /*Dummy read*/
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               goto out;
-       /* Start back RTC */
-       save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
-       ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
-
-out:
-       return ret;
-}
-
-/*
- * Gets current TPS65910 RTC alarm time.
- */
-static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
-{
-       unsigned char rtc_data[ALL_TIME_REGS + 1];
-       int ret;
-
-       ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_ALARM_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_ALARM_MINUTES);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_ALARM_HOURS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_ALARM_DAYS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_ALARM_MONTHS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_ALARM_YEARS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-
-       /* some of these fields may be wildcard/"match all" */
-       alm->time.tm_sec = bcd2bin(rtc_data[0]);
-       alm->time.tm_min = bcd2bin(rtc_data[1]);
-       alm->time.tm_hour = bcd2bin(rtc_data[2]);
-       alm->time.tm_mday = bcd2bin(rtc_data[3]);
-       alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1;
-       alm->time.tm_year = bcd2bin(rtc_data[5]) + 100;
-
-       /* report cached alarm enable state */
-       if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M)
-               alm->enabled = 1;
-
-       return ret;
-}
-
-static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
-{
-       unsigned char alarm_data[ALL_TIME_REGS + 1];
-       int ret;
-
-       ret = tps65910_rtc_alarm_irq_enable(dev, 0);
-       if (ret)
-               goto out;
-
-       alarm_data[1] = bin2bcd(alm->time.tm_sec);
-       alarm_data[2] = bin2bcd(alm->time.tm_min);
-       alarm_data[3] = bin2bcd(alm->time.tm_hour);
-       alarm_data[4] = bin2bcd(alm->time.tm_mday);
-       alarm_data[5] = bin2bcd(alm->time.tm_mon + 1);
-       alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
-
-       /* update all the alarm registers in one shot */
-       ret = tps65910_rtc_write_u8(alarm_data[1], TPS65910_REG_ALARM_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[2], TPS65910_REG_ALARM_MINUTES);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[3], TPS65910_REG_ALARM_HOURS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[4], TPS65910_REG_ALARM_DAYS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[5], TPS65910_REG_ALARM_MONTHS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[6], TPS65910_REG_ALARM_YEARS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-
-       if (alm->enabled)
-               ret = tps65910_rtc_alarm_irq_enable(dev, 1);
-out:
-       return ret;
-}
-
-
-struct work_struct rtc_wq;
-unsigned long rtc_events;
-struct rtc_device *global_rtc;
-
-void tps65910_rtc_work(void  *data)
-{
-       int res;
-       u8 rd_reg;
-       unsigned long events = 0;
-
-       DBG("Enter::%s %d\n",__FUNCTION__,__LINE__);
-
-       res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
-
-       if (res < 0)
-               goto out;
-       /*
-        * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
-        * only one (ALARM or RTC) interrupt source may be enabled
-        * at time, we also could check our results
-        * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
-        */
-       if (rd_reg & TPS65910_RTC_ALARM_IT) {
-               res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_ALARM_IT,
-                               TPS65910_REG_INT_STS);
-               if (res < 0)
-                       goto out;
-
-               /*Dummy read -- mandatory for status register*/
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               mdelay(100);
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
-
-               rtc_events |= RTC_IRQF | RTC_AF;
-       } else if (rd_reg & TPS65910_RTC_PERIOD_IT) {
-               res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_PERIOD_IT,
-                               TPS65910_REG_INT_STS);
-               if (res < 0)
-                       goto out;
-
-               /*Dummy read -- mandatory for status register*/
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               mdelay(100);
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               rd_reg &= 0xC3;
-               res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
-               rtc_events |= RTC_IRQF | RTC_UF;
-       }
-out:
-       /* Notify RTC core on event */
-       events = rtc_events;
-       rtc_update_irq(global_rtc, 1, events);
-}
-
-static struct rtc_class_ops tps65910_rtc_ops = {
-       .read_time      = tps65910_rtc_read_time,
-       .set_time       = tps65910_rtc_set_time,
-       .read_alarm     = tps65910_rtc_read_alarm,
-       .set_alarm      = tps65910_rtc_set_alarm,
-       .alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
-       .update_irq_enable = tps65910_rtc_update_irq_enable,
-       .irq_set_freq   = tps65910_rtc_irq_set_freq,
-};
-
-static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
-{
-       struct rtc_device *rtc;
-       int ret = 0, stop_run = 0;
-       u8 rd_reg;
-       struct rtc_time tm_def = {      //      2011.1.1 12:00:00 Saturday
-               .tm_wday = 6,
-               .tm_year = 111,
-               .tm_mon = 0,
-               .tm_mday = 1,
-               .tm_hour = 12,
-               .tm_min = 0,
-               .tm_sec = 0,
-       };
-       
-       rtc = rtc_device_register(pdev->name,
-                       &pdev->dev, &tps65910_rtc_ops, THIS_MODULE);
-
-       if (IS_ERR(rtc)) {
-               ret = PTR_ERR(rtc);
-               dev_err(&pdev->dev, "can't register TPS65910 RTC device,\
-                                        err %ld\n", PTR_ERR(rtc));
-               goto out0;
-
-       }
-       printk(KERN_INFO "TPS65910 RTC device successfully registered\n");
-
-       platform_set_drvdata(pdev, rtc);
-       /* Take rtc out of reset */
-       tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_DEVCTRL);
-       rd_reg &= ~BIT_RTC_PWDN;
-       ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_DEVCTRL);
-
-       /* Dummy read to ensure that the register gets updated.
-        * Please refer tps65910 TRM table:25 for details
-        */
-       stop_run = 0;
-       ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-       if (ret < 0) {
-               printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
-               goto out1;
-       }
-
-       if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) {
-               dev_warn(&pdev->dev, "Power up reset detected.\n");
-               //      cwz:if rtc power up reset, set default time.
-               printk(KERN_INFO "TPS65910 RTC set to default time\n");
-               tps65910_rtc_set_time(rtc, &tm_def);
-       }
-       if (!(rd_reg & BIT_RTC_STATUS_REG_RUN_M)) {
-               dev_warn(&pdev->dev, "RTC stop run.\n");
-               stop_run = 1;
-       }
-       if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
-               dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
-
-       /* Clear RTC Power up reset and pending alarm interrupts */
-       ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
-       if (ret < 0)
-               goto out1;
-       
-       ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
-       if (ret < 0) {
-               printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
-               goto out1;
-       }
-
-       if (rd_reg & 0x40) {
-               printk(KERN_INFO "pending alarm interrupt!!! clearing!!!");
-               tps65910_rtc_write_u8(rd_reg, TPS65910_REG_INT_STS);
-       }
-
-       global_rtc = rtc;
-
-       /* Link RTC IRQ handler to TPS65910 Core */
-       tps65910_add_irq_work(TPS65910_RTC_ALARM_IRQ, tps65910_rtc_work);
-       tps65910_add_irq_work(TPS65910_RTC_PERIOD_IRQ, tps65910_rtc_work);
-
-       /* Check RTC module status, Enable if it is off */
-       if (stop_run) {
-               dev_info(&pdev->dev, "Enabling TPS65910-RTC.\n");
-               //      cwz:if rtc stop, set default time, then enable rtc
-               printk(KERN_INFO "TPS65910 RTC set to default time\n");
-               tps65910_rtc_set_time(rtc, &tm_def);
-               ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_CTRL);
-               if (ret < 0)
-                       goto out1;
-
-               rd_reg |= BIT_RTC_CTRL_REG_STOP_RTC_M;
-               ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_CTRL);
-               if (ret < 0)
-                       goto out1;
-       }
-
-       /* init cached IRQ enable bits */
-       ret = tps65910_rtc_read_u8(&rtc_irq_bits, TPS65910_REG_RTC_INTERRUPTS);
-       if (ret < 0)
-               goto out1;
-
-       tps65910_rtc_write_u8(0x3F, TPS65910_REG_INT_MSK);
-       return ret;
-
-out1:
-       rtc_device_unregister(rtc);
-out0:
-       return ret;
-}
-
-/*
- * Disable all TPS65910 RTC module interrupts.
- * Sets status flag to free.
- */
-static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
-{
-       /* leave rtc running, but disable irqs */
-       struct rtc_device *rtc = platform_get_drvdata(pdev);
-       int irq = platform_get_irq(pdev, 0);
-
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-
-
-       free_irq(irq, rtc);
-
-       rtc_device_unregister(rtc);
-       platform_set_drvdata(pdev, NULL);
-       return 0;
-}
-
-static void tps65910_rtc_shutdown(struct platform_device *pdev)
-{
-       /* mask timer interrupts, but leave alarm interrupts on to enable
-        * power-on when alarm is triggered
-        */
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-}
-
-#ifdef CONFIG_PM
-
-static unsigned char irqstat;
-
-static
-int tps65910_rtc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       irqstat = rtc_irq_bits;
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-       return 0;
-}
-
-static int tps65910_rtc_resume(struct platform_device *pdev)
-{
-       set_rtc_irq_bit(irqstat);
-       return 0;
-}
-
-#else
-#define tps65910_rtc_suspend NULL
-#define tps65910_rtc_resume  NULL
-#endif
-
-
-static struct platform_driver tps65910rtc_driver = {
-       .probe          = tps65910_rtc_probe,
-       .remove         = __devexit_p(tps65910_rtc_remove),
-       .shutdown       = tps65910_rtc_shutdown,
-       .suspend        = tps65910_rtc_suspend,
-       .resume         = tps65910_rtc_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "tps65910_rtc",
-       },
-};
-static int __init tps65910_rtc_init(void)
-{
-       return platform_driver_register(&tps65910rtc_driver);
-}
-module_init(tps65910_rtc_init);
-
-static void __exit tps65910_rtc_exit(void)
-{
-       platform_driver_unregister(&tps65910rtc_driver);
-}
-module_exit(tps65910_rtc_exit);
-
-MODULE_ALIAS("platform:tps65910_rtc");
-MODULE_AUTHOR("cwz  <cwz@rockchips.com");
-MODULE_LICENSE("GPL");
diff --git a/drivers/serial/rk2818_serial.h b/drivers/serial/rk2818_serial.h
deleted file mode 100644 (file)
index 54558ed..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * drivers/serial/rk2818_serial.h
- *
- * Copyright (C) 2010 ROCKCHIP, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __DRIVERS_SERIAL_RK2818_SERIAL_H
-#define __DRIVERS_SERIAL_RK2818_SERIAL_H
-
-#define UART_RBR       0x0000                  /* Receive Buffer Register */
-#define UART_THR       0x0000                  /* Transmit Holding Register */
-#define UART_DLL       0x0000                  /* Divisor Latch (Low) */
-#define UART_DLH       0x0004                  /* Divisor Latch (High) */
-#define UART_IER       0x0004                  /* Interrupt Enable Register */
-#define UART_IIR       0x0008                  /* Interrupt Identification Register */
-#define UART_FCR       0x0008                  /* FIFO Control Register */
-#define UART_LCR       0x000C                  /* Line Control Register */
-#define UART_MCR       0x0010                  /* Modem Control Register */
-#define UART_LSR       0x0014                  /* [0x0000_0060] Line Status Register */
-#define UART_MSR       0x0018                  /* Modem Status Register */
-#define UART_SCR       0x001c                  /* Scratchpad Register */
-#define UART_SRBR(n)   (0x0030+((n) * 4))      /* Shadow Receive Buffer Register */
-#define UART_STHR(n)   (0x0030+((n) * 4))      /* Shadow Transmit Holding Register */
-#define UART_FAR       0x0070                  /* FIFO Access Register */
-#define UART_TFR       0x0074                  /* Transmit FIFO Read */
-#define UART_RFW       0x0078                  /* Receive FIFO Write */
-#define UART_USR       0x007C                  /* UART Status Register */
-#define UART_TFL       0x0080                  /* Transmit FIFO Level */
-#define UART_RFL       0x0084                  /* Receive FIFO Level */
-#define UART_SRR       0x0088                  /* Software Reset Register */
-#define UART_SRTS      0x008C                  /* Shadow Request to Send */
-#define UART_SBCR      0x0090                  /* Shadow Break Control Register */
-#define UART_SDMAM     0x0094                  /* Shadow DMA Mode */
-#define UART_SFE       0x0098                  /* Shadow FIFO Enable */
-#define UART_SRT       0x009C                  /* Shadow RCVR Trigger */
-#define UART_STET      0x00A0                  /* Shadow TX Empty Trigger */
-#define UART_HTX       0x00A4                  /* Halt TX */
-#define UART_DMASA     0x00A8                  /* DMA Software Acknowledge */
-#define UART_CPR       0x00F4                  /* Component Parameter Register */
-#define UART_UCV       0x00F8                  /* [0x3330_372a] UART Component Version */
-#define UART_CTR       0x00FC                  /* [0x4457_0110] Component Type Register */
-
-//#define UART_FCR            0x08
-#define  UART_FCR_FIFO_ENABLE  (1<<0) 
-#define  UART_FCR_CLEAR_RCVR   (1<<1)  /* Clear the RCVR FIFO */
-#define  UART_FCR_CLEAR_XMIT           (1<<2)  /* Clear the XMIT FIFO */
-#define  UART_FCR_DMA_SELECT   (1<<3)   /* For DMA applications */
-#define  UART_FCR_R_TRIG_00    0x00
-#define  UART_FCR_R_TRIG_01    0x40
-#define  UART_FCR_R_TRIG_10    0x80
-#define  UART_FCR_R_TRIG_11    0xc0
-#define  UART_FCR_T_TRIG_00    0x00
-#define  UART_FCR_T_TRIG_01    0x10
-#define  UART_FCR_T_TRIG_10    0x20
-#define  UART_FCR_T_TRIG_11    0x30
-
-//#define UART_LCR            0x0c
-#define  LCR_DLA_EN                         (1<<7)
-#define  BREAK_CONTROL_BIT                  (1<<6)
-#define  EVEN_PARITY_SELECT                 (1<<4)
-#define  EVEN_PARITY                        (1<<4)
-#define  ODD_PARITY                          (0)
-#define  PARITY_DISABLED                     (0)
-#define  PARITY_ENABLED                     (1<<3)
-#define  ONE_STOP_BIT                        (0)
-#define  ONE_HALF_OR_TWO_BIT                (1<<2)
-#define  LCR_WLS_5                           (0x00)
-#define  LCR_WLS_6                           (0x01)
-#define  LCR_WLS_7                           (0x02)
-#define  LCR_WLS_8                           (0x03)
-#define  UART_DATABIT_MASK                   (0x03)
-
-/* Detail UART_IER  Register Description */
-#define UART_IER_THRE_MODE_INT_ENABLE          1<<7
-#define UART_IER_MODEM_STATUS_INT_ENABLE       1<<3
-#define UART_IER_RECV_LINE_STATUS_INT_ENABLE   1<<2
-#define UART_IER_SEND_EMPTY_INT_ENABLE         1<<1
-#define UART_IER_RECV_DATA_AVAIL_INT_ENABLE    1<<0
-
-
-/* Detail UART_IIR  Register Description */
-#define UART_IIR_FIFO_DISABLE                  0x00
-#define UART_IIR_FIFO_ENABLE                   0x03
-#define UART_IIR_INT_ID_MASK                   0x0F
-#define UART_IIR_MODEM_STATUS                  0x00
-#define UART_IIR_NO_INTERRUPT_PENDING  0x01
-#define UART_IIR_THR_EMPTY                         0x02
-#define UART_IIR_RECV_AVAILABLE                        0x04
-#define UART_IIR_RECV_LINE_STATUS              0x06
-#define UART_IIR_BUSY_DETECT                   0x07
-#define UART_IIR_CHAR_TIMEOUT                  0x0C
-
-//#define UART_MCR            0x10
-/* Modem Control Register */
-#define        UART_SIR_ENABLE (1 << 6)
-#define UART_MCR_AFCEN (1 << 5)        /* Auto Flow Control Mode enabled */
-#define UART_MCR_URLB  (1 << 4)        /* Loop-back mode */
-#define UART_MCR_UROUT2        (1 << 3)        /* OUT2 signal */
-#define UART_MCR_UROUT1        (1 << 2)        /* OUT1 signal */
-#define UART_MCR_URRTS (1 << 1)        /* Request to Send */
-#define UART_MCR_URDTR (1 << 0)        /* Data Terminal Ready */
-
-//#define UART_MSR            0x18
-/* Modem Status Register */
-#define UART_MSR_URDCD (1 << 7)        /* Data Carrier Detect */
-#define UART_MSR_URRI  (1 << 6)        /* Ring Indicator */
-#define UART_MSR_URDSR (1 << 5)        /* Data Set Ready */
-#define UART_MSR_URCTS (1 << 4)        /* Clear to Send */
-#define UART_MSR_URDDCD        (1 << 3)        /* Delta Data Carrier Detect */
-#define UART_MSR_URTERI        (1 << 2)        /* Trailing Edge Ring Indicator */
-#define UART_MSR_URDDST        (1 << 1)        /* Delta Data Set Ready */
-#define UART_MSR_URDCTS        (1 << 0)        /* Delta Clear to Send */
-
-/* Detail UART_USR  Register Description */
-#define  UART_RECEIVE_FIFO_FULL              (1<<4)
-#define  UART_RECEIVE_FIFO_NOT_FULL          (0)
-#define  UART_RECEIVE_FIFO_EMPTY             (0)
-#define  UART_RECEIVE_FIFO_NOT_EMPTY         (1<<3)
-#define  UART_TRANSMIT_FIFO_NOT_EMPTY        (0)
-#define  UART_TRANSMIT_FIFO_EMPTY            (1<<2)
-#define  UART_TRANSMIT_FIFO_FULL             (0)
-#define  UART_TRANSMIT_FIFO_NOT_FULL         (1<<1)
-#define  UART_USR_BUSY                       (1)
-
-/*UART_LSR Line Status Register*/
-#define UART_BREAK_INT_BIT                                     (1<<4)/*break Interrupt bit*/
-
-#endif /* __DRIVERS_SERIAL_RK2818_SERIAL_H */
diff --git a/drivers/serial/rk29_serial.c b/drivers/serial/rk29_serial.c
deleted file mode 100755 (executable)
index 5bfcaa2..0000000
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
- * drivers/serial/rk29_serial.c - driver for rk29 serial device and console
- *
- * Copyright (C) 2010 ROCKCHIP, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-
-#if defined(CONFIG_SERIAL_RK29_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/hrtimer.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <mach/iomux.h>
-#include <mach/gpio.h>
-#include <mach/board.h>
-#include "rk2818_serial.h"
-
-#define DBG_PORT    0
-#if 0
-#define DBG(msg...)    printk(msg);
-#else
-#define DBG(...)
-#endif
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct rk29_port {
-       struct uart_port        uart;
-       char                    name[16];
-       struct clk              *clk;
-       unsigned int            imr;
-};
-
-#define UART_TO_RK29(uart_port)        ((struct rk29_port *) uart_port)
-#define RK29_SERIAL_MAJOR       TTY_MAJOR
-#define RK29_SERIAL_MINOR       64      
-
-
-static inline void rk29_uart_write(struct uart_port *port, unsigned int val,
-                            unsigned int off)
-{
-       __raw_writel(val, port->membase + off);
-}
-
-static inline unsigned int rk29_uart_read(struct uart_port *port, unsigned int off)
-{
-       return __raw_readl(port->membase + off);
-}
-
-static int rk29_set_baud_rate(struct uart_port *port, unsigned int baud)
-{
-       unsigned int uartTemp;
-       
-       rk29_uart_write(port,rk29_uart_read(port,UART_LCR) | LCR_DLA_EN,UART_LCR);
-    uartTemp = port->uartclk / (16 * baud);
-    rk29_uart_write(port,uartTemp & 0xff,UART_DLL);
-    rk29_uart_write(port,(uartTemp>>8) & 0xff,UART_DLH);
-    rk29_uart_write(port,rk29_uart_read(port,UART_LCR) & (~LCR_DLA_EN),UART_LCR);
-       return baud;
-}
-
-/*
- * ÅжϷ¢ËÍ»º³åÇøÊÇ·ñΪ¿Õ
- *ÏÈÒÔFIFO´ò¿ª×ö£¬ºóÃæ¿ÉÒÔ×ö³ÉFIFO¹Ø»òFIFO¿ª¡£
- */
-static u_int rk29_serial_tx_empty(struct uart_port *port)
-{
-    int timeout = 10000000;
-    while(!(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY))
-        if(timeout-- ==0)
-            break;
-        cpu_relax();
-       if(rk29_uart_read(port,UART_USR)&UART_TRANSMIT_FIFO_EMPTY)
-       {
-        return (1);///1£º¿Õ
-       }else{
-        return (0);///0:·Ç¿Õ
-       }
-}
-
-/*
- * Power / Clock management.
- */
-static void rk29_serial_pm(struct uart_port *port, unsigned int state,
-                           unsigned int oldstate)
-{
-       struct rk29_port *rk29_port = UART_TO_RK29(port);
-
-       switch (state) {
-       case 0:
-               /*
-                * Enable the peripheral clock for this serial port.
-                * This is called on uart_open() or a resume event.
-                */
-               clk_enable(rk29_port->clk);
-               break;
-       case 3:
-               /*
-                * Disable the peripheral clock for this serial port.
-                * This is called on uart_close() or a suspend event.
-                */
-               clk_disable(rk29_port->clk);
-               break;
-       default:
-               printk(KERN_ERR "rk29_serial: unknown pm %d\n", state);
-       }
-}
-
-/*
- * Return string describing the specified port
- */
-static const char *rk29_serial_type(struct uart_port *port)
-{
-       return (port->type == PORT_RK29) ? "RK29_SERIAL" : NULL;
-}
-
-static void rk29_serial_enable_ms(struct uart_port *port)
-{
-  #ifdef DEBUG_LHH
-  printk("Enter::%s\n",__FUNCTION__);
-  #endif
-}
-
-/* no modem control lines */
-static unsigned int rk29_serial_get_mctrl(struct uart_port *port)
-{
-       unsigned int result = 0;
-       unsigned int status;
-       
-       status = rk29_uart_read(port,UART_MSR);
-       if (status & UART_MSR_URCTS)
-       {                       
-               result = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
-               printk("UART_GET_MSR:0x%x\n",result);
-       }else{                  
-               result = TIOCM_CAR | TIOCM_DSR;
-               printk("UART_GET_MSR:0x%x\n",result);
-       }
-       return result;
-}
-
-static void rk29_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{        
-       #ifdef DEBUG_LHH
-       printk("Enter::%s\n",__FUNCTION__);
-       #endif 
-}
-
-/*
- * Stop transmitting.
- */
-static void rk29_serial_stop_tx(struct uart_port *port)
-{
-       #ifdef DEBUG_LHH
-       printk("Enter::%s\n",__FUNCTION__);
-       #endif
-}
-
-/*
- * Start transmitting.
- */
-static void rk29_serial_start_tx(struct uart_port *port)
-{
-       struct circ_buf *xmit = &port->state->xmit;
-
-    if(DBG_PORT == port->line) {
-        DBG("TX:");
-    }
-    
-       while(!(uart_circ_empty(xmit)))
-       {
-               while (!(rk29_uart_read(port,UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL)){
-            rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE|UART_IER_SEND_EMPTY_INT_ENABLE,UART_IER);
-            return;
-        }
-        rk29_uart_write(port,xmit->buf[xmit->tail],UART_THR);
-        
-        if(DBG_PORT == port->line) {
-            DBG("0x%x, ", xmit->buf[xmit->tail]);
-        }
-        
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-               port->icount.tx++;
-       }
-       if((uart_circ_empty(xmit)))
-               rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER);
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
-               uart_write_wakeup(port);        
-    
-    if(DBG_PORT == port->line) {
-        DBG("\n");
-    }
-}
-
-/*
- * Stop receiving - port is in process of being closed.
- */
-static void rk29_serial_stop_rx(struct uart_port *port)
-{
-    #ifdef DEBUG_LHH
-    printk("Enter::%s\n",__FUNCTION__);
-    #endif
-}
-
-/*
- * Control the transmission of a break signal
- */
-static void rk29_serial_break_ctl(struct uart_port *port, int break_state)
-{
-    unsigned int temp;
-    temp = rk29_uart_read(port,UART_LCR);
-    if (break_state != 0)       
-        temp = temp & (~BREAK_CONTROL_BIT);/* start break */
-       else
-        temp = temp | BREAK_CONTROL_BIT; /* stop break */
-    rk29_uart_write(port,temp,UART_LCR);       
-}
-
-
-/*
- * Characters received (called from interrupt handler)
- */
-static void rk29_rx_chars(struct uart_port *port)
-{
-       unsigned int ch, flag;
-    
-    if(DBG_PORT == port->line) {
-        DBG("RX:");
-    }
-    
-       while((rk29_uart_read(port,UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY)
-       {
-               u32 lsr = rk29_uart_read(port, UART_LSR);
-           ch = rk29_uart_read(port,UART_RBR);
-           flag = TTY_NORMAL;
-               port->icount.rx++;
-               if (lsr & UART_BREAK_INT_BIT) {
-                       port->icount.brk++;
-                       if (uart_handle_break(port))
-                               continue;
-               }
-#if 1
-               if (uart_handle_sysrq_char(port, ch))
-               {
-                       continue;
-               } 
-#endif
-               uart_insert_char(port, 0, 0, ch, flag);
-        
-        if(DBG_PORT == port->line) {
-            DBG("0x%x, ", ch);
-        }
-       }
-       tty_flip_buffer_push(port->state->port.tty);
-
-    if(DBG_PORT == port->line) {
-        DBG("\n");
-    }
-}
-
-/*
- * Interrupt handler
- */
-static irqreturn_t rk29_uart_interrupt(int irq, void *dev_id)
-{      
-       struct uart_port *port = dev_id;
-       unsigned int status, pending;
-       
-       spin_lock(&port->lock);
-       status = rk29_uart_read(port,UART_IIR); 
-       pending = status & 0x0f;
-    if((pending == UART_IIR_RECV_AVAILABLE) || (pending == UART_IIR_CHAR_TIMEOUT))
-               rk29_rx_chars(port);
-       if(pending == UART_IIR_THR_EMPTY)
-               rk29_serial_start_tx(port);             
-       spin_unlock(&port->lock);
-       return IRQ_HANDLED;     
-}
-
-/*
- * Disable the port
- */
-static void rk29_serial_shutdown(struct uart_port *port)
-{
-       struct rk29_port *rk29_port = UART_TO_RK29(port);
-       rk29_uart_write(port,0x00,UART_IER);
-       rk29_uart_write(port, UART_FCR_FIFO_ENABLE |
-               UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, UART_FCR);
-       //rk29_uart_write(port, 0, UART_FCR);
-       clk_disable(rk29_port->clk);
-       free_irq(port->irq, port);
-}
-/*
- * Perform initialization and enable port for reception
- */
-static int rk29_serial_startup(struct uart_port *port)
-{
-       struct rk29_port *rk29_port = UART_TO_RK29(port);
-       struct tty_struct *tty = port->state->port.tty; 
-       int retval;     
-       DBG("%s\n",__FUNCTION__);
-
-       if(2 == port->line) 
-       {
-               rk29_mux_api_set(GPIO2B1_UART2SOUT_NAME, GPIO2L_UART2_SOUT);
-               rk29_mux_api_set(GPIO2B0_UART2SIN_NAME, GPIO2L_UART2_SIN);
-       }
-       else if(0 == port->line) 
-       {
-               rk29_mux_api_set(GPIO1B7_UART0SOUT_NAME, GPIO1L_UART0_SOUT);
-               rk29_mux_api_set(GPIO1B6_UART0SIN_NAME, GPIO1L_UART0_SIN);
-       }
-       else if(3 == port->line)
-       {
-               rk29_mux_api_set(GPIO2B3_UART3SOUT_NAME, GPIO2L_UART3_SOUT);
-               rk29_mux_api_set(GPIO2B2_UART3SIN_NAME, GPIO2L_UART3_SIN);
-       }
-
-       retval = request_irq(port->irq,rk29_uart_interrupt,IRQF_SHARED,
-                    tty ? tty->name : "rk29_serial",port);
-       if(retval)
-       {
-               printk("\nrk29_serial_startup err \n"); 
-               rk29_serial_shutdown(port);
-               return  retval;
-       }       
-       clk_enable(rk29_port->clk);
-#if 0
-       if(port->irq == IRQ_NR_UART0)
-       rk29_uart_write(port,0xf7,UART_FCR);    //enable and clear fifo if busy while starting
-       else
-       rk29_uart_write(port,0xf1,UART_FCR);    //enable fifo
-       rk29_uart_write(port,0x01,UART_SFE);
-       rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER);  //enable uart recevice IRQ
-#else
-       //lw modify on 110309
-       /*
-        * Clear the FIFO buffers and disable them.
-        */
-       rk29_uart_write(port, UART_FCR_FIFO_ENABLE, UART_FCR);
-       rk29_uart_write(port, UART_FCR_FIFO_ENABLE |
-                       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, UART_FCR);
-       rk29_uart_write(port, 0, UART_FCR);
-       
-       /*
-        * Clear the interrupt registers.
-        */
-       (void) rk29_uart_read(port, UART_LSR);
-       (void) rk29_uart_read(port, UART_RBR);
-       (void) rk29_uart_read(port, UART_IIR);
-       (void) rk29_uart_read(port, UART_MSR);
-
-       /*
-        * And clear the user registers.
-        */
-       (void) rk29_uart_read(port, UART_USR);
-       
-#endif
-       return 0;
-}
-
-/*
- * Change the port parameters
- */
-static void rk29_serial_set_termios(struct uart_port *port, struct ktermios *termios,
-                             struct ktermios *old)
-{
-    unsigned long flags;
-    unsigned int mode, baud;
-       unsigned int umcon,fcr;
-       spin_lock_irqsave(&port->lock, flags);
-    /* Get current mode register */
-    mode = rk29_uart_read(port,UART_LCR) & (BREAK_CONTROL_BIT | EVEN_PARITY_SELECT | PARITY_ENABLED
-                       | ONE_HALF_OR_TWO_BIT | UART_DATABIT_MASK);  
-    
-    baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
-    /* byte size */
-    switch (termios->c_cflag & CSIZE) {
-    case CS5:
-        mode |= LCR_WLS_5;
-        break;
-    case CS6:
-        mode |= LCR_WLS_6;
-        break;
-    case CS7:
-        mode |= LCR_WLS_7;
-        break;
-    default:
-        mode |= LCR_WLS_8;
-        break;
-    }
-    
-    /* stop bits */
-    if (termios->c_cflag & CSTOPB)
-        mode |= ONE_STOP_BIT;
-    
-    /* parity */
-    if (termios->c_cflag & PARENB) 
-    {
-        mode |= PARITY_ENABLED;
-        if (termios->c_cflag & PARODD)
-            mode |= ODD_PARITY;
-        else
-            mode |= EVEN_PARITY;
-    }
-
-       int timeout = 10000000;
-       while(rk29_uart_read(port,UART_USR)&UART_USR_BUSY){
-       if(timeout-- == 0){
-       printk("rk29_serial_set_termios uart timeout,irq=%d,ret=0x%x\n",port->irq,rk29_uart_read(port,UART_USR));
-       break;
-       }
-       cpu_relax(); 
-       }       
-    
-       rk29_uart_write(port,mode,UART_LCR);
-       baud = rk29_set_baud_rate(port, baud);
-       uart_update_timeout(port, termios->c_cflag, baud);
-
-       /*
-        * enable FIFO and interrupt
-        */
-       if(termios->c_cflag & CRTSCTS)                               
-       {        
-               /*¿ªÆôuart0Ó²¼þÁ÷¿Ø*/
-               printk("start CRTSCTS control and baudrate is %d,irq=%d\n",baud,port->irq);
-               if(2 == port->line) 
-               {
-                       rk29_mux_api_set(GPIO2A7_UART2RTSN_NAME, GPIO2L_UART2_RTS_N);
-                       rk29_mux_api_set(GPIO2A6_UART2CTSN_NAME, GPIO2L_UART2_CTS_N);
-               }
-               else if(0 == port->line) 
-               {
-                       rk29_mux_api_set(GPIO1C1_UART0RTSN_SDMMC1WRITEPRT_NAME, GPIO1H_UART0_RTS_N);
-                       rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_UART0_CTS_N);
-               }
-               else if(3 == port->line)
-               {
-                       rk29_mux_api_set(GPIO2B5_UART3RTSN_I2C3SCL_NAME, GPIO2L_UART3_RTS_N);
-                       rk29_mux_api_set(GPIO2B4_UART3CTSN_I2C3SDA_NAME, GPIO2L_UART3_CTS_N);
-               }
-
-               umcon=rk29_uart_read(port,UART_MCR);
-               umcon |= UART_MCR_AFCEN;
-               umcon |= UART_MCR_URRTS;
-               umcon &=~UART_SIR_ENABLE;
-               rk29_uart_write(port,umcon,UART_MCR);
-               printk("UART_GET_MCR umcon=0x%x\n",umcon);
-       }
-       mode = mode | LCR_DLA_EN;
-
-#if 1
-       //lw modify on 110309
-       fcr = UART_FCR_FIFO_ENABLE | UART_FCR_R_TRIG_10 | UART_FCR_T_TRIG_10;
-       rk29_uart_write(port,  fcr,  UART_FCR); 
-       rk29_uart_write(port,0x01,UART_SFE);
-       rk29_uart_write(port,UART_IER_RECV_DATA_AVAIL_INT_ENABLE,UART_IER);  //enable uart recevice IRQ
-       printk("%s:fcr=0x%x,irq=%d\n",__FUNCTION__,fcr,port->irq);
-#endif
-
-       spin_unlock_irqrestore(&port->lock, flags);
-       
-}
-
-
-static void rk29_serial_release_port(struct uart_port *port)
-{
-    struct platform_device *pdev = to_platform_device(port->dev);
-       struct resource *resource;
-       resource_size_t size;
-
-       resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (unlikely(!resource))
-               return;
-       size = resource->end - resource->start + 1;
-
-       release_mem_region(port->mapbase, size);
-       iounmap(port->membase);
-       port->membase = NULL;
-}
-
-static int rk29_serial_request_port(struct uart_port *port)
-{
-       struct platform_device *pdev = to_platform_device(port->dev);
-       struct resource *resource;
-       resource_size_t size;
-
-       resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (unlikely(!resource))
-               return -ENXIO;
-       size = resource->end - resource->start + 1;
-
-       if (unlikely(!request_mem_region(port->mapbase, size, "rk29_serial")))
-               return -EBUSY;
-
-       port->membase = ioremap(port->mapbase, size);
-       if (!port->membase) {
-               release_mem_region(port->mapbase, size);
-               return -EBUSY;
-       }
-
-       return 0;
-}                    
-
-/*
- * Configure/autoconfigure the port.
- */
-static void rk29_serial_config_port(struct uart_port *port, int flags)
-{
-       if (flags & UART_CONFIG_TYPE) {
-               port->type = PORT_RK29;
-               rk29_serial_request_port(port);
-       }
-}
-
-/*
- * Verify the new serial_struct (for TIOCSSERIAL).
- */
-static int rk29_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
-       int ret = 0;
-       if (ser->type != PORT_UNKNOWN && ser->type != PORT_RK29)
-               ret = -EINVAL;
-       if (port->irq != ser->irq)
-               ret = -EINVAL;
-       if (ser->io_type != SERIAL_IO_MEM)
-               ret = -EINVAL;
-       if (port->uartclk / 16 != ser->baud_base)
-               ret = -EINVAL;
-       if ((void *)port->mapbase != ser->iomem_base)
-               ret = -EINVAL;
-       if (port->iobase != ser->port)
-               ret = -EINVAL;
-       if (ser->hub6 != 0)
-               ret = -EINVAL;
-       return ret;
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int rk29_serial_poll_get_char(struct uart_port *port)
-{
-       while (!((rk29_uart_read(port, UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY))
-               barrier();
-       return rk29_uart_read(port, UART_RBR);
-}
-
-static void rk29_serial_poll_put_char(struct uart_port *port, unsigned char c)
-{
-       while (!(rk29_uart_read(port, UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL))
-               barrier();
-       rk29_uart_write(port, c, UART_THR);
-}
-#endif /* CONFIG_CONSOLE_POLL */
-
-static struct uart_ops rk29_uart_pops = {
-       .tx_empty = rk29_serial_tx_empty,
-       .set_mctrl = rk29_serial_set_mctrl,
-       .get_mctrl = rk29_serial_get_mctrl,
-       .stop_tx = rk29_serial_stop_tx,
-       .start_tx = rk29_serial_start_tx,
-       .stop_rx = rk29_serial_stop_rx,
-       .enable_ms = rk29_serial_enable_ms,
-       .break_ctl = rk29_serial_break_ctl,
-       .startup = rk29_serial_startup,
-       .shutdown = rk29_serial_shutdown,
-       .set_termios = rk29_serial_set_termios,
-       .type = rk29_serial_type,
-       .release_port = rk29_serial_release_port,
-       .request_port = rk29_serial_request_port,
-       .config_port = rk29_serial_config_port,
-       .verify_port = rk29_serial_verify_port,
-       .pm = rk29_serial_pm,
-#ifdef CONFIG_CONSOLE_POLL
-       .poll_get_char = rk29_serial_poll_get_char,
-       .poll_put_char = rk29_serial_poll_put_char,
-#endif
-};
-
-
-static struct rk29_port rk29_uart_ports[] = {
-       {
-               .uart = {
-                       .iotype = UPIO_MEM,
-                       .ops = &rk29_uart_pops,
-                       .flags = UPF_BOOT_AUTOCONF,
-                       .fifosize = 32,
-                       .line = 0,
-               },
-       },
-       {
-               .uart = {
-                       .iotype = UPIO_MEM,
-                       .ops = &rk29_uart_pops,
-                       .flags = UPF_BOOT_AUTOCONF,
-                       .fifosize = 32,
-                       .line = 1,
-               },
-       },
-       {
-               .uart = {
-                       .iotype = UPIO_MEM,
-                       .ops = &rk29_uart_pops,
-                       .flags = UPF_BOOT_AUTOCONF,
-                       .fifosize = 32,
-                       .line = 2,
-               },
-       },
-       {
-               .uart = {
-                       .iotype = UPIO_MEM,
-                       .ops = &rk29_uart_pops,
-                       .flags = UPF_BOOT_AUTOCONF,
-                       .fifosize = 32,
-                       .line = 3,
-               },
-       },
-};
-
-#define UART_NR        ARRAY_SIZE(rk29_uart_ports)
-
-static inline struct uart_port *get_port_from_line(unsigned int line)
-{
-       return &rk29_uart_ports[line].uart;
-}
-
-#ifdef CONFIG_SERIAL_RK29_CONSOLE
-static void rk29_console_putchar(struct uart_port *port, int ch)
-{
-    while (!(rk29_uart_read(port,UART_USR) & UART_TRANSMIT_FIFO_NOT_FULL))
-               cpu_relax();
-       rk29_uart_write(port,ch,UART_THR);      
-}
-
-/*
- * Interrupts are disabled on entering
- */
-static void rk29_console_write(struct console *co, const char *s, u_int count)
-{
-       struct uart_port *port;
-       struct rk29_port *rk29_port;
-
-       BUG_ON(co->index < 0 || co->index >= UART_NR);
-
-       port = get_port_from_line(co->index);
-       rk29_port = UART_TO_RK29(port);
-
-       spin_lock(&port->lock);
-       uart_console_write(port, s, count, rk29_console_putchar);
-       spin_unlock(&port->lock);
-}
-
-static int __init rk29_console_setup(struct console *co, char *options)
-{
-       struct uart_port *port;
-       int baud, flow, bits, parity;
-       
-       if (unlikely(co->index >= UART_NR || co->index < 0))
-               return -ENXIO;
-
-       port = get_port_from_line(co->index);
-
-       if (unlikely(!port->membase))
-               return -ENXIO;
-
-       port->cons = co;
-
-       //rk29_init_clock(port);
-
-       if (options)
-               uart_parse_options(options, &baud, &parity, &bits, &flow);
-
-       bits = 8;
-       parity = 'n';
-       flow = 'n';     
-       rk29_uart_write(port,rk29_uart_read(port,UART_LCR) | LCR_WLS_8 | PARITY_DISABLED | ONE_STOP_BIT,UART_LCR);      /* 8N1 */
-       if (baud < 300 || baud > 115200)
-               baud = 115200;
-       rk29_set_baud_rate(port, baud);
-
-       printk(KERN_INFO "rk29_serial: console setup on port %d\n", port->line);
-
-       /* clear rx fifo, else will blocked on set_termios (always busy) */
-       while ((rk29_uart_read(port, UART_USR) & UART_RECEIVE_FIFO_NOT_EMPTY) == UART_RECEIVE_FIFO_NOT_EMPTY)
-               rk29_uart_read(port, UART_RBR);
-
-       return uart_set_options(port, co, baud, parity, bits, flow);    
-}
-
-static struct uart_driver rk29_uart_driver;
-
-static struct console rk29_console = {
-       .name = "ttyS",
-       .write = rk29_console_write,
-       .device = uart_console_device,
-       .setup = rk29_console_setup,
-       .flags = CON_PRINTBUFFER,
-       .index = 1,  
-       .data = &rk29_uart_driver,
-};
-
-#define RK29_CONSOLE   (&rk29_console)
-
-#else
-#define RK29_CONSOLE   NULL
-#endif
-
-static struct uart_driver rk29_uart_driver = {
-       .owner = THIS_MODULE,
-       .driver_name = "rk29_serial",
-       .dev_name = "ttyS",
-       .nr = UART_NR,
-       .cons = RK29_CONSOLE,
-       .major          = RK29_SERIAL_MAJOR,    
-       .minor          = RK29_SERIAL_MINOR,
-};
-
-static int __devinit rk29_serial_probe(struct platform_device *pdev)
-{
-       struct rk29_port *rk29_port;
-       struct resource *resource;
-       struct uart_port *port;
-    //struct rk29_serial_platform_data *pdata = pdev->dev.platform_data;
-               
-       if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
-               return -ENXIO;
-
-       printk(KERN_INFO "rk29_serial: detected port %d\n", pdev->id);
-
-       //if (pdata && pdata->io_init)
-               //pdata->io_init();
-    
-       port = get_port_from_line(pdev->id);
-       port->dev = &pdev->dev;
-       rk29_port = UART_TO_RK29(port);
-
-       rk29_port->clk = clk_get(&pdev->dev, "uart");
-       if (unlikely(IS_ERR(rk29_port->clk)))
-               return PTR_ERR(rk29_port->clk);
-       port->uartclk = 24000000; ///clk_get_rate(rk29_port->clk);
-
-       resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (unlikely(!resource))
-               return -ENXIO;
-       port->mapbase = resource->start;
-
-       port->irq = platform_get_irq(pdev, 0);
-       if (unlikely(port->irq < 0))
-               return -ENXIO;
-
-       platform_set_drvdata(pdev, port);
-
-       return uart_add_one_port(&rk29_uart_driver, port);      
-}
-
-static int __devexit rk29_serial_remove(struct platform_device *pdev)
-{
-       struct rk29_port *rk29_port = platform_get_drvdata(pdev);
-
-       clk_put(rk29_port->clk);
-
-       return 0;
-}
-
-static struct platform_driver rk29_platform_driver = {
-       .remove = rk29_serial_remove,
-       .driver = {
-               .name = "rk29_serial",
-               .owner = THIS_MODULE,
-       },
-};
-
-static int __init rk29_serial_init(void)
-{
-       int ret;
-       ret = uart_register_driver(&rk29_uart_driver);
-       if (unlikely(ret))
-               return ret;
-
-       ret = platform_driver_probe(&rk29_platform_driver, rk29_serial_probe);
-       if (unlikely(ret))
-               uart_unregister_driver(&rk29_uart_driver);
-
-       printk(KERN_INFO "rk29_serial: driver initialized\n");
-
-       return ret;
-}
-
-static void __exit rk29_serial_exit(void)
-{
-       #ifdef CONFIG_SERIAL_RK29_CONSOLE
-       unregister_console(&rk29_console);
-       #endif
-       platform_driver_unregister(&rk29_platform_driver);
-       uart_unregister_driver(&rk29_uart_driver);
-}
-
-/*
- * While this can be a module, if builtin it's most likely the console
- * So let's leave module_exit but move module_init to an earlier place
- */
-arch_initcall(rk29_serial_init);
-module_exit(rk29_serial_exit);
-
-MODULE_AUTHOR("lhh lhh@rock-chips.com");
-MODULE_DESCRIPTION("Rockchip rk29 Serial port driver");
-MODULE_LICENSE("GPL");
-
-
diff --git a/drivers/serial/rk_serial.c b/drivers/serial/rk_serial.c
deleted file mode 100644 (file)
index 91f35d1..0000000
+++ /dev/null
@@ -1,1917 +0,0 @@
-/*\r
- * Driver for RK-UART controller.\r
- * Based on drivers/tty/serial/8250.c\r
- *\r
- * Copyright (C) 2011 Rochchip.\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
-\r
- * (at your option) any later version.\r
- *\r
- * Author: hhb@rock-chips.com\r
- * Date: 2011.06.18\r
- */\r
-\r
-#ifndef CONFIG_SERIAL_RK_CONSOLE\r
-#if defined(CONFIG_SERIAL_RK29_CONSOLE)\r
-#define CONFIG_SERIAL_RK_CONSOLE\r
-#endif\r
-#endif\r
-\r
-#if defined(CONFIG_SERIAL_RK_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)\r
-#define SUPPORT_SYSRQ\r
-#endif\r
-\r
-//#define DEBUG\r
-#include <linux/module.h>\r
-#include <linux/ioport.h>\r
-#include <linux/init.h>\r
-#include <linux/console.h>\r
-#include <linux/sysrq.h>\r
-#include <linux/delay.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/tty.h>\r
-#include <linux/ratelimit.h>\r
-#include <linux/tty_flip.h>\r
-#include <linux/serial_reg.h>\r
-#include <linux/serial_core.h>\r
-#include <linux/serial.h>\r
-#include <linux/serial_8250.h>\r
-#include <linux/nmi.h>\r
-#include <linux/mutex.h>\r
-#include <linux/slab.h>\r
-#include <linux/clk.h>\r
-#include <linux/timer.h>\r
-#include <linux/workqueue.h>\r
-#include <mach/rk29-dma-pl330.h>\r
-#include <linux/dma-mapping.h>\r
-\r
-#include <asm/io.h>\r
-#include <asm/irq.h>\r
-\r
-\r
-#define PORT_RK                90\r
-#define UART_USR       0x1F    /* UART Status Register */\r
-#define UART_USR_BUSY (1)\r
-#define UART_IER_PTIME 0x80    /* Programmable THRE Interrupt Mode Enable */\r
-#define UART_LSR_RFE   0x80    /* receive fifo error */\r
-#define UART_SRR               0x22    /* software reset register */\r
-#define UART_RESET             0x01\r
-#define RX_TIMEOUT             (3000*10)  //uint ms\r
-\r
-#define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)\r
-\r
-#define UART_NR        4   //uart port number\r
-#define POWER_MANEGEMENT 1\r
-\r
-/* configurate whether the port transmit-receive by DMA */\r
-#define OPEN_DMA      1\r
-#define CLOSE_DMA     0\r
-\r
-#ifdef CONFIG_UART0_DMA_RK29\r
-#define UART0_USE_DMA OPEN_DMA\r
-#else\r
-#define UART0_USE_DMA CLOSE_DMA\r
-#endif\r
-\r
-#ifdef CONFIG_UART2_DMA_RK29\r
-#define UART2_USE_DMA OPEN_DMA\r
-#else\r
-#define UART2_USE_DMA CLOSE_DMA\r
-#endif\r
-\r
-#ifdef CONFIG_UART3_DMA_RK29\r
-#define UART3_USE_DMA OPEN_DMA\r
-#else\r
-#define UART3_USE_DMA CLOSE_DMA\r
-#endif\r
-\r
-#define UART1_USE_DMA CLOSE_DMA\r
-\r
-#define DMA_TX_TRRIGE_LEVEL 30\r
-\r
-#define USE_TIMER 1           // use timer for dma transport\r
-#define THRE_MODE 0X00   //0yhh\r
-\r
-static struct uart_driver serial_rk_reg;\r
-\r
-/*\r
- * Debugging.\r
- */\r
-#define DBG_PORT 1   //DBG_PORT which uart is used to print log message\r
-\r
-#ifdef CONFIG_SERIAL_CORE_CONSOLE\r
-#define uart_console(port)     ((port)->cons && (port)->cons->index == (port)->line)\r
-#else\r
-#define uart_console(port)     (0)\r
-#endif\r
-\r
-#define DEBUG 0\r
-\r
-extern void printascii(const char *);\r
-static void dbg(const char *fmt, ...)\r
-{\r
-       va_list va;\r
-       char buff[256];\r
-\r
-       va_start(va, fmt);\r
-       vsprintf(buff, fmt, va);\r
-       va_end(va);\r
-\r
-       printascii(buff);\r
-}\r
-\r
-#if DEBUG\r
-#define DEBUG_INTR(fmt...)     if (!uart_console(&up->port)) dbg(fmt)\r
-#else\r
-#define DEBUG_INTR(fmt...)     do { } while (0)\r
-#endif\r
-\r
-\r
-/* added by hhb@rock-chips.com for uart dma transfer */\r
-\r
-struct rk29_uart_dma_t {\r
-       u32 use_dma;            //1:used\r
-       u32 rx_dma_start;\r
-       enum dma_ch rx_dmach;\r
-       enum dma_ch tx_dmach;\r
-       u32 tx_dma_inited;\r
-       u32 rx_dma_inited;\r
-       spinlock_t              tx_lock;\r
-       spinlock_t              rx_lock;\r
-       char * rx_buffer;\r
-       char * tx_buffer;\r
-       dma_addr_t rx_phy_addr;\r
-       dma_addr_t tx_phy_addr;\r
-       u32 rx_buffer_size;\r
-       u32 tx_buffer_size;\r
-\r
-       u32 rb_cur_pos;\r
-       u32 rb_pre_pos;\r
-       u32 rx_size;\r
-       char use_timer;\r
-       char tx_dma_used;\r
-       /* timer to poll activity on rx dma */\r
-       struct timer_list       rx_timer;\r
-       int                     rx_timeout;\r
-\r
-};\r
-\r
-struct uart_rk_port {\r
-       struct uart_port        port;\r
-       struct platform_device  *pdev;\r
-       struct clk              *clk;\r
-       unsigned int            tx_loadsz;      /* transmit fifo load size */\r
-       unsigned char           ier;\r
-       unsigned char           lcr;\r
-       unsigned char           mcr;\r
-       unsigned char           iir;\r
-       unsigned char           fcr;\r
-       /*\r
-        * Some bits in registers are cleared on a read, so they must\r
-        * be saved whenever the register is read but the bits will not\r
-        * be immediately processed.\r
-        */\r
-#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS\r
-       unsigned char           lsr_saved_flags;\r
-#if 0\r
-#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA\r
-       unsigned char           msr_saved_flags;\r
-#endif\r
-\r
-       char                    name[12];\r
-       char                    fifo[32];\r
-       char                    fifo_size;\r
-       unsigned long           port_activity;\r
-       struct work_struct uart_work;\r
-       struct work_struct uart_work_rx;\r
-       struct workqueue_struct *uart_wq;\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t;\r
-};\r
-\r
-static void serial_rk_release_dma_tx(struct uart_port *port);\r
-static int serial_rk_start_tx_dma(struct uart_port *port);\r
-static void serial_rk_rx_timeout(unsigned long uart);\r
-static void serial_rk_release_dma_rx(struct uart_port *port);\r
-static int serial_rk_start_rx_dma(struct uart_port *port);\r
-static int serial_rk_startup(struct uart_port *port);\r
-static inline unsigned int serial_in(struct uart_rk_port *up, int offset)\r
-{\r
-       offset = offset << 2;\r
-       return readb(up->port.membase + offset);\r
-}\r
-\r
-/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */\r
-static inline void dwapb_save_out_value(struct uart_rk_port *up, int offset,\r
-                                       unsigned char value)\r
-{\r
-       if (offset == UART_LCR)\r
-               up->lcr = value;\r
-}\r
-\r
-/* Read the IER to ensure any interrupt is cleared before returning from ISR. */\r
-static inline void dwapb_check_clear_ier(struct uart_rk_port *up, int offset)\r
-{\r
-       if (offset == UART_TX || offset == UART_IER)\r
-               serial_in(up, UART_IER);\r
-}\r
-\r
-static inline void serial_out(struct uart_rk_port *up, int offset, unsigned char value)\r
-{\r
-       dwapb_save_out_value(up, offset, value);\r
-       writeb(value, up->port.membase + (offset << 2));\r
-       dwapb_check_clear_ier(up, offset);\r
-}\r
-\r
-/* Uart divisor latch read */\r
-static inline int serial_dl_read(struct uart_rk_port *up)\r
-{\r
-       return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;\r
-}\r
-\r
-/* Uart divisor latch write */\r
-static int serial_dl_write(struct uart_rk_port *up, unsigned int value)\r
-{\r
-       unsigned int tmout = 100;\r
-       if(up->port.line != DBG_PORT)\r
-       {\r
-               while(!(serial_in(up, UART_LCR) & UART_LCR_DLAB)){\r
-                       if (--tmout == 0){\r
-                               dbg("set serial.%d baudrate fail with DLAB not set\n", up->port.line);\r
-                               return -1;\r
-                       }\r
-               }\r
-\r
-               tmout = 15000;\r
-               while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
-                       if (--tmout == 0){\r
-                               dbg("set serial.%d baudrate timeout\n", up->port.line);\r
-                               return -1;\r
-                       }\r
-               }\r
-       }\r
-\r
-       serial_out(up, UART_DLL, value & 0xff);\r
-       serial_out(up, UART_DLM, value >> 8 & 0xff);\r
-\r
-       return 0;\r
-\r
-}\r
-\r
-static int serial_lcr_write(struct uart_rk_port *up, unsigned char value)\r
-{\r
-       unsigned int tmout = 15000;\r
-\r
-       if(up->port.line != DBG_PORT)\r
-       {\r
-               while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
-\r
-                       if (--tmout == 0){\r
-                               dbg("set serial.%d lc r = 0x%02x timeout\n", up->port.line, value);\r
-                               return -1;\r
-                       }\r
-                       udelay(1);\r
-               }\r
-       }\r
-\r
-       serial_out(up, UART_LCR, value);\r
-\r
-       return 0;\r
-}\r
-\r
-static inline void serial_rk_enable_ier_thri(struct uart_rk_port *up)\r
-{\r
-       if (!(up->ier & UART_IER_THRI)) {\r
-               up->ier |= UART_IER_THRI;\r
-               serial_out(up, UART_IER, up->ier);\r
-       }\r
-}\r
-\r
-\r
-static inline void serial_rk_disable_ier_thri(struct uart_rk_port *up)\r
-{\r
-       if (up->ier & UART_IER_THRI) {\r
-               up->ier &= ~UART_IER_THRI;\r
-               serial_out(up, UART_IER, up->ier);\r
-       }\r
-}\r
-#if 0\r
-static int rk29_uart_dump_register(struct uart_rk_port *up){\r
-\r
-       unsigned int reg_value = 0;\r
-\r
-       reg_value = serial_in(up, UART_IER);\r
-       dbg("UART_IER = 0x%0x\n", reg_value);\r
-       reg_value = serial_in(up, UART_IIR);\r
-       dbg("UART_IIR = 0x%0x\n", reg_value);\r
-    reg_value = serial_in(up, UART_LSR);\r
-    dbg("UART_LSR = 0x%0x\n", reg_value);\r
-    reg_value = serial_in(up, UART_MSR);\r
-    dbg("UART_MSR = 0x%0x\n", reg_value);\r
-    reg_value = serial_in(up, UART_MCR);\r
-    dbg("UART_MCR = 0x%0x\n", reg_value);\r
-    reg_value = serial_in(up, 0x21);\r
-    dbg("UART_RFL = 0x%0x\n", reg_value);\r
-    reg_value = serial_in(up, UART_LCR);\r
-    dbg("UART_LCR = 0x%0x\n", reg_value);\r
-       return 0;\r
-\r
-}\r
-#endif\r
-\r
-/*\r
- * FIFO support.\r
- */\r
-static void serial_rk_clear_fifos(struct uart_rk_port *up)\r
-{\r
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);\r
-       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |\r
-                      UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);\r
-       serial_out(up, UART_FCR, 0);\r
-}\r
-\r
-static inline void __stop_tx(struct uart_rk_port *p)\r
-{\r
-       if (p->ier & UART_IER_THRI) {\r
-               p->ier &= ~UART_IER_THRI;\r
-               serial_out(p, UART_IER, p->ier);\r
-       }\r
-}\r
-\r
-static void serial_rk_stop_tx(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-\r
-       if(OPEN_DMA == prk29_uart_dma_t->use_dma){\r
-               serial_rk_release_dma_tx(port);\r
-       }\r
-       __stop_tx(up);\r
-}\r
-\r
-\r
-static void serial_rk_start_tx(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-\r
-\r
-       if(0 == serial_rk_start_tx_dma(port)){\r
-               serial_rk_enable_ier_thri(up);\r
-       }\r
-\r
-}\r
-\r
-\r
-static void serial_rk_stop_rx(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-\r
-       if(OPEN_DMA == prk29_uart_dma_t->use_dma){\r
-               serial_rk_release_dma_rx(port);\r
-       }\r
-       up->ier &= ~UART_IER_RLSI;\r
-       up->port.read_status_mask &= ~UART_LSR_DR;\r
-       serial_out(up, UART_IER, up->ier);\r
-}\r
-\r
-\r
-static void serial_rk_enable_ms(struct uart_port *port)\r
-{\r
-       /* no MSR capabilities */\r
-#if 0\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-       up->ier |= UART_IER_MSI;\r
-       serial_out(up, UART_IER, up->ier);\r
-#endif\r
-}\r
-\r
-\r
-/*\r
- * Start transmitting by dma.\r
- */\r
-#define DMA_SERIAL_BUFFER_SIZE     UART_XMIT_SIZE\r
-\r
-/* added by hhb@rock-chips.com  for uart dma transfer*/\r
-static struct rk29_uart_dma_t rk29_uart_ports_dma_t[] = {\r
-               {UART0_USE_DMA, 0, DMACH_UART0_RX, DMACH_UART0_TX},\r
-               {UART1_USE_DMA, 0, DMACH_UART1_RX, DMACH_UART1_TX},\r
-               {UART2_USE_DMA, 0, DMACH_UART2_RX, DMACH_UART2_TX},\r
-               {UART3_USE_DMA, 0, DMACH_UART3_RX, DMACH_UART3_TX},\r
-};\r
-\r
-\r
-/* DMAC PL330 add by hhb@rock-chips.com */\r
-static struct rk29_dma_client rk29_uart_dma_client = {\r
-       .name = "rk29xx-uart-dma",\r
-};\r
-\r
-/*TX*/\r
-\r
-static void serial_rk_release_dma_tx(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-                       container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(!port){\r
-               return;\r
-       }\r
-       if(prk29_uart_dma_t && prk29_uart_dma_t->tx_dma_inited) {\r
-               rk29_dma_free(prk29_uart_dma_t->tx_dmach, &rk29_uart_dma_client);\r
-               prk29_uart_dma_t->tx_dma_inited = 0;\r
-       }\r
-}\r
-\r
-/*this function will be called every time after rk29_dma_enqueue() be invoked*/\r
-static void serial_rk_dma_txcb(void *buf, int size, enum rk29_dma_buffresult result) {\r
-       struct uart_port *port = buf;\r
-       struct uart_rk_port *up = container_of(port, struct uart_rk_port, port);\r
-       struct circ_buf *xmit = &port->state->xmit;\r
-\r
-       if(result != RK29_RES_OK){\r
-               return;\r
-       }\r
-\r
-       port->icount.tx += size;\r
-       xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);\r
-\r
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
-               uart_write_wakeup(&up->port);\r
-       spin_lock(&(up->prk29_uart_dma_t->tx_lock));\r
-       up->prk29_uart_dma_t->tx_dma_used = 0;\r
-       spin_unlock(&(up->prk29_uart_dma_t->tx_lock));\r
-       if (!uart_circ_empty(xmit)) {\r
-               serial_rk_start_tx_dma(port);\r
-       }\r
-\r
-       up->port_activity = jiffies;\r
-//     dev_info(up->port.dev, "s:%d\n", size);\r
-}\r
-\r
-static int serial_rk_init_dma_tx(struct uart_port *port) {\r
-\r
-       struct uart_rk_port *up =\r
-                               container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(!port || !prk29_uart_dma_t){\r
-               dev_info(up->port.dev, "serial_rk_init_dma_tx fail\n");\r
-               return -1;\r
-       }\r
-\r
-       if(prk29_uart_dma_t->tx_dma_inited) {\r
-               return 0;\r
-       }\r
-\r
-       if (rk29_dma_request(prk29_uart_dma_t->tx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
-               dev_info(up->port.dev, "rk29_dma_request tx fail\n");\r
-               return -1;\r
-       }\r
-\r
-       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->tx_dmach, serial_rk_dma_txcb)) {\r
-               dev_info(up->port.dev, "rk29_dma_set_buffdone_fn tx fail\n");\r
-               return -1;\r
-       }\r
-       if (rk29_dma_devconfig(prk29_uart_dma_t->tx_dmach, RK29_DMASRC_MEM, (unsigned long)(port->iobase + UART_TX))) {\r
-               dev_info(up->port.dev, "rk29_dma_devconfig tx fail\n");\r
-               return -1;\r
-       }\r
-       if (rk29_dma_config(prk29_uart_dma_t->tx_dmach, 1, 1)) {\r
-               dev_info(up->port.dev, "rk29_dma_config tx fail\n");\r
-               return -1;\r
-       }\r
-\r
-       prk29_uart_dma_t->tx_dma_inited = 1;\r
-       dev_info(up->port.dev, "serial_rk_init_dma_tx sucess\n");\r
-       return 0;\r
-\r
-}\r
-\r
-static int serial_rk_start_tx_dma(struct uart_port *port)\r
-{\r
-\r
-       struct circ_buf *xmit = &port->state->xmit;\r
-       struct uart_rk_port *up = container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-\r
-       if(0 == prk29_uart_dma_t->use_dma){\r
-               return CLOSE_DMA;\r
-       }\r
-\r
-       if(-1 == serial_rk_init_dma_tx(port)){\r
-               goto err_out;\r
-       }\r
-\r
-       if (1 == prk29_uart_dma_t->tx_dma_used){\r
-               return 1;\r
-       }\r
-       if(!uart_circ_empty(xmit)){\r
-               if (rk29_dma_enqueue(prk29_uart_dma_t->tx_dmach, port,\r
-                               prk29_uart_dma_t->tx_phy_addr + xmit->tail,\r
-                               CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE))) {\r
-                       goto err_out;\r
-               }\r
-       }\r
-       rk29_dma_ctrl(prk29_uart_dma_t->tx_dmach, RK29_DMAOP_START);\r
-       spin_lock(&(prk29_uart_dma_t->tx_lock));\r
-       up->prk29_uart_dma_t->tx_dma_used = 1;\r
-       spin_unlock(&(prk29_uart_dma_t->tx_lock));\r
-\r
-       return 1;\r
-err_out:\r
-       dev_info(up->port.dev, "-serial_rk_start_tx_dma-error-\n");\r
-       return -1;\r
-\r
-}\r
-\r
-\r
-\r
-/*RX*/\r
-static void serial_rk_dma_rxcb(void *buf, int size, enum rk29_dma_buffresult result) {\r
-\r
-\r
-}\r
-\r
-static void serial_rk_release_dma_rx(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-                               container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(!port){\r
-               return;\r
-       }\r
-       if(prk29_uart_dma_t && prk29_uart_dma_t->rx_dma_inited) {\r
-               del_timer(&prk29_uart_dma_t->rx_timer);\r
-               rk29_dma_free(prk29_uart_dma_t->rx_dmach, &rk29_uart_dma_client);\r
-               prk29_uart_dma_t->rb_pre_pos = 0;\r
-               prk29_uart_dma_t->rx_dma_inited = 0;\r
-               prk29_uart_dma_t->rx_dma_start = 0;\r
-       }\r
-}\r
-\r
-\r
-static int serial_rk_init_dma_rx(struct uart_port *port) {\r
-\r
-       struct uart_rk_port *up =\r
-                               container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(!port || !prk29_uart_dma_t){\r
-               dev_info(up->port.dev, "serial_rk_init_dma_rx: port fail\n");\r
-               return -1;\r
-       }\r
-       if(prk29_uart_dma_t->rx_dma_inited) {\r
-               return 0;\r
-       }\r
-\r
-       if (rk29_dma_request(prk29_uart_dma_t->rx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
-               dev_info(up->port.dev, "rk29_dma_request fail rx \n");\r
-               return -1;\r
-       }\r
-\r
-       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->rx_dmach, serial_rk_dma_rxcb)) {\r
-               dev_info(up->port.dev, "rk29_dma_set_buffdone_fn rx fail\n");\r
-               return -1;\r
-       }\r
-       if (rk29_dma_devconfig(prk29_uart_dma_t->rx_dmach, RK29_DMASRC_HW, (unsigned long)(port->iobase + UART_RX))) {\r
-               dev_info(up->port.dev, "rk29_dma_devconfig rx fail\n");\r
-               return -1;\r
-       }\r
-\r
-       if (rk29_dma_config(prk29_uart_dma_t->rx_dmach, 1, 1)) {\r
-               dev_info(up->port.dev, "rk29_dma_config rx fail\n");\r
-               return -1;\r
-       }\r
-\r
-       rk29_dma_setflags(prk29_uart_dma_t->rx_dmach, RK29_DMAF_CIRCULAR);\r
-\r
-       prk29_uart_dma_t->rx_dma_inited = 1;\r
-       dev_info(up->port.dev, "serial_rk_init_dma_rx sucess\n");\r
-       return 0;\r
-\r
-}\r
-\r
-static int serial_rk_start_rx_dma(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-                               container_of(port, struct uart_rk_port, port);\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(0 == prk29_uart_dma_t->use_dma){\r
-               return 0;\r
-       }\r
-\r
-       if(prk29_uart_dma_t->rx_dma_start == 1){\r
-               return 0;\r
-       }\r
-\r
-       if(-1 == serial_rk_init_dma_rx(port)){\r
-               dev_info(up->port.dev, "*******serial_rk_init_dma_rx*******error*******\n");\r
-               return -1;\r
-       }\r
-\r
-       if (rk29_dma_enqueue(prk29_uart_dma_t->rx_dmach, (void *)up, prk29_uart_dma_t->rx_phy_addr,\r
-                       prk29_uart_dma_t->rx_buffer_size/2)) {\r
-               dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
-               return -1;\r
-       }\r
-\r
-       if (rk29_dma_enqueue(prk29_uart_dma_t->rx_dmach, (void *)up,\r
-                       prk29_uart_dma_t->rx_phy_addr+prk29_uart_dma_t->rx_buffer_size/2,\r
-               prk29_uart_dma_t->rx_buffer_size/2)) {\r
-               dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
-               return -1;\r
-       }\r
-\r
-       rk29_dma_ctrl(prk29_uart_dma_t->rx_dmach, RK29_DMAOP_START);\r
-       prk29_uart_dma_t->rx_dma_start = 1;\r
-       if(prk29_uart_dma_t->use_timer == 1){\r
-               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies +\r
-                               msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
-       }\r
-       up->port_activity = jiffies;\r
-       return 1;\r
-}\r
-\r
-static void serial_rk_update_rb_addr(struct uart_rk_port *up){\r
-       dma_addr_t current_pos = 0;\r
-       dma_addr_t rx_current_pos = 0;\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
-       rk29_dma_getposition(prk29_uart_dma_t->rx_dmach, &current_pos, &rx_current_pos);\r
-\r
-       prk29_uart_dma_t->rb_cur_pos = (rx_current_pos - prk29_uart_dma_t->rx_phy_addr);\r
-       prk29_uart_dma_t->rx_size = CIRC_CNT(prk29_uart_dma_t->rb_cur_pos,\r
-                       prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_buffer_size);\r
-\r
-       spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
-}\r
-\r
-static void serial_rk_report_dma_rx(unsigned long uart)\r
-{\r
-       struct uart_rk_port *up = (struct uart_rk_port *)uart;\r
-       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
-       if(prk29_uart_dma_t->use_timer == 1){\r
-               serial_rk_update_rb_addr(up);\r
-       }\r
-       if(prk29_uart_dma_t->rx_size > 0) {\r
-               spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
-\r
-               if(prk29_uart_dma_t->rb_cur_pos > prk29_uart_dma_t->rb_pre_pos){\r
-                       tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer\r
-                                       + prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_size);\r
-                       tty_flip_buffer_push(up->port.state->port.tty);\r
-               }\r
-               else if(prk29_uart_dma_t->rb_cur_pos < prk29_uart_dma_t->rb_pre_pos){\r
-\r
-                       tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer\r
-                                       + prk29_uart_dma_t->rb_pre_pos, CIRC_CNT_TO_END(prk29_uart_dma_t->rb_cur_pos,\r
-                                       prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_buffer_size));\r
-                       tty_flip_buffer_push(up->port.state->port.tty);\r
-\r
-                       if(prk29_uart_dma_t->rb_cur_pos != 0){\r
-                               tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer,\r
-                                               prk29_uart_dma_t->rb_cur_pos);\r
-                               tty_flip_buffer_push(up->port.state->port.tty);\r
-                       }\r
-               }\r
-\r
-               prk29_uart_dma_t->rb_pre_pos = (prk29_uart_dma_t->rb_pre_pos + prk29_uart_dma_t->rx_size)\r
-                               & (prk29_uart_dma_t->rx_buffer_size - 1);\r
-               up->port.icount.rx += prk29_uart_dma_t->rx_size;\r
-               spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
-               prk29_uart_dma_t->rx_timeout = 7;\r
-               up->port_activity = jiffies;\r
-       }\r
-\r
-\r
-#if 1\r
-       if (jiffies_to_msecs(jiffies - up->port_activity) < RX_TIMEOUT) {\r
-               if(prk29_uart_dma_t->use_timer == 1){\r
-                       mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
-               }\r
-       } else {\r
-\r
-#if 1\r
-\r
-\r
-               prk29_uart_dma_t->rx_timeout = 20;\r
-               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
-#else\r
-//             serial_out(up, 0x2a, 0x01);\r
-               serial_rk_release_dma_rx(&up->port);\r
-               serial_out(up, 0x2a, 0x01);\r
-               up->ier |= (UART_IER_RDI | UART_IER_RLSI);\r
-               serial_out(up, UART_IER, up->ier);\r
-//             serial_out(up, 0x22, 0x01);\r
-               dev_info(up->port.dev, "*****enable recv int*****\n");\r
-\r
-               //serial_rk_start_rx_dma(&up->port);\r
-#endif\r
-       }\r
-\r
-\r
-#else\r
-       if(prk29_uart_dma_t->use_timer == 1){\r
-               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
-       }\r
-#endif\r
-\r
-}\r
-\r
-static void serial_rk_rx_timeout(unsigned long uart)\r
-{\r
-       struct uart_rk_port *up = (struct uart_rk_port *)uart;\r
-\r
-       //serial_rk_report_dma_rx(up);\r
-       queue_work(up->uart_wq, &up->uart_work);\r
-}\r
-\r
-static void serial_rk_report_revdata_workfunc(struct work_struct *work)\r
-{\r
-       struct uart_rk_port *up =\r
-                               container_of(work, struct uart_rk_port, uart_work);\r
-       serial_rk_report_dma_rx((unsigned long)up);\r
-       spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
-\r
-       if(up->prk29_uart_dma_t->use_timer == 1){\r
-\r
-       }else{\r
-               tty_insert_flip_string(up->port.state->port.tty, up->fifo, up->fifo_size);\r
-               tty_flip_buffer_push(up->port.state->port.tty);\r
-               up->port.icount.rx += up->fifo_size;\r
-       }\r
-\r
-       spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
-\r
-}\r
-\r
-\r
-static void serial_rk_start_dma_rx(struct work_struct *work)\r
-{\r
-       struct uart_rk_port *up =\r
-                                       container_of(work, struct uart_rk_port, uart_work_rx);\r
-       serial_rk_start_rx_dma(&up->port);\r
-}\r
-\r
-\r
-\r
-static void\r
-receive_chars(struct uart_rk_port *up, unsigned int *status)\r
-{\r
-       struct tty_struct *tty = up->port.state->port.tty;\r
-       unsigned char ch, lsr = *status;\r
-       int max_count = 256;\r
-       char flag;\r
-\r
-       do {\r
-               if (likely(lsr & UART_LSR_DR)){\r
-                       ch = serial_in(up, UART_RX);\r
-               }\r
-               else\r
-                       /*\r
-                        * Intel 82571 has a Serial Over Lan device that will\r
-                        * set UART_LSR_BI without setting UART_LSR_DR when\r
-                        * it receives a break. To avoid reading from the\r
-                        * receive buffer without UART_LSR_DR bit set, we\r
-                        * just force the read character to be 0\r
-                        */\r
-                       ch = 0;\r
-\r
-               flag = TTY_NORMAL;\r
-               up->port.icount.rx++;\r
-\r
-               lsr |= up->lsr_saved_flags;\r
-               up->lsr_saved_flags = 0;\r
-\r
-               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {\r
-                       /*\r
-                        * For statistics only\r
-                        */\r
-                       if (lsr & UART_LSR_BI) {\r
-                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);\r
-                               up->port.icount.brk++;\r
-                               /*\r
-                                * We do the SysRQ and SAK checking\r
-                                * here because otherwise the break\r
-                                * may get masked by ignore_status_mask\r
-                                * or read_status_mask.\r
-                                */\r
-                               if (uart_handle_break(&up->port))\r
-                                       goto ignore_char;\r
-                       } else if (lsr & UART_LSR_PE)\r
-                               up->port.icount.parity++;\r
-                       else if (lsr & UART_LSR_FE)\r
-                               up->port.icount.frame++;\r
-                       if (lsr & UART_LSR_OE)\r
-                               up->port.icount.overrun++;\r
-\r
-\r
-                       /*\r
-                        * Mask off conditions which should be ignored.\r
-                        */\r
-                       lsr &= up->port.read_status_mask;\r
-\r
-                       if (lsr & UART_LSR_BI) {\r
-                               DEBUG_INTR("handling break....");\r
-                               flag = TTY_BREAK;\r
-                       } else if (lsr & UART_LSR_PE)\r
-                               flag = TTY_PARITY;\r
-                       else if (lsr & UART_LSR_FE)\r
-                               flag = TTY_FRAME;\r
-               }\r
-               if (uart_handle_sysrq_char(&up->port, ch))\r
-                       goto ignore_char;\r
-\r
-               uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);\r
-\r
-ignore_char:\r
-               lsr = serial_in(up, UART_LSR);\r
-       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));\r
-       spin_unlock(&up->port.lock);\r
-       tty_flip_buffer_push(tty);\r
-       spin_lock(&up->port.lock);\r
-       *status = lsr;\r
-}\r
-\r
-static void transmit_chars(struct uart_rk_port *up)\r
-{\r
-       struct circ_buf *xmit = &up->port.state->xmit;\r
-       int count;\r
-\r
-       if (up->port.x_char) {\r
-               serial_out(up, UART_TX, up->port.x_char);\r
-               up->port.icount.tx++;\r
-               up->port.x_char = 0;\r
-               return;\r
-       }\r
-       if (uart_tx_stopped(&up->port)) {\r
-               __stop_tx(up);\r
-               return;\r
-       }\r
-       if (uart_circ_empty(xmit)) {\r
-               __stop_tx(up);\r
-               return;\r
-       }\r
-\r
-       count = up->tx_loadsz;\r
-       do {\r
-               serial_out(up, UART_TX, xmit->buf[xmit->tail]);\r
-               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\r
-               up->port.icount.tx++;\r
-               if (uart_circ_empty(xmit))\r
-                       break;\r
-       } while (--count > 0);\r
-\r
-       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
-               uart_write_wakeup(&up->port);\r
-\r
-       DEBUG_INTR("THRE...");\r
-\r
-       if (uart_circ_empty(xmit))\r
-               __stop_tx(up);\r
-}\r
-\r
-static unsigned int check_modem_status(struct uart_rk_port *up)\r
-{\r
-       unsigned int status = serial_in(up, UART_MSR);\r
-\r
-#if 0\r
-       status |= up->msr_saved_flags;\r
-       up->msr_saved_flags = 0;\r
-       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&\r
-           up->port.state != NULL) {\r
-               if (status & UART_MSR_TERI)\r
-                       up->port.icount.rng++;\r
-               if (status & UART_MSR_DDSR)\r
-                       up->port.icount.dsr++;\r
-               if (status & UART_MSR_DDCD)\r
-                       uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);\r
-               if (status & UART_MSR_DCTS)\r
-                       uart_handle_cts_change(&up->port, status & UART_MSR_CTS);\r
-\r
-               wake_up_interruptible(&up->port.state->port.delta_msr_wait);\r
-       }\r
-#endif\r
-\r
-       return status;\r
-}\r
-\r
-\r
-/*\r
- * This handles the interrupt from one port.\r
- */\r
-static void serial_rk_handle_port(struct uart_rk_port *up)\r
-{\r
-       unsigned int status;\r
-       unsigned long flags;\r
-       spin_lock_irqsave(&up->port.lock, flags);\r
-\r
-       /* reading UART_LSR can automatically clears PE FE OE bits, except receive fifo error bit*/\r
-       status = serial_in(up, UART_LSR);\r
-\r
-       DEBUG_INTR("status = %x...", status);\r
-       /* DMA mode enable */\r
-       if(up->prk29_uart_dma_t->use_dma == 1) {\r
-\r
-               if(up->iir & UART_IIR_RLSI){\r
-                       if (status & (UART_LSR_DR | UART_LSR_BI)) {\r
-                               up->port_activity = jiffies;\r
-                               up->ier &= ~UART_IER_RLSI;\r
-                               up->ier &= ~UART_IER_RDI;\r
-                               serial_out(up, UART_IER, up->ier);\r
-                               //receive_chars(up, &status);\r
-                               //mod_timer(&up->prk29_uart_dma_t->rx_timer, jiffies +\r
-                               //msecs_to_jiffies(up->prk29_uart_dma_t->rx_timeout));\r
-                               if(serial_rk_start_rx_dma(&up->port) == -1){\r
-                                       receive_chars(up, &status);\r
-                               }\r
-                       }\r
-               }\r
-\r
-       }else {   //dma mode disable\r
-\r
-               /*\r
-                * when uart receive a serial of data which doesn't have stop bit and so on, that causes frame error,and\r
-                * set UART_LSR_RFE to one,what is worse,we couldn't read the data in the receive fifo. So if\r
-                * wo don't clear this bit and reset the receive fifo, the received data available interrupt would\r
-                * occur continuously.  added by hhb@rock-chips.com 2011-08-05\r
-                */\r
-\r
-               if (status & UART_LSR_RFE) {\r
-                       \r
-                       if(up->port.line != DBG_PORT){\r
-                               status = serial_in(up, UART_LSR);\r
-                               dev_info(up->port.dev, "error:lsr=0x%x\n", status);\r
-                       }\r
-                       \r
-                       \r
-               //      rk29_uart_dump_register(up);\r
-               }\r
-\r
-               if (status & (UART_LSR_DR | UART_LSR_BI)) {\r
-                       receive_chars(up, &status);\r
-               }\r
-               check_modem_status(up);\r
-               if (status & UART_LSR_THRE) {\r
-                       transmit_chars(up);\r
-               }\r
-       }\r
-\r
-       spin_unlock_irqrestore(&up->port.lock, flags);\r
-}\r
-\r
-/*\r
- * This is the serial driver's interrupt routine.\r
- */\r
-\r
-static irqreturn_t serial_rk_interrupt(int irq, void *dev_id)\r
-{\r
-       struct uart_rk_port *up = dev_id;\r
-       int handled = 0;\r
-       unsigned int iir;\r
-\r
-       iir = serial_in(up, UART_IIR);\r
-\r
-       DEBUG_INTR("%s(%d) iir = 0x%02x\n", __func__, irq, iir);\r
-\r
-       up->iir = iir;\r
-\r
-       if (!(iir & UART_IIR_NO_INT)) {\r
-               serial_rk_handle_port(up);\r
-               handled = 1;\r
-       } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {\r
-\r
-               /* The DesignWare APB UART has an Busy Detect (0x07)\r
-                * interrupt meaning an LCR write attempt occured while the\r
-                * UART was busy. The interrupt must be cleared by reading\r
-                * the UART status register (USR) and the LCR re-written. */\r
-\r
-               if(!(serial_in(up, UART_USR) & UART_USR_BUSY)){\r
-                       serial_out(up, UART_LCR, up->lcr);\r
-               }\r
-               handled = 1;\r
-               dbg("the serial.%d is busy\n", up->port.line);\r
-       }\r
-       DEBUG_INTR("end(%d).\n", handled);\r
-\r
-       return IRQ_RETVAL(handled);\r
-}\r
-\r
-static unsigned int serial_rk_tx_empty(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned long flags;\r
-       unsigned int lsr;\r
-\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-       spin_lock_irqsave(&up->port.lock, flags);\r
-       lsr = serial_in(up, UART_LSR);\r
-       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;\r
-       spin_unlock_irqrestore(&up->port.lock, flags);\r
-\r
-       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;\r
-}\r
-\r
-static unsigned int serial_rk_get_mctrl(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned int status;\r
-       unsigned int ret;\r
-\r
-       status = check_modem_status(up);\r
-\r
-       ret = 0;\r
-       if (status & UART_MSR_DCD)\r
-               ret |= TIOCM_CAR;\r
-       if (status & UART_MSR_RI)\r
-               ret |= TIOCM_RNG;\r
-       if (status & UART_MSR_DSR)\r
-               ret |= TIOCM_DSR;\r
-       if (status & UART_MSR_CTS)\r
-               ret |= TIOCM_CTS;\r
-       dev_dbg(port->dev, "%s 0x%08x\n", __func__, ret);\r
-       return ret;\r
-}\r
-\r
-static void serial_rk_set_mctrl(struct uart_port *port, unsigned int mctrl)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned char mcr = 0;\r
-\r
-       dev_dbg(port->dev, "+%s\n", __func__);\r
-       if (mctrl & TIOCM_RTS)\r
-               mcr |= UART_MCR_RTS;\r
-       if (mctrl & TIOCM_DTR)\r
-               mcr |= UART_MCR_DTR;\r
-       if (mctrl & TIOCM_OUT1)\r
-               mcr |= UART_MCR_OUT1;\r
-       if (mctrl & TIOCM_OUT2)\r
-               mcr |= UART_MCR_OUT2;\r
-       if (mctrl & TIOCM_LOOP)\r
-               mcr |= UART_MCR_LOOP;\r
-\r
-       mcr |= up->mcr;\r
-\r
-       serial_out(up, UART_MCR, mcr);\r
-       dev_dbg(port->dev, "-serial.%d %s mcr: 0x%02x\n", port->line, __func__, mcr);\r
-}\r
-\r
-static void serial_rk_break_ctl(struct uart_port *port, int break_state)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned long flags;\r
-\r
-       dev_dbg(port->dev, "+%s\n", __func__);\r
-       spin_lock_irqsave(&up->port.lock, flags);\r
-       if (break_state == -1)\r
-               up->lcr |= UART_LCR_SBC;\r
-       else\r
-               up->lcr &= ~UART_LCR_SBC;\r
-       serial_lcr_write(up, up->lcr);\r
-       spin_unlock_irqrestore(&up->port.lock, flags);\r
-       dev_dbg(port->dev, "-%s lcr: 0x%02x\n", __func__, up->lcr);\r
-}\r
-\r
-/*\r
- *     Wait for transmitter & holding register to empty\r
- */\r
-static void wait_for_xmitr(struct uart_rk_port *up, int bits)\r
-{\r
-       unsigned int status, tmout = 10000;\r
-\r
-       /* Wait up to 10ms for the character(s) to be sent. */\r
-       for (;;) {\r
-               status = serial_in(up, UART_LSR);\r
-\r
-               up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;\r
-\r
-               if ((status & bits) == bits)\r
-                       break;\r
-               if (--tmout == 0)\r
-                       break;\r
-               udelay(1);\r
-       }\r
-}\r
-\r
-#ifdef CONFIG_CONSOLE_POLL\r
-/*\r
- * Console polling routines for writing and reading from the uart while\r
- * in an interrupt or debug context.\r
- */\r
-\r
-static int serial_rk_get_poll_char(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned char lsr = serial_in(up, UART_LSR);\r
-\r
-       while (!(lsr & UART_LSR_DR))\r
-               lsr = serial_in(up, UART_LSR);\r
-\r
-       return serial_in(up, UART_RX);\r
-}\r
-\r
-static void serial_rk_put_poll_char(struct uart_port *port,\r
-                        unsigned char c)\r
-{\r
-       unsigned int ier;\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-\r
-       /*\r
-        *      First save the IER then disable the interrupts\r
-        */\r
-       ier = serial_in(up, UART_IER);\r
-       serial_out(up, UART_IER, 0);\r
-\r
-       wait_for_xmitr(up, BOTH_EMPTY);\r
-       /*\r
-        *      Send the character out.\r
-        *      If a LF, also do CR...\r
-        */\r
-       serial_out(up, UART_TX, c);\r
-       if (c == 10) {\r
-               wait_for_xmitr(up, BOTH_EMPTY);\r
-               serial_out(up, UART_TX, 13);\r
-       }\r
-\r
-       /*\r
-        *      Finally, wait for transmitter to become empty\r
-        *      and restore the IER\r
-        */\r
-       wait_for_xmitr(up, BOTH_EMPTY);\r
-       serial_out(up, UART_IER, ier);\r
-}\r
-\r
-#endif /* CONFIG_CONSOLE_POLL */\r
-\r
-static int serial_rk_startup(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned long flags;\r
-       int retval;\r
-\r
-\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-\r
-       /*\r
-        * Allocate the IRQ\r
-        */\r
-       retval = request_irq(up->port.irq, serial_rk_interrupt, up->port.irqflags,\r
-                               up->name, up);\r
-       if (retval)\r
-               return retval;\r
-\r
-       up->mcr = 0;\r
-\r
-       clk_enable(up->clk);  // enable the config uart clock\r
-\r
-       /*\r
-        * Clear the FIFO buffers and disable them.\r
-        * (they will be reenabled in set_termios())\r
-        */\r
-       serial_rk_clear_fifos(up);\r
-\r
-       /*\r
-        * Clear the interrupt registers.\r
-        */\r
-       (void) serial_in(up, UART_LSR);\r
-       (void) serial_in(up, UART_RX);\r
-       (void) serial_in(up, UART_IIR);\r
-       (void) serial_in(up, UART_MSR);\r
-       (void) serial_in(up, UART_USR);\r
-\r
-       /*\r
-        * Now, initialize the UART\r
-        */\r
-       serial_lcr_write(up, UART_LCR_WLEN8 | UART_LCR_EPAR);\r
-\r
-       spin_lock_irqsave(&up->port.lock, flags);\r
-\r
-       /*\r
-        * Most PC uarts need OUT2 raised to enable interrupts.\r
-        */\r
-//     up->port.mctrl |= TIOCM_OUT2;\r
-\r
-       serial_rk_set_mctrl(&up->port, up->port.mctrl);\r
-\r
-       spin_unlock_irqrestore(&up->port.lock, flags);\r
-\r
-       /*\r
-        * Clear the interrupt registers again for luck, and clear the\r
-        * saved flags to avoid getting false values from polling\r
-        * routines or the previous session.\r
-        */\r
-       (void) serial_in(up, UART_LSR);\r
-       (void) serial_in(up, UART_RX);\r
-       (void) serial_in(up, UART_IIR);\r
-       (void) serial_in(up, UART_MSR);\r
-       (void) serial_in(up, UART_USR);\r
-       up->lsr_saved_flags = 0;\r
-#if 0\r
-       up->msr_saved_flags = 0;\r
-#endif\r
-\r
-       if (1 == up->prk29_uart_dma_t->use_dma) {\r
-\r
-               if(up->port.state->xmit.buf != up->prk29_uart_dma_t->tx_buffer){\r
-                       free_page((unsigned long)up->port.state->xmit.buf);\r
-                       up->port.state->xmit.buf = up->prk29_uart_dma_t->tx_buffer;\r
-               }\r
-\r
-#if 1\r
-               serial_rk_start_rx_dma(&up->port);\r
-#else\r
-               up->ier |= UART_IER_RDI;\r
-               up->ier |= UART_IER_RLSI;\r
-               serial_out(up, UART_IER, up->ier);\r
-#endif\r
-               up->port_activity = jiffies;\r
-\r
-       }else{\r
-               up->ier = 0;\r
-               serial_out(up, UART_IER, up->ier);\r
-       }\r
-\r
-       /*\r
-        * Finally, enable interrupts.  Note: Modem status interrupts\r
-        * are set via set_termios(), which will be occurring imminently\r
-        * anyway, so we don't enable them here.\r
-        */\r
-\r
-       return 0;\r
-}\r
-\r
-\r
-static void serial_rk_shutdown(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned long flags;\r
-\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-       /*\r
-        * Disable interrupts from this port\r
-        */\r
-       up->ier = 0;\r
-       serial_out(up, UART_IER, 0);\r
-\r
-       spin_lock_irqsave(&up->port.lock, flags);\r
-//     up->port.mctrl &= ~TIOCM_OUT2;\r
-       serial_rk_set_mctrl(&up->port, up->port.mctrl);\r
-       spin_unlock_irqrestore(&up->port.lock, flags);\r
-\r
-       /*\r
-        * Disable break condition and FIFOs\r
-        */\r
-       serial_lcr_write(up, serial_in(up, UART_LCR) & ~UART_LCR_SBC);\r
-       serial_rk_clear_fifos(up);\r
-\r
-       /*\r
-        * Read data port to reset things, and then free the irq\r
-        */\r
-       (void) serial_in(up, UART_RX);\r
-\r
-       free_irq(up->port.irq, up);\r
-}\r
-\r
-static void\r
-serial_rk_set_termios(struct uart_port *port, struct ktermios *termios,\r
-                     struct ktermios *old)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-       unsigned char cval, fcr = 0;\r
-       unsigned long flags;\r
-       unsigned int baud, quot;\r
-       int timeout = 1000000;\r
-       dev_dbg(port->dev, "+%s\n", __func__);\r
-\r
-       switch (termios->c_cflag & CSIZE) {\r
-       case CS5:\r
-               cval = UART_LCR_WLEN5;\r
-               break;\r
-       case CS6:\r
-               cval = UART_LCR_WLEN6;\r
-               break;\r
-       case CS7:\r
-               cval = UART_LCR_WLEN7;\r
-               break;\r
-       case CS8:\r
-       default:\r
-               cval = UART_LCR_WLEN8;\r
-               break;\r
-       }\r
-\r
-       if (termios->c_cflag & CSTOPB){\r
-               cval |= UART_LCR_STOP;\r
-       }\r
-       if (termios->c_cflag & PARENB){\r
-               cval |= UART_LCR_PARITY;\r
-       }\r
-       if (!(termios->c_cflag & PARODD)){\r
-               cval |= UART_LCR_EPAR;\r
-       }\r
-#ifdef CMSPAR\r
-       if (termios->c_cflag & CMSPAR)\r
-               cval |= UART_LCR_SPAR;\r
-#endif\r
-\r
-\r
-       /*\r
-        * Ask the core to calculate the divisor for us.\r
-        */\r
-       baud = uart_get_baud_rate(port, termios, old,\r
-                                 port->uartclk / 16 / 0xffff,\r
-                                 port->uartclk / 16);\r
-\r
-       quot = uart_get_divisor(port, baud);\r
-\r
-       dev_info(up->port.dev, "baud:%d\n", baud);\r
-//     dev_info(up->port.dev, "quot:%d\n", quot);\r
-\r
-       /*\r
-        * To wait long enough to avoid writting lcr when the uart is busy\r
-        * because of data communication, so that we can set lcr and baud rate\r
-        * successfully. added by hhb@rock-chips.com\r
-        */\r
-\r
-       while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
-               if(--timeout == 0){\r
-                       if(port->line != DBG_PORT){\r
-                               serial_out(up, UART_SRR, UART_RESET);\r
-                       }\r
-                       dbg("rk_serial_set_termios uart.%d timeout,irq=%d,ret=0x%x  AND uart is reseted\n",\r
-                                       port->line, port->irq, serial_in(up, UART_USR));\r
-                       break;\r
-               }\r
-               cpu_relax();\r
-       }\r
-\r
-\r
-       printk("serial.%d timeout:%d\n", up->port.line,timeout);\r
-\r
-\r
-       if (baud < 2400){\r
-               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;\r
-       }\r
-       else{\r
-               //added by hhb@rock-chips.com\r
-               if(up->prk29_uart_dma_t->use_timer == 1){\r
-                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_01;\r
-               }\r
-               else{\r
-                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | UART_FCR_T_TRIG_01;\r
-               }\r
-       }\r
-\r
-       /*\r
-        * MCR-based auto flow control.  When AFE is enabled, RTS will be\r
-        * deasserted when the receive FIFO contains more characters than\r
-        * the trigger, or the MCR RTS bit is cleared.  In the case where\r
-        * the remote UART is not using CTS auto flow control, we must\r
-        * have sufficient FIFO entries for the latency of the remote\r
-        * UART to respond.  IOW, at least 32 bytes of FIFO.\r
-        */\r
-       up->mcr &= ~UART_MCR_AFE;\r
-       if (termios->c_cflag & CRTSCTS){\r
-               up->mcr |= UART_MCR_AFE;\r
-       }\r
-\r
-       /*\r
-        * Ok, we're now changing the port state.  Do it with\r
-        * interrupts disabled.\r
-        */\r
-       spin_lock_irqsave(&up->port.lock, flags);\r
-\r
-       /*\r
-        * Update the per-port timeout.\r
-        */\r
-       uart_update_timeout(port, termios->c_cflag, baud);\r
-\r
-       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;\r
-       if (termios->c_iflag & INPCK)\r
-               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;\r
-       if (termios->c_iflag & (BRKINT | PARMRK))\r
-               up->port.read_status_mask |= UART_LSR_BI;\r
-\r
-       /*\r
-        * Characteres to ignore\r
-        */\r
-       up->port.ignore_status_mask = 0;\r
-       if (termios->c_iflag & IGNPAR)\r
-               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;\r
-       if (termios->c_iflag & IGNBRK) {\r
-               up->port.ignore_status_mask |= UART_LSR_BI;\r
-               /*\r
-                * If we're ignoring parity and break indicators,\r
-                * ignore overruns too (for real raw support).\r
-                */\r
-               if (termios->c_iflag & IGNPAR)\r
-                       up->port.ignore_status_mask |= UART_LSR_OE;\r
-       }\r
-\r
-       /*\r
-        * ignore all characters if CREAD is not set\r
-        */\r
-       if ((termios->c_cflag & CREAD) == 0)\r
-               up->port.ignore_status_mask |= UART_LSR_DR;\r
-\r
-       /*\r
-        * CTS flow control flag and modem status interrupts\r
-        */\r
-       up->ier &= ~UART_IER_MSI;\r
-#if 0\r
-       if (UART_ENABLE_MS(&up->port, termios->c_cflag))\r
-               up->ier |= UART_IER_MSI;\r
-#endif\r
-\r
-       up->lcr = cval;                         /* Save LCR */\r
-       /* set DLAB */\r
-       if(serial_lcr_write(up, cval | UART_LCR_DLAB)){\r
-               dbg("serial.%d set DLAB fail\n", up->port.line);\r
-               serial_out(up, UART_SRR, UART_RESET);\r
-               goto fail;\r
-       }\r
-\r
-       /* set uart baud rate */\r
-       if(serial_dl_write(up, quot)){\r
-               dbg("serial.%d set dll fail\n", up->port.line);\r
-               serial_out(up, UART_SRR, UART_RESET);\r
-               goto fail;\r
-       }\r
-\r
-       /* reset DLAB */\r
-       if(serial_lcr_write(up, cval)){\r
-               dbg("serial.%d reset DLAB fail\n", up->port.line);\r
-               serial_out(up, UART_SRR, UART_RESET);\r
-               goto fail;\r
-       }\r
-       else{\r
-               serial_rk_set_mctrl(&up->port, up->port.mctrl);\r
-               serial_out(up, UART_FCR, fcr);          /* set fcr */\r
-               up->fcr = fcr;\r
-               /* enable the uart interrupt last */\r
-               up->ier |= UART_IER_RDI;\r
-               up->ier |= UART_IER_RLSI;\r
-               serial_out(up, UART_IER, up->ier);\r
-       }\r
-\r
-       spin_unlock_irqrestore(&up->port.lock, flags);\r
-\r
-       /* Don't rewrite B0 */\r
-       if (tty_termios_baud_rate(termios))\r
-               tty_termios_encode_baud_rate(termios, baud, baud);\r
-       dev_dbg(port->dev, "-%s baud %d\n", __func__, baud);\r
-\r
-       return;\r
-\r
-fail:\r
-       spin_unlock_irqrestore(&up->port.lock, flags);\r
-\r
-}\r
-\r
-#if 0\r
-static void\r
-serial_rk_set_ldisc(struct uart_port *port, int new)\r
-{\r
-       if (new == N_PPS) {\r
-               port->flags |= UPF_HARDPPS_CD;\r
-               serial_rk_enable_ms(port);\r
-       } else\r
-               port->flags &= ~UPF_HARDPPS_CD;\r
-}\r
-#endif\r
-\r
-static void\r
-serial_rk_pm(struct uart_port *port, unsigned int state,\r
-             unsigned int oldstate)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-\r
-       dev_dbg(port->dev, "%s: %s\n", __func__, state ? "disable" : "enable");\r
-       if (state)\r
-               clk_disable(up->clk);\r
-       else\r
-               clk_enable(up->clk);\r
-}\r
-\r
-static void serial_rk_release_port(struct uart_port *port)\r
-{\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-}\r
-\r
-static int serial_rk_request_port(struct uart_port *port)\r
-{\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-       return 0;\r
-}\r
-\r
-static void serial_rk_config_port(struct uart_port *port, int flags)\r
-{\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-       port->type = PORT_RK;\r
-}\r
-\r
-static int\r
-serial_rk_verify_port(struct uart_port *port, struct serial_struct *ser)\r
-{\r
-       /* we don't want the core code to modify any port params */\r
-       dev_dbg(port->dev, "%s\n", __func__);\r
-       return -EINVAL;\r
-}\r
-\r
-static const char *\r
-serial_rk_type(struct uart_port *port)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-\r
-       dev_dbg(port->dev, "%s: %s\n", __func__, up->name);\r
-       return up->name;\r
-}\r
-\r
-static struct uart_ops serial_rk_pops = {\r
-       .tx_empty       = serial_rk_tx_empty,\r
-       .set_mctrl      = serial_rk_set_mctrl,\r
-       .get_mctrl      = serial_rk_get_mctrl,\r
-       .stop_tx        = serial_rk_stop_tx,\r
-       .start_tx       = serial_rk_start_tx,\r
-       .stop_rx        = serial_rk_stop_rx,\r
-       .enable_ms      = serial_rk_enable_ms,\r
-       .break_ctl      = serial_rk_break_ctl,\r
-       .startup        = serial_rk_startup,\r
-       .shutdown       = serial_rk_shutdown,\r
-       .set_termios    = serial_rk_set_termios,\r
-#if 0\r
-       .set_ldisc      = serial_rk_set_ldisc,\r
-#endif\r
-       .pm             = serial_rk_pm,\r
-       .type           = serial_rk_type,\r
-       .release_port   = serial_rk_release_port,\r
-       .request_port   = serial_rk_request_port,\r
-       .config_port    = serial_rk_config_port,\r
-       .verify_port    = serial_rk_verify_port,\r
-#ifdef CONFIG_CONSOLE_POLL\r
-       .poll_get_char = serial_rk_get_poll_char,\r
-       .poll_put_char = serial_rk_put_poll_char,\r
-#endif\r
-};\r
-\r
-#ifdef CONFIG_SERIAL_RK_CONSOLE\r
-\r
-static struct uart_rk_port *serial_rk_console_ports[UART_NR];\r
-\r
-static void serial_rk_console_putchar(struct uart_port *port, int ch)\r
-{\r
-       struct uart_rk_port *up =\r
-               container_of(port, struct uart_rk_port, port);\r
-\r
-       wait_for_xmitr(up, UART_LSR_THRE);\r
-       serial_out(up, UART_TX, ch);\r
-}\r
-\r
-/*\r
- *     Print a string to the serial port trying not to disturb\r
- *     any possible real use of the port...\r
- *\r
- *     The console_lock must be held when we get here.\r
- */\r
-static void\r
-serial_rk_console_write(struct console *co, const char *s, unsigned int count)\r
-{\r
-       struct uart_rk_port *up = serial_rk_console_ports[co->index];\r
-       unsigned long flags;\r
-       unsigned int ier;\r
-       int locked = 1;\r
-\r
-       touch_nmi_watchdog();\r
-\r
-       local_irq_save(flags);\r
-       if (up->port.sysrq) {\r
-               /* serial_rk_handle_port() already took the lock */\r
-               locked = 0;\r
-       } else if (oops_in_progress) {\r
-               locked = spin_trylock(&up->port.lock);\r
-       } else\r
-               spin_lock(&up->port.lock);\r
-\r
-       /*\r
-        *      First save the IER then disable the interrupts\r
-        */\r
-       ier = serial_in(up, UART_IER);\r
-\r
-       serial_out(up, UART_IER, 0);\r
-\r
-       uart_console_write(&up->port, s, count, serial_rk_console_putchar);\r
-\r
-       /*\r
-        *      Finally, wait for transmitter to become empty\r
-        *      and restore the IER\r
-        */\r
-       wait_for_xmitr(up, BOTH_EMPTY);\r
-       serial_out(up, UART_IER, ier);\r
-\r
-#if 0\r
-       /*\r
-        *      The receive handling will happen properly because the\r
-        *      receive ready bit will still be set; it is not cleared\r
-        *      on read.  However, modem control will not, we must\r
-        *      call it if we have saved something in the saved flags\r
-        *      while processing with interrupts off.\r
-        */\r
-       if (up->msr_saved_flags)\r
-               check_modem_status(up);\r
-#endif\r
-\r
-       if (locked)\r
-               spin_unlock(&up->port.lock);\r
-       local_irq_restore(flags);\r
-}\r
-\r
-static int __init serial_rk_console_setup(struct console *co, char *options)\r
-{\r
-       struct uart_rk_port *up;\r
-       int baud = 115200;\r
-       int bits = 8;\r
-       int parity = 'n';\r
-       int flow = 'n';\r
-\r
-       if (unlikely(co->index >= UART_NR || co->index < 0))\r
-               return -ENODEV;\r
-\r
-       if (serial_rk_console_ports[co->index] == NULL)\r
-               return -ENODEV;\r
-       up = serial_rk_console_ports[co->index];\r
-\r
-       if (options)\r
-               uart_parse_options(options, &baud, &parity, &bits, &flow);\r
-\r
-       return uart_set_options(&up->port, co, baud, parity, bits, flow);\r
-}\r
-\r
-static struct console serial_rk_console = {\r
-       .name           = "ttyS",\r
-       .write          = serial_rk_console_write,\r
-       .device         = uart_console_device,\r
-       .setup          = serial_rk_console_setup,\r
-       .flags          = CON_PRINTBUFFER | CON_ANYTIME,\r
-       .index          = -1,\r
-       .data           = &serial_rk_reg,\r
-};\r
-\r
-static void serial_rk_add_console_port(struct uart_rk_port *up)\r
-{\r
-       serial_rk_console_ports[up->pdev->id] = up;\r
-}\r
-\r
-#define SERIAL_CONSOLE &serial_rk_console\r
-#else\r
-#define SERIAL_CONSOLE NULL\r
-\r
-static inline void serial_rk_add_console_port(struct uart_rk_port *up)\r
-{}\r
-\r
-#endif\r
-\r
-static struct uart_driver serial_rk_reg = {\r
-       .owner                  = THIS_MODULE,\r
-       .driver_name            = "rk29_serial",\r
-       .dev_name               = "ttyS",\r
-       .major                  = TTY_MAJOR,\r
-       .minor                  = 64,\r
-       .cons                   = SERIAL_CONSOLE,\r
-       .nr                     = UART_NR,\r
-};\r
-\r
-static int __devinit serial_rk_probe(struct platform_device *pdev)\r
-{\r
-       struct uart_rk_port     *up;\r
-       struct resource         *mem;\r
-       int irq;\r
-       int ret = -ENOSPC;\r
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-       if (!mem) {\r
-               dev_err(&pdev->dev, "no mem resource?\n");\r
-               return -ENODEV;\r
-       }\r
-\r
-       irq = platform_get_irq(pdev, 0);\r
-       if (irq < 0) {\r
-               dev_err(&pdev->dev, "no irq resource?\n");\r
-               return irq;\r
-       }\r
-\r
-       if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,\r
-                               pdev->dev.driver->name)) {\r
-               dev_err(&pdev->dev, "memory region already claimed\n");\r
-               return -EBUSY;\r
-       }\r
-\r
-       up = kzalloc(sizeof(*up), GFP_KERNEL);\r
-       if (up == NULL) {\r
-               ret = -ENOMEM;\r
-               goto do_release_region;\r
-       }\r
-\r
-       sprintf(up->name, "rk29_serial.%d", pdev->id);\r
-       up->pdev = pdev;\r
-       up->clk = clk_get(&pdev->dev, "uart");\r
-       if (unlikely(IS_ERR(up->clk))) {\r
-               ret = PTR_ERR(up->clk);\r
-               goto do_free;\r
-       }\r
-       up->tx_loadsz = 30;\r
-       up->prk29_uart_dma_t = &rk29_uart_ports_dma_t[pdev->id];\r
-       up->port.dev = &pdev->dev;\r
-       up->port.type = PORT_RK;\r
-       up->port.irq = irq;\r
-       up->port.iotype = UPIO_DWAPB;\r
-\r
-       up->port.regshift = 2;\r
-       up->port.fifosize = 32;\r
-       up->port.ops = &serial_rk_pops;\r
-       up->port.line = pdev->id;\r
-       up->port.iobase = mem->start;\r
-       up->port.membase = ioremap_nocache(mem->start, mem->end - mem->start + 1);\r
-       if (!up->port.membase) {\r
-               ret = -ENOMEM;\r
-               goto do_put_clk;\r
-       }\r
-       up->port.mapbase = mem->start;\r
-       up->port.irqflags = IRQF_DISABLED;\r
-       up->port.uartclk = clk_get_rate(up->clk);\r
-\r
-       /* set dma config */\r
-       if(1 == up->prk29_uart_dma_t->use_dma) {\r
-               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);\r
-\r
-               //timer\r
-               up->prk29_uart_dma_t->use_timer = USE_TIMER;\r
-               up->prk29_uart_dma_t->rx_timer.function = serial_rk_rx_timeout;\r
-               up->prk29_uart_dma_t->rx_timer.data = (unsigned long)up;\r
-               up->prk29_uart_dma_t->rx_timeout = 7;\r
-               up->prk29_uart_dma_t->rx_timer.expires = jiffies + msecs_to_jiffies(up->prk29_uart_dma_t->rx_timeout);\r
-               init_timer(&up->prk29_uart_dma_t->rx_timer);\r
-               //tx buffer\r
-               up->prk29_uart_dma_t->tx_buffer_size = UART_XMIT_SIZE;\r
-               up->prk29_uart_dma_t->tx_buffer = dmam_alloc_coherent(up->port.dev, up->prk29_uart_dma_t->tx_buffer_size,\r
-                               &up->prk29_uart_dma_t->tx_phy_addr, DMA_MEMORY_MAP);\r
-               if(!up->prk29_uart_dma_t->tx_buffer){\r
-                       dev_info(up->port.dev, "dmam_alloc_coherent dma_tx_buffer fail\n");\r
-               }\r
-               else{\r
-                       dev_info(up->port.dev, "dma_tx_buffer 0x%08x\n", (unsigned) up->prk29_uart_dma_t->tx_buffer);\r
-                       dev_info(up->port.dev, "dma_tx_phy 0x%08x\n", (unsigned) up->prk29_uart_dma_t->tx_phy_addr);\r
-               }\r
-               //rx buffer\r
-               up->prk29_uart_dma_t->rx_buffer_size = UART_XMIT_SIZE*32;\r
-               up->prk29_uart_dma_t->rx_buffer = dmam_alloc_coherent(up->port.dev, up->prk29_uart_dma_t->rx_buffer_size,\r
-                               &up->prk29_uart_dma_t->rx_phy_addr, DMA_MEMORY_MAP);\r
-               up->prk29_uart_dma_t->rb_pre_pos = 0;\r
-               if(!up->prk29_uart_dma_t->rx_buffer){\r
-                       dev_info(up->port.dev, "dmam_alloc_coherent dma_rx_buffer fail\n");\r
-               }\r
-               else {\r
-                       dev_info(up->port.dev, "dma_rx_buffer 0x%08x\n", (unsigned) up->prk29_uart_dma_t->rx_buffer);\r
-                       dev_info(up->port.dev, "up 0x%08x\n", (unsigned)up->prk29_uart_dma_t);\r
-               }\r
-\r
-               // work queue\r
-               INIT_WORK(&up->uart_work, serial_rk_report_revdata_workfunc);\r
-               INIT_WORK(&up->uart_work_rx, serial_rk_start_dma_rx);\r
-               up->uart_wq = create_singlethread_workqueue("uart_workqueue");\r
-               up->prk29_uart_dma_t->rx_dma_start = 0;\r
-               spin_lock_init(&(up->prk29_uart_dma_t->tx_lock));\r
-               spin_lock_init(&(up->prk29_uart_dma_t->rx_lock));\r
-               serial_rk_init_dma_rx(&up->port);\r
-               serial_rk_init_dma_tx(&up->port);\r
-               up->ier |= THRE_MODE;                   // enable THRE interrupt mode\r
-               serial_out(up, UART_IER, up->ier);\r
-       }\r
-\r
-       serial_rk_add_console_port(up);\r
-       ret = uart_add_one_port(&serial_rk_reg, &up->port);\r
-       if (ret != 0)\r
-               goto do_iounmap;\r
-\r
-       platform_set_drvdata(pdev, up);\r
-       dev_info(&pdev->dev, "membase 0x%08x\n", (unsigned) up->port.membase);\r
-\r
-       return 0;\r
-\r
-do_iounmap:\r
-       iounmap(up->port.membase);\r
-       up->port.membase = NULL;\r
-do_put_clk:\r
-       clk_put(up->clk);\r
-do_free:\r
-       kfree(up);\r
-do_release_region:\r
-       release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
-       return ret;\r
-}\r
-\r
-static int __devexit serial_rk_remove(struct platform_device *pdev)\r
-{\r
-       struct uart_rk_port *up = platform_get_drvdata(pdev);\r
-\r
-       platform_set_drvdata(pdev, NULL);\r
-       if (up) {\r
-               struct resource *mem;\r
-               destroy_workqueue(up->uart_wq);\r
-               uart_remove_one_port(&serial_rk_reg, &up->port);\r
-               mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
-               iounmap(up->port.membase);\r
-               up->port.membase = NULL;\r
-               clk_put(up->clk);\r
-               kfree(up);\r
-               release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-static int serial_rk_suspend(struct platform_device *dev, pm_message_t state)\r
-{\r
-       struct uart_rk_port *up = platform_get_drvdata(dev);\r
-\r
-       if (up && up->port.line != DBG_PORT && POWER_MANEGEMENT){\r
-               uart_suspend_port(&serial_rk_reg, &up->port);\r
-       }\r
-       if(up->port.line == DBG_PORT && POWER_MANEGEMENT){\r
-               serial_rk_pm(&up->port, 1, 0);\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-static int serial_rk_resume(struct platform_device *dev)\r
-{\r
-       struct uart_rk_port *up = platform_get_drvdata(dev);\r
-\r
-       if (up && up->port.line != DBG_PORT && POWER_MANEGEMENT){\r
-               uart_resume_port(&serial_rk_reg, &up->port);\r
-       }\r
-       if(up->port.line == DBG_PORT && POWER_MANEGEMENT){\r
-               serial_rk_pm(&up->port, 0, 1);\r
-       }\r
-       return 0;\r
-}\r
-\r
-static struct platform_driver serial_rk_driver = {\r
-       .probe          = serial_rk_probe,\r
-       .remove         = __devexit_p(serial_rk_remove),\r
-       .suspend        = serial_rk_suspend,\r
-       .resume         = serial_rk_resume,\r
-       .driver         = {\r
-#if defined(CONFIG_SERIAL_RK29)\r
-               .name   = "rk29_serial",\r
-#elif defined(CONFIG_SERIAL_RK2818)\r
-               .name   = "rk2818_serial",\r
-#else\r
-               .name   = "rk_serial",\r
-#endif\r
-               .owner  = THIS_MODULE,\r
-       },\r
-};\r
-\r
-static int __init serial_rk_init(void)\r
-{\r
-       int ret;\r
-\r
-       ret = uart_register_driver(&serial_rk_reg);\r
-       if (ret)\r
-               return ret;\r
-\r
-       ret = platform_driver_register(&serial_rk_driver);\r
-       if (ret != 0)\r
-               uart_unregister_driver(&serial_rk_reg);\r
-\r
-       return ret;\r
-}\r
-\r
-static void __exit serial_rk_exit(void)\r
-{\r
-       platform_driver_unregister(&serial_rk_driver);\r
-       uart_unregister_driver(&serial_rk_reg);\r
-}\r
-\r
-module_init(serial_rk_init);\r
-module_exit(serial_rk_exit);\r
-\r
-MODULE_LICENSE("GPL");\r
-MODULE_DESCRIPTION("RK UART driver");\r
-\r
diff --git a/drivers/serial/sc8800.c b/drivers/serial/sc8800.c
deleted file mode 100755 (executable)
index 86f6fdf..0000000
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- *
- *  Copyright (C) 2010 liuyixing <lyx@rock-chips.com>
- *
- *
- * Example platform data:
-
- static struct plat_sc8800 sc8800_plat_data = {
-        .slav_rts_pin = RK29_PIN4_PD0,
-        .slav_rdy_pin = RK29_PIN4_PD0,
-        .master_rts_pin = RK29_PIN4_PD0,
-        .master_rdy_pin = RK29_PIN4_PD0,
-        //.poll_time = 100,
- };
-
- static struct spi_board_info spi_board_info[] = {
-        {
-        .modalias      = "sc8800",
-        .platform_data = &sc8800_plat_data,
-        .max_speed_hz  = 12*1000*1000,
-        .chip_select   = 0,
-        },
- };
-
- * The initial minor number is 209 in the low-density serial port:
- * mknod /dev/ttySPI0 c 204 209
- */
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include <linux/gpio.h>
-
-#include "sc8800.h"
-
-struct sc8800_port {
-       struct uart_port port;
-       struct spi_device *spi;
-
-       int cts;                /* last CTS received for flow ctrl */
-       int tx_empty;           /* last TX empty bit */
-
-       spinlock_t conf_lock;   /* shared data */
-       int conf;               /* configuration for the SC88000
-                                * (bits 0-7, bits 8-11 are irqs) */
-
-       int rx_enabled;         /* if we should rx chars */
-
-       int irq;                /* irq assigned to the sc8800 */
-
-       int minor;              /* minor number */
-       int loopback;           /* 1 if we are in loopback mode */
-
-       /* for handling irqs: need workqueue since we do spi_sync */
-       struct workqueue_struct *workqueue;
-       struct work_struct work;
-       /* set to 1 to make the workhandler exit as soon as possible */
-       int  force_end_work;
-       /* need to know we are suspending to avoid deadlock on workqueue */
-       int suspending;
-
-       /* hook for suspending SC8800 via dedicated pin */
-       void (*sc8800_hw_suspend) (int suspend);
-
-       /* poll time (in ms) for ctrl lines */
-       int poll_time;
-       /* and its timer */
-       struct timer_list       timer;
-
-       /*signal define, always gpio*/
-       int slav_rts;
-       int slav_rdy;
-       int master_rts;
-       int master_rdy;
-};
-
-#define SC8800_MAJOR 204
-#define SC8800_MINOR 209
-#define MAX_SC8800 1
-
-#define SPI_MAX_PACKET (8192-128)
-#define FREAM_SIZE 64
-#define SPI_DMA_SIZE PAGE_SIZE
-
-void * g_dma_buffer = NULL;
-dma_addr_t g_dma_addr;
-
-#if 1
-#define sc8800_dbg(x...) printk(x)
-#else
-#define sc8800_dbg(x...)
-#endif
-
-static struct sc8800_port *sc8800s[MAX_SC8800]; /* the chips */
-static DEFINE_MUTEX(sc8800s_lock);                /* race on probe */
-
-static int sc8800_get_slave_rts_status(struct sc8800_port *s)
-{
-       return gpio_get_value(s->slav_rts);
-}
-
-static int sc8800_get_slave_rdy_status(struct sc8800_port *s)
-{
-       return gpio_get_value(s->slav_rdy);
-}
-
-static void sc8800_set_master_rts_status(struct sc8800_port *s, int value)
-{
-       gpio_set_value(s->master_rts, value);
-}
-
-static void sc8800_set_master_rdy_status(struct sc8800_port *s, int value)
-{
-       gpio_set_value(s->master_rdy, value);
-}
-
-static int sc8800_send_head_data(struct sc8800_port *s, u32 data_len)
-{
-       char head[64] = {0};
-       struct spi_message message;
-       int status;
-       struct spi_transfer tran;
-
-       head[0] = 0x7f;
-       head[1] = 0x7e;
-       head[2] = 0x55;
-       head[3] = 0xaa;
-       head[4] = data_len & 0xff;
-       head[5] = (data_len>>8) & 0xff;
-       head[6] = (data_len>>16) & 0xff;
-       head[7] = (data_len>>24) & 0xff;
-       
-       tran.tx_buf = (void *)(head);
-       tran.len = FREAM_SIZE;
-       
-       spi_message_init(&message);
-       spi_message_add_tail(&tran, &message);
-       status = spi_sync(s->spi, &message);
-       if (status) {
-               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
-               return -EIO;
-       }
-       
-       return 0;
-}
-static int sc8800_recv_and_parse_head_data(struct sc8800_port *s, u32 *len)
-{
-       struct spi_message message;
-       int status;
-       struct spi_transfer tran;
-       char buf[64] = {0};
-       u32 data_len = 0;
-               
-       tran.rx_buf = (void *)buf;
-       tran.len = FREAM_SIZE;
-       
-       spi_message_init(&message);
-       spi_message_add_tail(&tran, &message);
-       status = spi_sync(s->spi, &message);
-       if (status) {
-               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
-               return -EIO;
-       }
-
-       if ((buf[0]!=0x7f) || (buf[1]!=0x7e) || (buf[2]!=0x55) || (buf[3]!=0xaa)) {
-               dev_warn(&s->spi->dev, "line %d, error head data", __LINE__);
-               return -EIO;
-       }
-       
-       data_len = buf[5] + (buf[6]<<8) + (buf[7]<<16) + (buf[8]<<24);
-
-       *len = data_len;
-       
-       sc8800_dbg("line %d, %d data need to read\n", __LINE__, *len);
-       
-       return 0;
-}
-
-static int sc8800_send_data(struct sc8800_port *s, char *buf, int len)
-{
-#if 1
-       int status;
-       struct spi_message message;
-       struct spi_transfer tran;
-       
-       tran.tx_buf = (void *)buf;
-       tran.len = len;
-       
-       spi_message_init(&message);
-       spi_message_add_tail(&tran, &message);
-       status = spi_sync(s->spi, &message);
-       if (status) {
-               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
-               return -EIO;
-       }
-#else
-       int status;
-       struct spi_message message;
-       struct spi_transfer tran;
-
-       spi_message_init(&message);
-       
-       if (!g_dma_buffer) {
-               g_dma_buffer = dma_alloc_coherent(NULL, SPI_DMA_SIZE, &g_dma_addr, GFP_KERNEL | GFP_DMA);
-               if (!g_dma_buffer) {
-                       dev_err(&s->spi->dev, "alloc dma memory fail\n");
-               }
-       }
-
-       if (!g_dma_buffer) {    //nomal
-               sc8800_dbg("send data nomal");
-               tran.tx_buf = (void *)buf;
-               tran.len = len;
-       }
-       else {  //dma   
-               //message.is_dma_mapped = 1;
-               //memcpy(g_dma_buffer, buf, );
-       }
-
-       spi_message_add_tail(&tran, &message);
-       status = spi_sync(s->spi, &message);
-       if (status) {
-               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
-               return -EIO;
-       }
-#endif
-
-       return 0;
-}
-
-static int sc8800_recv_data(struct sc8800_port *s, char *buf, int len)
-{
-       struct spi_message message;
-       int status;
-       struct spi_transfer tran;
-       
-       tran.rx_buf = (void *)buf;
-       tran.len = len;
-       
-       spi_message_init(&message);
-       spi_message_add_tail(&tran, &message);
-       status = spi_sync(s->spi, &message);
-       if (status) {
-               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
-               return -EIO;
-       }
-       
-       return 0;
-}
-
-static void sc8800_work(struct work_struct *w);
-
-static void sc8800_dowork(struct sc8800_port *s)
-{
-       if (!s->force_end_work && !work_pending(&s->work) &&
-           !freezing(current) && !s->suspending)
-               queue_work(s->workqueue, &s->work);
-}
-
-static void sc8800_timeout(unsigned long data)
-{
-       struct sc8800_port *s = (struct sc8800_port *)data;
-
-       if (s->port.state) {
-               sc8800_dowork(s);
-               mod_timer(&s->timer, jiffies + s->poll_time);
-       }
-}
-
-static void sc8800_work(struct work_struct *w)
-{
-       struct sc8800_port *s = container_of(w, struct sc8800_port, work);
-       struct circ_buf *xmit = &s->port.state->xmit;
-       u32 len,i;
-       char *buf = NULL;
-       unsigned char ch;
-       
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-
-       if (sc8800_get_slave_rts_status(s) == GPIO_HIGH) {      //do wirte, master--->slave
-               if (sc8800_get_slave_rdy_status(s) == GPIO_HIGH) {      /*1.check slave rdy, must be high*/
-                       if (!(uart_circ_empty(xmit))) {
-                               len = uart_circ_chars_pending(xmit);
-                               len = (len > SPI_MAX_PACKET) ? SPI_MAX_PACKET : len;
-                               sc8800_dbg("send data length = %d\n", len);
-                               
-                               sc8800_set_master_rts_status(s, GPIO_LOW);      /*2.set master rts low*/
-                               sc8800_send_head_data(s,len);   /*3.send 64byte head data*/
-                               while (sc8800_get_slave_rdy_status(s)) {        /*4.check slav rdy, wait for low */
-                                       msleep(1);
-                               }
-                               
-                               /*5.long data transmit*/
-                               sc8800_send_data(s, xmit->buf+xmit->tail, len);
-                               
-                               while(sc8800_get_slave_rdy_status(s)==GPIO_LOW) {       /*6.wait for slave rdy high*/
-                                       msleep(1);
-                               }
-
-                               sc8800_set_master_rts_status(s, GPIO_HIGH);     /*end transmit, set master rts high*/
-                               xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);
-                               s->port.icount.tx += len;
-                       }
-               }
-               else {  //slave not ready, do it next time
-                       queue_work(s->workqueue, &s->work);
-               }                       
-       }
-       else {  //do read, slave--->master
-               sc8800_set_master_rdy_status(s, GPIO_LOW);
-               sc8800_recv_and_parse_head_data(s, &len);
-
-               buf = (char *)kzalloc(len, GFP_KERNEL);
-               if (!buf) {
-                       dev_err(&s->spi->dev, "line %d, err while malloc mem\n", __LINE__);
-                       sc8800_set_master_rdy_status(s, GPIO_HIGH);
-                       return ;
-               }
-               memset(buf, 0, len);
-               sc8800_recv_data(s, buf, len);
-               
-               while (sc8800_get_slave_rts_status(s) == GPIO_LOW) {
-                       msleep(1);
-               }
-               sc8800_set_master_rdy_status(s, GPIO_HIGH);
-
-               for (i=0; i<len; i++) {
-                       ch = buf[i];            
-                       uart_insert_char(&s->port, 0, 0, ch, TTY_NORMAL);
-               }
-               tty_flip_buffer_push(s->port.state->port.tty);
-       }
-}
-
-static irqreturn_t sc8800_irq(int irqno, void *dev_id)
-{
-       struct sc8800_port *s = dev_id;
-
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-
-       sc8800_dowork(s);
-       return IRQ_HANDLED;
-}
-
-static void sc8800_enable_ms(struct uart_port *port)
-{
-       struct sc8800_port *s = container_of(port,
-                                             struct sc8800_port,
-                                             port);
-
-       if (s->poll_time > 0)
-               mod_timer(&s->timer, jiffies);
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-}
-
-static void sc8800_start_tx(struct uart_port *port)
-{
-       struct sc8800_port *s = container_of(port,
-                                             struct sc8800_port,
-                                             port);
-
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-       
-       sc8800_dowork(s);
-}
-
-static void sc8800_stop_rx(struct uart_port *port)
-{
-       struct sc8800_port *s = container_of(port,
-                                             struct sc8800_port,
-                                             port);
-
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-
-       s->rx_enabled = 0;
-
-       sc8800_dowork(s);
-}
-
-static void sc8800_shutdown(struct uart_port *port)
-{
-       struct sc8800_port *s = container_of(port,
-                                             struct sc8800_port,
-                                             port);
-
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-
-       if (s->suspending)
-               return;
-
-       s->force_end_work = 1;
-
-       if (s->poll_time > 0)
-               del_timer_sync(&s->timer);
-
-       if (s->workqueue) {
-               flush_workqueue(s->workqueue);
-               destroy_workqueue(s->workqueue);
-               s->workqueue = NULL;
-       }
-       if (s->irq)
-               free_irq(s->irq, s);
-
-       gpio_free(s->master_rdy);
-       gpio_free(s->master_rts);
-       gpio_free(s->slav_rdy);
-       gpio_free(s->slav_rts);
-
-       /* set shutdown mode to save power */
-       if (s->sc8800_hw_suspend)
-               s->sc8800_hw_suspend(1);
-}
-
-static int sc8800_startup(struct uart_port *port)
-{
-       struct sc8800_port *s = container_of(port,
-                                             struct sc8800_port,
-                                             port);
-       int ret;
-       char b[12];
-
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-
-       s->rx_enabled = 1;
-
-       if (s->suspending)
-               return 0;
-       
-       s->force_end_work = 0;
-       
-       sprintf(b, "sc8800-%d", s->minor);
-       s->workqueue = create_freezeable_workqueue(b);
-       if (!s->workqueue) {
-               dev_warn(&s->spi->dev, "cannot create workqueue\n");
-               return -EBUSY;
-       }
-       INIT_WORK(&s->work, sc8800_work);
-
-       ret = gpio_request(s->slav_rts, "slav rts");
-       if (ret) {
-               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
-               ret = -EBUSY;
-               goto gpio_err1;
-       }
-       ret = gpio_request(s->slav_rdy, "slav rdy");
-       if (ret) {
-               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
-               ret = -EBUSY;
-               goto gpio_err2;
-       }
-       ret = gpio_request(s->master_rts, "master rts");
-       if (ret) {
-               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
-               ret = -EBUSY;
-               goto gpio_err3;
-       }
-       ret = gpio_request(s->master_rdy, "master rdy");
-       if (ret) {
-               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
-               ret = -EBUSY;
-               goto gpio_err4;
-       }
-
-       gpio_direction_input(s->slav_rts);
-       gpio_pull_updown(s->slav_rts, GPIOPullUp);
-       gpio_direction_input(s->slav_rdy);
-       gpio_pull_updown(s->slav_rdy, GPIOPullUp);
-       gpio_direction_output(s->master_rts, GPIO_HIGH);
-       gpio_direction_output(s->master_rdy, GPIO_HIGH);
-       
-       if (request_irq(s->irq, sc8800_irq,
-                       IRQF_TRIGGER_FALLING, "sc8800", s) < 0) {
-               dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq);
-               s->irq = 0;
-               goto irq_err;
-       }
-
-       if (s->sc8800_hw_suspend)
-               s->sc8800_hw_suspend(0);
-       
-       sc8800_dowork(s);
-
-       sc8800_enable_ms(&s->port);
-
-       return 0;
-       
-irq_err:
-       gpio_free(s->master_rdy);
-gpio_err4:
-       gpio_free(s->master_rts);
-gpio_err3:
-       gpio_free(s->slav_rdy);
-gpio_err2:
-       gpio_free(s->slav_rts);
-gpio_err1:
-       destroy_workqueue(s->workqueue);
-       s->workqueue = NULL;    
-       return ret;
-
-}
-
-static struct uart_ops sc8800_ops = {
-       .start_tx       = sc8800_start_tx,
-       .stop_rx        = sc8800_stop_rx,
-       .startup        = sc8800_startup,
-       .shutdown       = sc8800_shutdown,
-};
-
-static struct uart_driver sc8800_uart_driver = {
-       .owner          = THIS_MODULE,
-       .driver_name    = "ttySPI",
-       .dev_name       = "ttySPI",
-       .major          = SC8800_MAJOR,
-       .minor          = SC8800_MINOR,
-       .nr             = MAX_SC8800,
-};
-static int uart_driver_registered;
-
-static int __devinit sc8800_probe(struct spi_device *spi)
-{
-       int i, retval;
-       struct plat_sc8800 *pdata;
-       
-       mutex_lock(&sc8800s_lock);
-
-       if (!uart_driver_registered) {
-               uart_driver_registered = 1;
-               retval = uart_register_driver(&sc8800_uart_driver);
-               if (retval) {
-                       printk(KERN_ERR "Couldn't register sc8800 uart driver\n");
-                       mutex_unlock(&sc8800s_lock);
-                       return retval;
-               }
-       }
-
-       for (i = 0; i < MAX_SC8800; i++)
-               if (!sc8800s[i])
-                       break;
-       if (i == MAX_SC8800) {
-               dev_warn(&spi->dev, "too many SC8800 chips\n");
-               mutex_unlock(&sc8800s_lock);
-               return -ENOMEM;
-       }
-
-       sc8800s[i] = kzalloc(sizeof(struct sc8800_port), GFP_KERNEL);
-       if (!sc8800s[i]) {
-               dev_warn(&spi->dev,
-                        "kmalloc for sc8800 structure %d failed!\n", i);
-               mutex_unlock(&sc8800s_lock);
-               return -ENOMEM;
-       }
-       sc8800s[i]->spi = spi;
-       spin_lock_init(&sc8800s[i]->conf_lock);
-       dev_set_drvdata(&spi->dev, sc8800s[i]);
-       pdata = spi->dev.platform_data;
-       sc8800s[i]->irq = gpio_to_irq(pdata->slav_rts_pin);
-       sc8800s[i]->slav_rts = pdata->slav_rts_pin;
-       sc8800s[i]->slav_rdy = pdata->slav_rdy_pin;
-       sc8800s[i]->master_rts = pdata->master_rts_pin;
-       sc8800s[i]->master_rdy = pdata->master_rdy_pin;
-       //sc8800s[i]->sc8800_hw_suspend = pdata->sc8800_hw_suspend;
-       sc8800s[i]->minor = i;
-       init_timer(&sc8800s[i]->timer);
-       sc8800s[i]->timer.function = sc8800_timeout;
-       sc8800s[i]->timer.data = (unsigned long) sc8800s[i];
-
-       dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i);
-       sc8800s[i]->port.irq = sc8800s[i]->irq;
-       sc8800s[i]->port.uartclk = 24000000;
-       sc8800s[i]->port.fifosize = 64;
-       sc8800s[i]->port.ops = &sc8800_ops;
-       sc8800s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
-       sc8800s[i]->port.line = i;
-       sc8800s[i]->port.dev = &spi->dev;
-       retval = uart_add_one_port(&sc8800_uart_driver, &sc8800s[i]->port);
-       if (retval < 0)
-               dev_warn(&spi->dev,
-                        "uart_add_one_port failed for line %d with error %d\n",
-                        i, retval);
-
-       /* set shutdown mode to save power. Will be woken-up on open */
-       if (sc8800s[i]->sc8800_hw_suspend)
-               sc8800s[i]->sc8800_hw_suspend(1);
-
-       mutex_unlock(&sc8800s_lock);
-       return 0;
-}
-
-static int __devexit sc8800_remove(struct spi_device *spi)
-{
-       struct sc8800_port *s = dev_get_drvdata(&spi->dev);
-       int i;
-
-       mutex_lock(&sc8800s_lock);
-
-       /* find out the index for the chip we are removing */
-       for (i = 0; i < MAX_SC8800; i++)
-               if (sc8800s[i] == s)
-                       break;
-
-       dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i);
-       uart_remove_one_port(&sc8800_uart_driver, &sc8800s[i]->port);
-       kfree(sc8800s[i]);
-       sc8800s[i] = NULL;
-
-       /* check if this is the last chip we have */
-       for (i = 0; i < MAX_SC8800; i++)
-               if (sc8800s[i]) {
-                       mutex_unlock(&sc8800s_lock);
-                       return 0;
-               }
-       pr_debug("removing sc8800 driver\n");
-       uart_unregister_driver(&sc8800_uart_driver);
-
-       mutex_unlock(&sc8800s_lock);
-       return 0;
-}
-
-#ifdef CONFIG_PM
-
-static int sc8800_suspend(struct spi_device *spi, pm_message_t state)
-{
-       struct sc8800_port *s = dev_get_drvdata(&spi->dev);
-
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-
-       disable_irq(s->irq);
-
-       s->suspending = 1;
-       uart_suspend_port(&sc8800_uart_driver, &s->port);
-
-       if (s->sc8800_hw_suspend)
-               s->sc8800_hw_suspend(1);
-
-       return 0;
-}
-
-static int sc8800_resume(struct spi_device *spi)
-{
-       struct sc8800_port *s = dev_get_drvdata(&spi->dev);
-
-       dev_dbg(&s->spi->dev, "%s\n", __func__);
-
-       if (s->sc8800_hw_suspend)
-               s->sc8800_hw_suspend(0);
-       uart_resume_port(&sc8800_uart_driver, &s->port);
-       s->suspending = 0;
-
-       enable_irq(s->irq);
-
-       if (s->workqueue)
-               sc8800_dowork(s);
-
-       return 0;
-}
-
-#else
-#define sc8800_suspend NULL
-#define sc8800_resume  NULL
-#endif
-
-static struct spi_driver sc8800_driver = {
-       .driver = {
-               .name           = "sc8800",
-               .bus            = &spi_bus_type,
-               .owner          = THIS_MODULE,
-       },
-
-       .probe          = sc8800_probe,
-       .remove         = __devexit_p(sc8800_remove),
-       .suspend        = sc8800_suspend,
-       .resume         = sc8800_resume,
-};
-
-static int __init sc8800_init(void)
-{
-       return spi_register_driver(&sc8800_driver);
-}
-module_init(sc8800_init);
-
-static void __exit sc8800_exit(void)
-{
-       spi_unregister_driver(&sc8800_driver);
-}
-module_exit(sc8800_exit);
-
-MODULE_DESCRIPTION("SC8800 driver");
-MODULE_AUTHOR("liuyixing <lyx@rock-chips.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:SC8800");
diff --git a/drivers/serial/sc8800.h b/drivers/serial/sc8800.h
deleted file mode 100755 (executable)
index b425cb4..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __SC8800_H__\r
-#define __SC8800_H__\r
-\r
-typedef struct _spi_packet_head {\r
-       u16 tag; //HEADER_TAG(0x7e7f) \r
-       u16 type; //HEADER_TYPE(0xaa55) \r
-       u32 length; //the length of data after head  (8192-128 bytes) \r
-       u32 frame_num; //no used , always 0\r
-       u32 reserved2; //reserved \r
-} SPI_PACKET_HEAD_T;\r
-\r
-\r
-/*define flatform data struct*/\r
-struct plat_sc8800 {\r
-       int slav_rts_pin;\r
-       int slav_rdy_pin;\r
-       int master_rts_pin;\r
-       int master_rdy_pin;\r
-       int poll_time;\r
-};\r
-\r
-#endif\r
index 11a4b5b3596374530c164a952899d3cebaa991b3..e6578c85de82254a4837a8c6c31b4dd8aeb30691 100755 (executable)
@@ -104,6 +104,9 @@ source "drivers/staging/iio/Kconfig"
 
 source "drivers/staging/cs5535_gpio/Kconfig"
 
+source "drivers/staging/rk29/vivante/Kconfig"
+source "drivers/staging/rk29/ipp/Kconfig"
+
 source "drivers/staging/zram/Kconfig"
 
 source "drivers/staging/zcache/Kconfig"
index ae62e923e1b82203962f1453aec0311092d51a14..d00aa99e57f4aa541ef5ad1e24b0d7bc84b8f989 100755 (executable)
@@ -43,6 +43,8 @@ obj-$(CONFIG_VME_BUS)         += vme/
 obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)              += iio/
 obj-$(CONFIG_CS5535_GPIO)      += cs5535_gpio/
+obj-$(CONFIG_VIVANTE)          += rk29/vivante/
+obj-$(CONFIG_RK29_IPP)         += rk29/ipp/
 obj-$(CONFIG_ZRAM)             += zram/
 obj-$(CONFIG_XVMALLOC)         += zram/
 obj-$(CONFIG_ZCACHE)           += zcache/
index a64481c3e86d02ed02d094235f7e510b3e0df058..4c3e8fc63099df94ade21b352ca95ed83fe20e4d 100644 (file)
 #include <linux/hrtimer.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
-
+#include <linux/wakelock.h>
+#include <linux/delay.h>
 #include "timed_output.h"
 #include "timed_gpio.h"
 
+#define GPIO_TYPE   0 
 
 struct timed_gpio_data {
        struct timed_output_dev dev;
@@ -32,14 +34,40 @@ struct timed_gpio_data {
        unsigned        gpio;
        int             max_timeout;
        u8              active_low;
+       int             adjust_time;
+#if (GPIO_TYPE == 1)
+       struct work_struct      timed_gpio_work;        
+#endif
+       struct wake_lock        irq_wake;
 };
 
+#if (GPIO_TYPE == 1)
+static void timed_gpio_work_handler(struct work_struct *work)
+{
+       struct timed_gpio_data *data =
+               container_of(work, struct timed_gpio_data, timed_gpio_work);
+       int ret = 0,i = 0;
+       //set gpio several times once error happened
+       for(i=0; i<3; i++)
+       {
+               ret = gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
+               if(!ret)                
+                       break;
+               printk("%s:ret=%d,fail to set gpio and set again,i=%d\n",__FUNCTION__,ret,i);
+       }
+}
+#endif
+
 static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
 {
        struct timed_gpio_data *data =
                container_of(timer, struct timed_gpio_data, timer);
-
+               
+#if (GPIO_TYPE == 0)
        gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
+#else  
+       schedule_work(&data->timed_gpio_work);
+#endif 
        return HRTIMER_NORESTART;
 }
 
@@ -60,24 +88,26 @@ static void gpio_enable(struct timed_output_dev *dev, int value)
 {
        struct timed_gpio_data  *data =
                container_of(dev, struct timed_gpio_data, dev);
-       unsigned long   flags;
-
-       spin_lock_irqsave(&data->lock, flags);
+       int ret = 0,i = 0;
 
        /* cancel previous timer and set GPIO according to value */
        hrtimer_cancel(&data->timer);
-       gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
-
+       //set gpio several times once error happened
+       for(i=0; i<3; i++)
+       {
+               ret = gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
+               if(!ret)                
+                       break;
+               printk("%s:ret=%d,fail to set gpio and set again,i=%d\n",__FUNCTION__,ret,i);
+       }
        if (value > 0) {
+               value += data->adjust_time;
                if (value > data->max_timeout)
                        value = data->max_timeout;
-
                hrtimer_start(&data->timer,
                        ktime_set(value / 1000, (value % 1000) * 1000000),
                        HRTIMER_MODE_REL);
        }
-
-       spin_unlock_irqrestore(&data->lock, flags);
 }
 
 static int timed_gpio_probe(struct platform_device *pdev)
@@ -125,10 +155,17 @@ static int timed_gpio_probe(struct platform_device *pdev)
                gpio_dat->gpio = cur_gpio->gpio;
                gpio_dat->max_timeout = cur_gpio->max_timeout;
                gpio_dat->active_low = cur_gpio->active_low;
+               gpio_dat->adjust_time = cur_gpio->adjust_time;
                gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
        }
-
+#if (GPIO_TYPE == 1)
+    INIT_WORK(&gpio_dat->timed_gpio_work, timed_gpio_work_handler);
+#endif    
        platform_set_drvdata(pdev, gpio_data);
+       wake_lock_init(&gpio_data->irq_wake, WAKE_LOCK_SUSPEND, "timed_gpio_wake");
+
+       gpio_enable(&gpio_data ->dev, 100);
+       printk("%s\n",__FUNCTION__);
 
        return 0;
 }
@@ -168,7 +205,7 @@ static void __exit timed_gpio_exit(void)
        platform_driver_unregister(&timed_gpio_driver);
 }
 
-module_init(timed_gpio_init);
+subsys_initcall(timed_gpio_init);
 module_exit(timed_gpio_exit);
 
 MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
index a0e15f8be3f717e5aa8c6bb462ef3710b75bbba3..c8487df9a109142f7a9052c123b3243776814ded 100644 (file)
@@ -23,6 +23,7 @@ struct timed_gpio {
        unsigned        gpio;
        int             max_timeout;
        u8              active_low;
+       int         adjust_time;
 };
 
 struct timed_gpio_platform_data {
index 34c4be3c44cd93d3367b03b6805d56bf96cb40cb..4f1cd0cd34ec2a127c8a3d0ec9f520dea806b0de 100644 (file)
@@ -42,7 +42,7 @@ static gceSTATUS  _lastError  = gcvSTATUS_OK;
 static gctUINT32  _debugLevel = gcvLEVEL_ERROR;
 static gctUINT32  _debugZones = gcvZONE_NONE;
 static gctINT     _indent     = 0;
-static spinlock_t _lock       = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(_lock);
 
 static void
 OutputDebugString(
index f4eaae12536a53140b6edce84e0e1217299c6b37..2581c269ad9def76191d67afc2618b8b49acd7a5 100755 (executable)
@@ -2443,7 +2443,7 @@ gceSTATUS gckOS_CreateMutex(
     }
 
     /* Initialize the semaphore.. Come up in unlocked state. */
-    init_MUTEX(*Mutex);
+    sema_init(*Mutex, 1);
 
     /* Return status. */
     return gcvSTATUS_OK;
index b3692e6e3c13571f7733093957c882142c10cb37..f94445822a1ac02ee72f418358d35abe18c97acf 100644 (file)
@@ -1512,6 +1512,63 @@ config SERIAL_BCM63XX_CONSOLE
          If you have enabled the serial port on the bcm63xx CPU
          you can make it the console by answering Y to this option.
 
+config SERIAL_RK29
+       bool "RockChip rk29 serial port support"
+       depends on ARM && ARCH_RK29
+       select SERIAL_CORE
+
+config UART0_RK29
+       bool "RockChip rk29 serial port 0 support"
+       depends on SERIAL_RK29
+
+config UART0_CTS_RTS_RK29
+       bool "RockChip rk29 serial port 0 CTS/RTS support"
+       depends on UART0_RK29
+
+config UART0_DMA_RK29
+       bool "RockChip rk29 serial port 0 DMA support (EXPERIMENTAL)"
+       depends on UART0_RK29
+
+config UART1_RK29
+       bool "RockChip rk29 serial port 1 support"
+       depends on SERIAL_RK29
+
+config UART2_RK29
+       bool "RockChip rk29 serial port 2 support"
+       depends on SERIAL_RK29
+
+config UART2_CTS_RTS_RK29
+       bool "RockChip rk29 serial port 2 CTS/RTS support"
+       depends on UART2_RK29
+
+config UART2_DMA_RK29
+       bool "RockChip rk29 serial port 2 DMA support (EXPERIMENTAL)"
+       depends on UART2_RK29
+
+config UART3_RK29
+       bool "RockChip rk29 serial port 3 support"
+       depends on SERIAL_RK29
+
+config UART3_CTS_RTS_RK29
+       bool "RockChip rk29 serial port 3 CTS/RTS support"
+       depends on UART3_RK29
+
+config UART3_DMA_RK29
+       bool "RockChip rk29 serial port 3 DMA support (EXPERIMENTAL)"
+       depends on UART3_RK29
+
+config SERIAL_RK29_CONSOLE
+       bool "Rockchip rk29 serial console support"
+       depends on SERIAL_RK29=y
+       select SERIAL_CORE_CONSOLE
+
+config SERIAL_SC8800
+       tristate "SC8800 support"
+       depends on SPI
+       select SERIAL_CORE
+       help
+         SC8800 spi-serial support
+
 config SERIAL_GRLIB_GAISLER_APBUART
        tristate "GRLIB APBUART serial support"
        depends on OF && SPARC
index cb2628fee4c7160e20f16eec800c76642ecfe9f8..4c73acffb0645c84c03730fd1ceb470dccb64812 100644 (file)
@@ -83,6 +83,8 @@ obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
 obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
 obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
 obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
+obj-$(CONFIG_SERIAL_RK29) += rk_serial.o
+obj-$(CONFIG_SERIAL_SC8800) += sc8800.o
 obj-$(CONFIG_SERIAL_TIMBERDALE)        += timbuart.o
 obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
 obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
diff --git a/drivers/tty/serial/rk2818_serial.h b/drivers/tty/serial/rk2818_serial.h
new file mode 100644 (file)
index 0000000..54558ed
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * drivers/serial/rk2818_serial.h
+ *
+ * Copyright (C) 2010 ROCKCHIP, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRIVERS_SERIAL_RK2818_SERIAL_H
+#define __DRIVERS_SERIAL_RK2818_SERIAL_H
+
+#define UART_RBR       0x0000                  /* Receive Buffer Register */
+#define UART_THR       0x0000                  /* Transmit Holding Register */
+#define UART_DLL       0x0000                  /* Divisor Latch (Low) */
+#define UART_DLH       0x0004                  /* Divisor Latch (High) */
+#define UART_IER       0x0004                  /* Interrupt Enable Register */
+#define UART_IIR       0x0008                  /* Interrupt Identification Register */
+#define UART_FCR       0x0008                  /* FIFO Control Register */
+#define UART_LCR       0x000C                  /* Line Control Register */
+#define UART_MCR       0x0010                  /* Modem Control Register */
+#define UART_LSR       0x0014                  /* [0x0000_0060] Line Status Register */
+#define UART_MSR       0x0018                  /* Modem Status Register */
+#define UART_SCR       0x001c                  /* Scratchpad Register */
+#define UART_SRBR(n)   (0x0030+((n) * 4))      /* Shadow Receive Buffer Register */
+#define UART_STHR(n)   (0x0030+((n) * 4))      /* Shadow Transmit Holding Register */
+#define UART_FAR       0x0070                  /* FIFO Access Register */
+#define UART_TFR       0x0074                  /* Transmit FIFO Read */
+#define UART_RFW       0x0078                  /* Receive FIFO Write */
+#define UART_USR       0x007C                  /* UART Status Register */
+#define UART_TFL       0x0080                  /* Transmit FIFO Level */
+#define UART_RFL       0x0084                  /* Receive FIFO Level */
+#define UART_SRR       0x0088                  /* Software Reset Register */
+#define UART_SRTS      0x008C                  /* Shadow Request to Send */
+#define UART_SBCR      0x0090                  /* Shadow Break Control Register */
+#define UART_SDMAM     0x0094                  /* Shadow DMA Mode */
+#define UART_SFE       0x0098                  /* Shadow FIFO Enable */
+#define UART_SRT       0x009C                  /* Shadow RCVR Trigger */
+#define UART_STET      0x00A0                  /* Shadow TX Empty Trigger */
+#define UART_HTX       0x00A4                  /* Halt TX */
+#define UART_DMASA     0x00A8                  /* DMA Software Acknowledge */
+#define UART_CPR       0x00F4                  /* Component Parameter Register */
+#define UART_UCV       0x00F8                  /* [0x3330_372a] UART Component Version */
+#define UART_CTR       0x00FC                  /* [0x4457_0110] Component Type Register */
+
+//#define UART_FCR            0x08
+#define  UART_FCR_FIFO_ENABLE  (1<<0) 
+#define  UART_FCR_CLEAR_RCVR   (1<<1)  /* Clear the RCVR FIFO */
+#define  UART_FCR_CLEAR_XMIT           (1<<2)  /* Clear the XMIT FIFO */
+#define  UART_FCR_DMA_SELECT   (1<<3)   /* For DMA applications */
+#define  UART_FCR_R_TRIG_00    0x00
+#define  UART_FCR_R_TRIG_01    0x40
+#define  UART_FCR_R_TRIG_10    0x80
+#define  UART_FCR_R_TRIG_11    0xc0
+#define  UART_FCR_T_TRIG_00    0x00
+#define  UART_FCR_T_TRIG_01    0x10
+#define  UART_FCR_T_TRIG_10    0x20
+#define  UART_FCR_T_TRIG_11    0x30
+
+//#define UART_LCR            0x0c
+#define  LCR_DLA_EN                         (1<<7)
+#define  BREAK_CONTROL_BIT                  (1<<6)
+#define  EVEN_PARITY_SELECT                 (1<<4)
+#define  EVEN_PARITY                        (1<<4)
+#define  ODD_PARITY                          (0)
+#define  PARITY_DISABLED                     (0)
+#define  PARITY_ENABLED                     (1<<3)
+#define  ONE_STOP_BIT                        (0)
+#define  ONE_HALF_OR_TWO_BIT                (1<<2)
+#define  LCR_WLS_5                           (0x00)
+#define  LCR_WLS_6                           (0x01)
+#define  LCR_WLS_7                           (0x02)
+#define  LCR_WLS_8                           (0x03)
+#define  UART_DATABIT_MASK                   (0x03)
+
+/* Detail UART_IER  Register Description */
+#define UART_IER_THRE_MODE_INT_ENABLE          1<<7
+#define UART_IER_MODEM_STATUS_INT_ENABLE       1<<3
+#define UART_IER_RECV_LINE_STATUS_INT_ENABLE   1<<2
+#define UART_IER_SEND_EMPTY_INT_ENABLE         1<<1
+#define UART_IER_RECV_DATA_AVAIL_INT_ENABLE    1<<0
+
+
+/* Detail UART_IIR  Register Description */
+#define UART_IIR_FIFO_DISABLE                  0x00
+#define UART_IIR_FIFO_ENABLE                   0x03
+#define UART_IIR_INT_ID_MASK                   0x0F
+#define UART_IIR_MODEM_STATUS                  0x00
+#define UART_IIR_NO_INTERRUPT_PENDING  0x01
+#define UART_IIR_THR_EMPTY                         0x02
+#define UART_IIR_RECV_AVAILABLE                        0x04
+#define UART_IIR_RECV_LINE_STATUS              0x06
+#define UART_IIR_BUSY_DETECT                   0x07
+#define UART_IIR_CHAR_TIMEOUT                  0x0C
+
+//#define UART_MCR            0x10
+/* Modem Control Register */
+#define        UART_SIR_ENABLE (1 << 6)
+#define UART_MCR_AFCEN (1 << 5)        /* Auto Flow Control Mode enabled */
+#define UART_MCR_URLB  (1 << 4)        /* Loop-back mode */
+#define UART_MCR_UROUT2        (1 << 3)        /* OUT2 signal */
+#define UART_MCR_UROUT1        (1 << 2)        /* OUT1 signal */
+#define UART_MCR_URRTS (1 << 1)        /* Request to Send */
+#define UART_MCR_URDTR (1 << 0)        /* Data Terminal Ready */
+
+//#define UART_MSR            0x18
+/* Modem Status Register */
+#define UART_MSR_URDCD (1 << 7)        /* Data Carrier Detect */
+#define UART_MSR_URRI  (1 << 6)        /* Ring Indicator */
+#define UART_MSR_URDSR (1 << 5)        /* Data Set Ready */
+#define UART_MSR_URCTS (1 << 4)        /* Clear to Send */
+#define UART_MSR_URDDCD        (1 << 3)        /* Delta Data Carrier Detect */
+#define UART_MSR_URTERI        (1 << 2)        /* Trailing Edge Ring Indicator */
+#define UART_MSR_URDDST        (1 << 1)        /* Delta Data Set Ready */
+#define UART_MSR_URDCTS        (1 << 0)        /* Delta Clear to Send */
+
+/* Detail UART_USR  Register Description */
+#define  UART_RECEIVE_FIFO_FULL              (1<<4)
+#define  UART_RECEIVE_FIFO_NOT_FULL          (0)
+#define  UART_RECEIVE_FIFO_EMPTY             (0)
+#define  UART_RECEIVE_FIFO_NOT_EMPTY         (1<<3)
+#define  UART_TRANSMIT_FIFO_NOT_EMPTY        (0)
+#define  UART_TRANSMIT_FIFO_EMPTY            (1<<2)
+#define  UART_TRANSMIT_FIFO_FULL             (0)
+#define  UART_TRANSMIT_FIFO_NOT_FULL         (1<<1)
+#define  UART_USR_BUSY                       (1)
+
+/*UART_LSR Line Status Register*/
+#define UART_BREAK_INT_BIT                                     (1<<4)/*break Interrupt bit*/
+
+#endif /* __DRIVERS_SERIAL_RK2818_SERIAL_H */
diff --git a/drivers/tty/serial/rk_serial.c b/drivers/tty/serial/rk_serial.c
new file mode 100644 (file)
index 0000000..91f35d1
--- /dev/null
@@ -0,0 +1,1917 @@
+/*\r
+ * Driver for RK-UART controller.\r
+ * Based on drivers/tty/serial/8250.c\r
+ *\r
+ * Copyright (C) 2011 Rochchip.\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+\r
+ * (at your option) any later version.\r
+ *\r
+ * Author: hhb@rock-chips.com\r
+ * Date: 2011.06.18\r
+ */\r
+\r
+#ifndef CONFIG_SERIAL_RK_CONSOLE\r
+#if defined(CONFIG_SERIAL_RK29_CONSOLE)\r
+#define CONFIG_SERIAL_RK_CONSOLE\r
+#endif\r
+#endif\r
+\r
+#if defined(CONFIG_SERIAL_RK_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)\r
+#define SUPPORT_SYSRQ\r
+#endif\r
+\r
+//#define DEBUG\r
+#include <linux/module.h>\r
+#include <linux/ioport.h>\r
+#include <linux/init.h>\r
+#include <linux/console.h>\r
+#include <linux/sysrq.h>\r
+#include <linux/delay.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/tty.h>\r
+#include <linux/ratelimit.h>\r
+#include <linux/tty_flip.h>\r
+#include <linux/serial_reg.h>\r
+#include <linux/serial_core.h>\r
+#include <linux/serial.h>\r
+#include <linux/serial_8250.h>\r
+#include <linux/nmi.h>\r
+#include <linux/mutex.h>\r
+#include <linux/slab.h>\r
+#include <linux/clk.h>\r
+#include <linux/timer.h>\r
+#include <linux/workqueue.h>\r
+#include <mach/rk29-dma-pl330.h>\r
+#include <linux/dma-mapping.h>\r
+\r
+#include <asm/io.h>\r
+#include <asm/irq.h>\r
+\r
+\r
+#define PORT_RK                90\r
+#define UART_USR       0x1F    /* UART Status Register */\r
+#define UART_USR_BUSY (1)\r
+#define UART_IER_PTIME 0x80    /* Programmable THRE Interrupt Mode Enable */\r
+#define UART_LSR_RFE   0x80    /* receive fifo error */\r
+#define UART_SRR               0x22    /* software reset register */\r
+#define UART_RESET             0x01\r
+#define RX_TIMEOUT             (3000*10)  //uint ms\r
+\r
+#define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)\r
+\r
+#define UART_NR        4   //uart port number\r
+#define POWER_MANEGEMENT 1\r
+\r
+/* configurate whether the port transmit-receive by DMA */\r
+#define OPEN_DMA      1\r
+#define CLOSE_DMA     0\r
+\r
+#ifdef CONFIG_UART0_DMA_RK29\r
+#define UART0_USE_DMA OPEN_DMA\r
+#else\r
+#define UART0_USE_DMA CLOSE_DMA\r
+#endif\r
+\r
+#ifdef CONFIG_UART2_DMA_RK29\r
+#define UART2_USE_DMA OPEN_DMA\r
+#else\r
+#define UART2_USE_DMA CLOSE_DMA\r
+#endif\r
+\r
+#ifdef CONFIG_UART3_DMA_RK29\r
+#define UART3_USE_DMA OPEN_DMA\r
+#else\r
+#define UART3_USE_DMA CLOSE_DMA\r
+#endif\r
+\r
+#define UART1_USE_DMA CLOSE_DMA\r
+\r
+#define DMA_TX_TRRIGE_LEVEL 30\r
+\r
+#define USE_TIMER 1           // use timer for dma transport\r
+#define THRE_MODE 0X00   //0yhh\r
+\r
+static struct uart_driver serial_rk_reg;\r
+\r
+/*\r
+ * Debugging.\r
+ */\r
+#define DBG_PORT 1   //DBG_PORT which uart is used to print log message\r
+\r
+#ifdef CONFIG_SERIAL_CORE_CONSOLE\r
+#define uart_console(port)     ((port)->cons && (port)->cons->index == (port)->line)\r
+#else\r
+#define uart_console(port)     (0)\r
+#endif\r
+\r
+#define DEBUG 0\r
+\r
+extern void printascii(const char *);\r
+static void dbg(const char *fmt, ...)\r
+{\r
+       va_list va;\r
+       char buff[256];\r
+\r
+       va_start(va, fmt);\r
+       vsprintf(buff, fmt, va);\r
+       va_end(va);\r
+\r
+       printascii(buff);\r
+}\r
+\r
+#if DEBUG\r
+#define DEBUG_INTR(fmt...)     if (!uart_console(&up->port)) dbg(fmt)\r
+#else\r
+#define DEBUG_INTR(fmt...)     do { } while (0)\r
+#endif\r
+\r
+\r
+/* added by hhb@rock-chips.com for uart dma transfer */\r
+\r
+struct rk29_uart_dma_t {\r
+       u32 use_dma;            //1:used\r
+       u32 rx_dma_start;\r
+       enum dma_ch rx_dmach;\r
+       enum dma_ch tx_dmach;\r
+       u32 tx_dma_inited;\r
+       u32 rx_dma_inited;\r
+       spinlock_t              tx_lock;\r
+       spinlock_t              rx_lock;\r
+       char * rx_buffer;\r
+       char * tx_buffer;\r
+       dma_addr_t rx_phy_addr;\r
+       dma_addr_t tx_phy_addr;\r
+       u32 rx_buffer_size;\r
+       u32 tx_buffer_size;\r
+\r
+       u32 rb_cur_pos;\r
+       u32 rb_pre_pos;\r
+       u32 rx_size;\r
+       char use_timer;\r
+       char tx_dma_used;\r
+       /* timer to poll activity on rx dma */\r
+       struct timer_list       rx_timer;\r
+       int                     rx_timeout;\r
+\r
+};\r
+\r
+struct uart_rk_port {\r
+       struct uart_port        port;\r
+       struct platform_device  *pdev;\r
+       struct clk              *clk;\r
+       unsigned int            tx_loadsz;      /* transmit fifo load size */\r
+       unsigned char           ier;\r
+       unsigned char           lcr;\r
+       unsigned char           mcr;\r
+       unsigned char           iir;\r
+       unsigned char           fcr;\r
+       /*\r
+        * Some bits in registers are cleared on a read, so they must\r
+        * be saved whenever the register is read but the bits will not\r
+        * be immediately processed.\r
+        */\r
+#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS\r
+       unsigned char           lsr_saved_flags;\r
+#if 0\r
+#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA\r
+       unsigned char           msr_saved_flags;\r
+#endif\r
+\r
+       char                    name[12];\r
+       char                    fifo[32];\r
+       char                    fifo_size;\r
+       unsigned long           port_activity;\r
+       struct work_struct uart_work;\r
+       struct work_struct uart_work_rx;\r
+       struct workqueue_struct *uart_wq;\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t;\r
+};\r
+\r
+static void serial_rk_release_dma_tx(struct uart_port *port);\r
+static int serial_rk_start_tx_dma(struct uart_port *port);\r
+static void serial_rk_rx_timeout(unsigned long uart);\r
+static void serial_rk_release_dma_rx(struct uart_port *port);\r
+static int serial_rk_start_rx_dma(struct uart_port *port);\r
+static int serial_rk_startup(struct uart_port *port);\r
+static inline unsigned int serial_in(struct uart_rk_port *up, int offset)\r
+{\r
+       offset = offset << 2;\r
+       return readb(up->port.membase + offset);\r
+}\r
+\r
+/* Save the LCR value so it can be re-written when a Busy Detect IRQ occurs. */\r
+static inline void dwapb_save_out_value(struct uart_rk_port *up, int offset,\r
+                                       unsigned char value)\r
+{\r
+       if (offset == UART_LCR)\r
+               up->lcr = value;\r
+}\r
+\r
+/* Read the IER to ensure any interrupt is cleared before returning from ISR. */\r
+static inline void dwapb_check_clear_ier(struct uart_rk_port *up, int offset)\r
+{\r
+       if (offset == UART_TX || offset == UART_IER)\r
+               serial_in(up, UART_IER);\r
+}\r
+\r
+static inline void serial_out(struct uart_rk_port *up, int offset, unsigned char value)\r
+{\r
+       dwapb_save_out_value(up, offset, value);\r
+       writeb(value, up->port.membase + (offset << 2));\r
+       dwapb_check_clear_ier(up, offset);\r
+}\r
+\r
+/* Uart divisor latch read */\r
+static inline int serial_dl_read(struct uart_rk_port *up)\r
+{\r
+       return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;\r
+}\r
+\r
+/* Uart divisor latch write */\r
+static int serial_dl_write(struct uart_rk_port *up, unsigned int value)\r
+{\r
+       unsigned int tmout = 100;\r
+       if(up->port.line != DBG_PORT)\r
+       {\r
+               while(!(serial_in(up, UART_LCR) & UART_LCR_DLAB)){\r
+                       if (--tmout == 0){\r
+                               dbg("set serial.%d baudrate fail with DLAB not set\n", up->port.line);\r
+                               return -1;\r
+                       }\r
+               }\r
+\r
+               tmout = 15000;\r
+               while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
+                       if (--tmout == 0){\r
+                               dbg("set serial.%d baudrate timeout\n", up->port.line);\r
+                               return -1;\r
+                       }\r
+               }\r
+       }\r
+\r
+       serial_out(up, UART_DLL, value & 0xff);\r
+       serial_out(up, UART_DLM, value >> 8 & 0xff);\r
+\r
+       return 0;\r
+\r
+}\r
+\r
+static int serial_lcr_write(struct uart_rk_port *up, unsigned char value)\r
+{\r
+       unsigned int tmout = 15000;\r
+\r
+       if(up->port.line != DBG_PORT)\r
+       {\r
+               while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
+\r
+                       if (--tmout == 0){\r
+                               dbg("set serial.%d lc r = 0x%02x timeout\n", up->port.line, value);\r
+                               return -1;\r
+                       }\r
+                       udelay(1);\r
+               }\r
+       }\r
+\r
+       serial_out(up, UART_LCR, value);\r
+\r
+       return 0;\r
+}\r
+\r
+static inline void serial_rk_enable_ier_thri(struct uart_rk_port *up)\r
+{\r
+       if (!(up->ier & UART_IER_THRI)) {\r
+               up->ier |= UART_IER_THRI;\r
+               serial_out(up, UART_IER, up->ier);\r
+       }\r
+}\r
+\r
+\r
+static inline void serial_rk_disable_ier_thri(struct uart_rk_port *up)\r
+{\r
+       if (up->ier & UART_IER_THRI) {\r
+               up->ier &= ~UART_IER_THRI;\r
+               serial_out(up, UART_IER, up->ier);\r
+       }\r
+}\r
+#if 0\r
+static int rk29_uart_dump_register(struct uart_rk_port *up){\r
+\r
+       unsigned int reg_value = 0;\r
+\r
+       reg_value = serial_in(up, UART_IER);\r
+       dbg("UART_IER = 0x%0x\n", reg_value);\r
+       reg_value = serial_in(up, UART_IIR);\r
+       dbg("UART_IIR = 0x%0x\n", reg_value);\r
+    reg_value = serial_in(up, UART_LSR);\r
+    dbg("UART_LSR = 0x%0x\n", reg_value);\r
+    reg_value = serial_in(up, UART_MSR);\r
+    dbg("UART_MSR = 0x%0x\n", reg_value);\r
+    reg_value = serial_in(up, UART_MCR);\r
+    dbg("UART_MCR = 0x%0x\n", reg_value);\r
+    reg_value = serial_in(up, 0x21);\r
+    dbg("UART_RFL = 0x%0x\n", reg_value);\r
+    reg_value = serial_in(up, UART_LCR);\r
+    dbg("UART_LCR = 0x%0x\n", reg_value);\r
+       return 0;\r
+\r
+}\r
+#endif\r
+\r
+/*\r
+ * FIFO support.\r
+ */\r
+static void serial_rk_clear_fifos(struct uart_rk_port *up)\r
+{\r
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);\r
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |\r
+                      UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);\r
+       serial_out(up, UART_FCR, 0);\r
+}\r
+\r
+static inline void __stop_tx(struct uart_rk_port *p)\r
+{\r
+       if (p->ier & UART_IER_THRI) {\r
+               p->ier &= ~UART_IER_THRI;\r
+               serial_out(p, UART_IER, p->ier);\r
+       }\r
+}\r
+\r
+static void serial_rk_stop_tx(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+\r
+       if(OPEN_DMA == prk29_uart_dma_t->use_dma){\r
+               serial_rk_release_dma_tx(port);\r
+       }\r
+       __stop_tx(up);\r
+}\r
+\r
+\r
+static void serial_rk_start_tx(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+\r
+\r
+       if(0 == serial_rk_start_tx_dma(port)){\r
+               serial_rk_enable_ier_thri(up);\r
+       }\r
+\r
+}\r
+\r
+\r
+static void serial_rk_stop_rx(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+\r
+       if(OPEN_DMA == prk29_uart_dma_t->use_dma){\r
+               serial_rk_release_dma_rx(port);\r
+       }\r
+       up->ier &= ~UART_IER_RLSI;\r
+       up->port.read_status_mask &= ~UART_LSR_DR;\r
+       serial_out(up, UART_IER, up->ier);\r
+}\r
+\r
+\r
+static void serial_rk_enable_ms(struct uart_port *port)\r
+{\r
+       /* no MSR capabilities */\r
+#if 0\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+       up->ier |= UART_IER_MSI;\r
+       serial_out(up, UART_IER, up->ier);\r
+#endif\r
+}\r
+\r
+\r
+/*\r
+ * Start transmitting by dma.\r
+ */\r
+#define DMA_SERIAL_BUFFER_SIZE     UART_XMIT_SIZE\r
+\r
+/* added by hhb@rock-chips.com  for uart dma transfer*/\r
+static struct rk29_uart_dma_t rk29_uart_ports_dma_t[] = {\r
+               {UART0_USE_DMA, 0, DMACH_UART0_RX, DMACH_UART0_TX},\r
+               {UART1_USE_DMA, 0, DMACH_UART1_RX, DMACH_UART1_TX},\r
+               {UART2_USE_DMA, 0, DMACH_UART2_RX, DMACH_UART2_TX},\r
+               {UART3_USE_DMA, 0, DMACH_UART3_RX, DMACH_UART3_TX},\r
+};\r
+\r
+\r
+/* DMAC PL330 add by hhb@rock-chips.com */\r
+static struct rk29_dma_client rk29_uart_dma_client = {\r
+       .name = "rk29xx-uart-dma",\r
+};\r
+\r
+/*TX*/\r
+\r
+static void serial_rk_release_dma_tx(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+                       container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       if(!port){\r
+               return;\r
+       }\r
+       if(prk29_uart_dma_t && prk29_uart_dma_t->tx_dma_inited) {\r
+               rk29_dma_free(prk29_uart_dma_t->tx_dmach, &rk29_uart_dma_client);\r
+               prk29_uart_dma_t->tx_dma_inited = 0;\r
+       }\r
+}\r
+\r
+/*this function will be called every time after rk29_dma_enqueue() be invoked*/\r
+static void serial_rk_dma_txcb(void *buf, int size, enum rk29_dma_buffresult result) {\r
+       struct uart_port *port = buf;\r
+       struct uart_rk_port *up = container_of(port, struct uart_rk_port, port);\r
+       struct circ_buf *xmit = &port->state->xmit;\r
+\r
+       if(result != RK29_RES_OK){\r
+               return;\r
+       }\r
+\r
+       port->icount.tx += size;\r
+       xmit->tail = (xmit->tail + size) & (UART_XMIT_SIZE - 1);\r
+\r
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
+               uart_write_wakeup(&up->port);\r
+       spin_lock(&(up->prk29_uart_dma_t->tx_lock));\r
+       up->prk29_uart_dma_t->tx_dma_used = 0;\r
+       spin_unlock(&(up->prk29_uart_dma_t->tx_lock));\r
+       if (!uart_circ_empty(xmit)) {\r
+               serial_rk_start_tx_dma(port);\r
+       }\r
+\r
+       up->port_activity = jiffies;\r
+//     dev_info(up->port.dev, "s:%d\n", size);\r
+}\r
+\r
+static int serial_rk_init_dma_tx(struct uart_port *port) {\r
+\r
+       struct uart_rk_port *up =\r
+                               container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       if(!port || !prk29_uart_dma_t){\r
+               dev_info(up->port.dev, "serial_rk_init_dma_tx fail\n");\r
+               return -1;\r
+       }\r
+\r
+       if(prk29_uart_dma_t->tx_dma_inited) {\r
+               return 0;\r
+       }\r
+\r
+       if (rk29_dma_request(prk29_uart_dma_t->tx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
+               dev_info(up->port.dev, "rk29_dma_request tx fail\n");\r
+               return -1;\r
+       }\r
+\r
+       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->tx_dmach, serial_rk_dma_txcb)) {\r
+               dev_info(up->port.dev, "rk29_dma_set_buffdone_fn tx fail\n");\r
+               return -1;\r
+       }\r
+       if (rk29_dma_devconfig(prk29_uart_dma_t->tx_dmach, RK29_DMASRC_MEM, (unsigned long)(port->iobase + UART_TX))) {\r
+               dev_info(up->port.dev, "rk29_dma_devconfig tx fail\n");\r
+               return -1;\r
+       }\r
+       if (rk29_dma_config(prk29_uart_dma_t->tx_dmach, 1, 1)) {\r
+               dev_info(up->port.dev, "rk29_dma_config tx fail\n");\r
+               return -1;\r
+       }\r
+\r
+       prk29_uart_dma_t->tx_dma_inited = 1;\r
+       dev_info(up->port.dev, "serial_rk_init_dma_tx sucess\n");\r
+       return 0;\r
+\r
+}\r
+\r
+static int serial_rk_start_tx_dma(struct uart_port *port)\r
+{\r
+\r
+       struct circ_buf *xmit = &port->state->xmit;\r
+       struct uart_rk_port *up = container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+\r
+       if(0 == prk29_uart_dma_t->use_dma){\r
+               return CLOSE_DMA;\r
+       }\r
+\r
+       if(-1 == serial_rk_init_dma_tx(port)){\r
+               goto err_out;\r
+       }\r
+\r
+       if (1 == prk29_uart_dma_t->tx_dma_used){\r
+               return 1;\r
+       }\r
+       if(!uart_circ_empty(xmit)){\r
+               if (rk29_dma_enqueue(prk29_uart_dma_t->tx_dmach, port,\r
+                               prk29_uart_dma_t->tx_phy_addr + xmit->tail,\r
+                               CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE))) {\r
+                       goto err_out;\r
+               }\r
+       }\r
+       rk29_dma_ctrl(prk29_uart_dma_t->tx_dmach, RK29_DMAOP_START);\r
+       spin_lock(&(prk29_uart_dma_t->tx_lock));\r
+       up->prk29_uart_dma_t->tx_dma_used = 1;\r
+       spin_unlock(&(prk29_uart_dma_t->tx_lock));\r
+\r
+       return 1;\r
+err_out:\r
+       dev_info(up->port.dev, "-serial_rk_start_tx_dma-error-\n");\r
+       return -1;\r
+\r
+}\r
+\r
+\r
+\r
+/*RX*/\r
+static void serial_rk_dma_rxcb(void *buf, int size, enum rk29_dma_buffresult result) {\r
+\r
+\r
+}\r
+\r
+static void serial_rk_release_dma_rx(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+                               container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       if(!port){\r
+               return;\r
+       }\r
+       if(prk29_uart_dma_t && prk29_uart_dma_t->rx_dma_inited) {\r
+               del_timer(&prk29_uart_dma_t->rx_timer);\r
+               rk29_dma_free(prk29_uart_dma_t->rx_dmach, &rk29_uart_dma_client);\r
+               prk29_uart_dma_t->rb_pre_pos = 0;\r
+               prk29_uart_dma_t->rx_dma_inited = 0;\r
+               prk29_uart_dma_t->rx_dma_start = 0;\r
+       }\r
+}\r
+\r
+\r
+static int serial_rk_init_dma_rx(struct uart_port *port) {\r
+\r
+       struct uart_rk_port *up =\r
+                               container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       if(!port || !prk29_uart_dma_t){\r
+               dev_info(up->port.dev, "serial_rk_init_dma_rx: port fail\n");\r
+               return -1;\r
+       }\r
+       if(prk29_uart_dma_t->rx_dma_inited) {\r
+               return 0;\r
+       }\r
+\r
+       if (rk29_dma_request(prk29_uart_dma_t->rx_dmach, &rk29_uart_dma_client, NULL) == -EBUSY) {\r
+               dev_info(up->port.dev, "rk29_dma_request fail rx \n");\r
+               return -1;\r
+       }\r
+\r
+       if (rk29_dma_set_buffdone_fn(prk29_uart_dma_t->rx_dmach, serial_rk_dma_rxcb)) {\r
+               dev_info(up->port.dev, "rk29_dma_set_buffdone_fn rx fail\n");\r
+               return -1;\r
+       }\r
+       if (rk29_dma_devconfig(prk29_uart_dma_t->rx_dmach, RK29_DMASRC_HW, (unsigned long)(port->iobase + UART_RX))) {\r
+               dev_info(up->port.dev, "rk29_dma_devconfig rx fail\n");\r
+               return -1;\r
+       }\r
+\r
+       if (rk29_dma_config(prk29_uart_dma_t->rx_dmach, 1, 1)) {\r
+               dev_info(up->port.dev, "rk29_dma_config rx fail\n");\r
+               return -1;\r
+       }\r
+\r
+       rk29_dma_setflags(prk29_uart_dma_t->rx_dmach, RK29_DMAF_CIRCULAR);\r
+\r
+       prk29_uart_dma_t->rx_dma_inited = 1;\r
+       dev_info(up->port.dev, "serial_rk_init_dma_rx sucess\n");\r
+       return 0;\r
+\r
+}\r
+\r
+static int serial_rk_start_rx_dma(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+                               container_of(port, struct uart_rk_port, port);\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       if(0 == prk29_uart_dma_t->use_dma){\r
+               return 0;\r
+       }\r
+\r
+       if(prk29_uart_dma_t->rx_dma_start == 1){\r
+               return 0;\r
+       }\r
+\r
+       if(-1 == serial_rk_init_dma_rx(port)){\r
+               dev_info(up->port.dev, "*******serial_rk_init_dma_rx*******error*******\n");\r
+               return -1;\r
+       }\r
+\r
+       if (rk29_dma_enqueue(prk29_uart_dma_t->rx_dmach, (void *)up, prk29_uart_dma_t->rx_phy_addr,\r
+                       prk29_uart_dma_t->rx_buffer_size/2)) {\r
+               dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
+               return -1;\r
+       }\r
+\r
+       if (rk29_dma_enqueue(prk29_uart_dma_t->rx_dmach, (void *)up,\r
+                       prk29_uart_dma_t->rx_phy_addr+prk29_uart_dma_t->rx_buffer_size/2,\r
+               prk29_uart_dma_t->rx_buffer_size/2)) {\r
+               dev_info(up->port.dev, "*******rk29_dma_enqueue fail*****\n");\r
+               return -1;\r
+       }\r
+\r
+       rk29_dma_ctrl(prk29_uart_dma_t->rx_dmach, RK29_DMAOP_START);\r
+       prk29_uart_dma_t->rx_dma_start = 1;\r
+       if(prk29_uart_dma_t->use_timer == 1){\r
+               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies +\r
+                               msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
+       }\r
+       up->port_activity = jiffies;\r
+       return 1;\r
+}\r
+\r
+static void serial_rk_update_rb_addr(struct uart_rk_port *up){\r
+       dma_addr_t current_pos = 0;\r
+       dma_addr_t rx_current_pos = 0;\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
+       rk29_dma_getposition(prk29_uart_dma_t->rx_dmach, &current_pos, &rx_current_pos);\r
+\r
+       prk29_uart_dma_t->rb_cur_pos = (rx_current_pos - prk29_uart_dma_t->rx_phy_addr);\r
+       prk29_uart_dma_t->rx_size = CIRC_CNT(prk29_uart_dma_t->rb_cur_pos,\r
+                       prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_buffer_size);\r
+\r
+       spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
+}\r
+\r
+static void serial_rk_report_dma_rx(unsigned long uart)\r
+{\r
+       struct uart_rk_port *up = (struct uart_rk_port *)uart;\r
+       struct rk29_uart_dma_t *prk29_uart_dma_t = up->prk29_uart_dma_t;\r
+       if(prk29_uart_dma_t->use_timer == 1){\r
+               serial_rk_update_rb_addr(up);\r
+       }\r
+       if(prk29_uart_dma_t->rx_size > 0) {\r
+               spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
+\r
+               if(prk29_uart_dma_t->rb_cur_pos > prk29_uart_dma_t->rb_pre_pos){\r
+                       tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer\r
+                                       + prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_size);\r
+                       tty_flip_buffer_push(up->port.state->port.tty);\r
+               }\r
+               else if(prk29_uart_dma_t->rb_cur_pos < prk29_uart_dma_t->rb_pre_pos){\r
+\r
+                       tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer\r
+                                       + prk29_uart_dma_t->rb_pre_pos, CIRC_CNT_TO_END(prk29_uart_dma_t->rb_cur_pos,\r
+                                       prk29_uart_dma_t->rb_pre_pos, prk29_uart_dma_t->rx_buffer_size));\r
+                       tty_flip_buffer_push(up->port.state->port.tty);\r
+\r
+                       if(prk29_uart_dma_t->rb_cur_pos != 0){\r
+                               tty_insert_flip_string(up->port.state->port.tty, prk29_uart_dma_t->rx_buffer,\r
+                                               prk29_uart_dma_t->rb_cur_pos);\r
+                               tty_flip_buffer_push(up->port.state->port.tty);\r
+                       }\r
+               }\r
+\r
+               prk29_uart_dma_t->rb_pre_pos = (prk29_uart_dma_t->rb_pre_pos + prk29_uart_dma_t->rx_size)\r
+                               & (prk29_uart_dma_t->rx_buffer_size - 1);\r
+               up->port.icount.rx += prk29_uart_dma_t->rx_size;\r
+               spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
+               prk29_uart_dma_t->rx_timeout = 7;\r
+               up->port_activity = jiffies;\r
+       }\r
+\r
+\r
+#if 1\r
+       if (jiffies_to_msecs(jiffies - up->port_activity) < RX_TIMEOUT) {\r
+               if(prk29_uart_dma_t->use_timer == 1){\r
+                       mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
+               }\r
+       } else {\r
+\r
+#if 1\r
+\r
+\r
+               prk29_uart_dma_t->rx_timeout = 20;\r
+               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
+#else\r
+//             serial_out(up, 0x2a, 0x01);\r
+               serial_rk_release_dma_rx(&up->port);\r
+               serial_out(up, 0x2a, 0x01);\r
+               up->ier |= (UART_IER_RDI | UART_IER_RLSI);\r
+               serial_out(up, UART_IER, up->ier);\r
+//             serial_out(up, 0x22, 0x01);\r
+               dev_info(up->port.dev, "*****enable recv int*****\n");\r
+\r
+               //serial_rk_start_rx_dma(&up->port);\r
+#endif\r
+       }\r
+\r
+\r
+#else\r
+       if(prk29_uart_dma_t->use_timer == 1){\r
+               mod_timer(&prk29_uart_dma_t->rx_timer, jiffies + msecs_to_jiffies(prk29_uart_dma_t->rx_timeout));\r
+       }\r
+#endif\r
+\r
+}\r
+\r
+static void serial_rk_rx_timeout(unsigned long uart)\r
+{\r
+       struct uart_rk_port *up = (struct uart_rk_port *)uart;\r
+\r
+       //serial_rk_report_dma_rx(up);\r
+       queue_work(up->uart_wq, &up->uart_work);\r
+}\r
+\r
+static void serial_rk_report_revdata_workfunc(struct work_struct *work)\r
+{\r
+       struct uart_rk_port *up =\r
+                               container_of(work, struct uart_rk_port, uart_work);\r
+       serial_rk_report_dma_rx((unsigned long)up);\r
+       spin_lock(&(up->prk29_uart_dma_t->rx_lock));\r
+\r
+       if(up->prk29_uart_dma_t->use_timer == 1){\r
+\r
+       }else{\r
+               tty_insert_flip_string(up->port.state->port.tty, up->fifo, up->fifo_size);\r
+               tty_flip_buffer_push(up->port.state->port.tty);\r
+               up->port.icount.rx += up->fifo_size;\r
+       }\r
+\r
+       spin_unlock(&(up->prk29_uart_dma_t->rx_lock));\r
+\r
+}\r
+\r
+\r
+static void serial_rk_start_dma_rx(struct work_struct *work)\r
+{\r
+       struct uart_rk_port *up =\r
+                                       container_of(work, struct uart_rk_port, uart_work_rx);\r
+       serial_rk_start_rx_dma(&up->port);\r
+}\r
+\r
+\r
+\r
+static void\r
+receive_chars(struct uart_rk_port *up, unsigned int *status)\r
+{\r
+       struct tty_struct *tty = up->port.state->port.tty;\r
+       unsigned char ch, lsr = *status;\r
+       int max_count = 256;\r
+       char flag;\r
+\r
+       do {\r
+               if (likely(lsr & UART_LSR_DR)){\r
+                       ch = serial_in(up, UART_RX);\r
+               }\r
+               else\r
+                       /*\r
+                        * Intel 82571 has a Serial Over Lan device that will\r
+                        * set UART_LSR_BI without setting UART_LSR_DR when\r
+                        * it receives a break. To avoid reading from the\r
+                        * receive buffer without UART_LSR_DR bit set, we\r
+                        * just force the read character to be 0\r
+                        */\r
+                       ch = 0;\r
+\r
+               flag = TTY_NORMAL;\r
+               up->port.icount.rx++;\r
+\r
+               lsr |= up->lsr_saved_flags;\r
+               up->lsr_saved_flags = 0;\r
+\r
+               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {\r
+                       /*\r
+                        * For statistics only\r
+                        */\r
+                       if (lsr & UART_LSR_BI) {\r
+                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);\r
+                               up->port.icount.brk++;\r
+                               /*\r
+                                * We do the SysRQ and SAK checking\r
+                                * here because otherwise the break\r
+                                * may get masked by ignore_status_mask\r
+                                * or read_status_mask.\r
+                                */\r
+                               if (uart_handle_break(&up->port))\r
+                                       goto ignore_char;\r
+                       } else if (lsr & UART_LSR_PE)\r
+                               up->port.icount.parity++;\r
+                       else if (lsr & UART_LSR_FE)\r
+                               up->port.icount.frame++;\r
+                       if (lsr & UART_LSR_OE)\r
+                               up->port.icount.overrun++;\r
+\r
+\r
+                       /*\r
+                        * Mask off conditions which should be ignored.\r
+                        */\r
+                       lsr &= up->port.read_status_mask;\r
+\r
+                       if (lsr & UART_LSR_BI) {\r
+                               DEBUG_INTR("handling break....");\r
+                               flag = TTY_BREAK;\r
+                       } else if (lsr & UART_LSR_PE)\r
+                               flag = TTY_PARITY;\r
+                       else if (lsr & UART_LSR_FE)\r
+                               flag = TTY_FRAME;\r
+               }\r
+               if (uart_handle_sysrq_char(&up->port, ch))\r
+                       goto ignore_char;\r
+\r
+               uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);\r
+\r
+ignore_char:\r
+               lsr = serial_in(up, UART_LSR);\r
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));\r
+       spin_unlock(&up->port.lock);\r
+       tty_flip_buffer_push(tty);\r
+       spin_lock(&up->port.lock);\r
+       *status = lsr;\r
+}\r
+\r
+static void transmit_chars(struct uart_rk_port *up)\r
+{\r
+       struct circ_buf *xmit = &up->port.state->xmit;\r
+       int count;\r
+\r
+       if (up->port.x_char) {\r
+               serial_out(up, UART_TX, up->port.x_char);\r
+               up->port.icount.tx++;\r
+               up->port.x_char = 0;\r
+               return;\r
+       }\r
+       if (uart_tx_stopped(&up->port)) {\r
+               __stop_tx(up);\r
+               return;\r
+       }\r
+       if (uart_circ_empty(xmit)) {\r
+               __stop_tx(up);\r
+               return;\r
+       }\r
+\r
+       count = up->tx_loadsz;\r
+       do {\r
+               serial_out(up, UART_TX, xmit->buf[xmit->tail]);\r
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);\r
+               up->port.icount.tx++;\r
+               if (uart_circ_empty(xmit))\r
+                       break;\r
+       } while (--count > 0);\r
+\r
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
+               uart_write_wakeup(&up->port);\r
+\r
+       DEBUG_INTR("THRE...");\r
+\r
+       if (uart_circ_empty(xmit))\r
+               __stop_tx(up);\r
+}\r
+\r
+static unsigned int check_modem_status(struct uart_rk_port *up)\r
+{\r
+       unsigned int status = serial_in(up, UART_MSR);\r
+\r
+#if 0\r
+       status |= up->msr_saved_flags;\r
+       up->msr_saved_flags = 0;\r
+       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&\r
+           up->port.state != NULL) {\r
+               if (status & UART_MSR_TERI)\r
+                       up->port.icount.rng++;\r
+               if (status & UART_MSR_DDSR)\r
+                       up->port.icount.dsr++;\r
+               if (status & UART_MSR_DDCD)\r
+                       uart_handle_dcd_change(&up->port, status & UART_MSR_DCD);\r
+               if (status & UART_MSR_DCTS)\r
+                       uart_handle_cts_change(&up->port, status & UART_MSR_CTS);\r
+\r
+               wake_up_interruptible(&up->port.state->port.delta_msr_wait);\r
+       }\r
+#endif\r
+\r
+       return status;\r
+}\r
+\r
+\r
+/*\r
+ * This handles the interrupt from one port.\r
+ */\r
+static void serial_rk_handle_port(struct uart_rk_port *up)\r
+{\r
+       unsigned int status;\r
+       unsigned long flags;\r
+       spin_lock_irqsave(&up->port.lock, flags);\r
+\r
+       /* reading UART_LSR can automatically clears PE FE OE bits, except receive fifo error bit*/\r
+       status = serial_in(up, UART_LSR);\r
+\r
+       DEBUG_INTR("status = %x...", status);\r
+       /* DMA mode enable */\r
+       if(up->prk29_uart_dma_t->use_dma == 1) {\r
+\r
+               if(up->iir & UART_IIR_RLSI){\r
+                       if (status & (UART_LSR_DR | UART_LSR_BI)) {\r
+                               up->port_activity = jiffies;\r
+                               up->ier &= ~UART_IER_RLSI;\r
+                               up->ier &= ~UART_IER_RDI;\r
+                               serial_out(up, UART_IER, up->ier);\r
+                               //receive_chars(up, &status);\r
+                               //mod_timer(&up->prk29_uart_dma_t->rx_timer, jiffies +\r
+                               //msecs_to_jiffies(up->prk29_uart_dma_t->rx_timeout));\r
+                               if(serial_rk_start_rx_dma(&up->port) == -1){\r
+                                       receive_chars(up, &status);\r
+                               }\r
+                       }\r
+               }\r
+\r
+       }else {   //dma mode disable\r
+\r
+               /*\r
+                * when uart receive a serial of data which doesn't have stop bit and so on, that causes frame error,and\r
+                * set UART_LSR_RFE to one,what is worse,we couldn't read the data in the receive fifo. So if\r
+                * wo don't clear this bit and reset the receive fifo, the received data available interrupt would\r
+                * occur continuously.  added by hhb@rock-chips.com 2011-08-05\r
+                */\r
+\r
+               if (status & UART_LSR_RFE) {\r
+                       \r
+                       if(up->port.line != DBG_PORT){\r
+                               status = serial_in(up, UART_LSR);\r
+                               dev_info(up->port.dev, "error:lsr=0x%x\n", status);\r
+                       }\r
+                       \r
+                       \r
+               //      rk29_uart_dump_register(up);\r
+               }\r
+\r
+               if (status & (UART_LSR_DR | UART_LSR_BI)) {\r
+                       receive_chars(up, &status);\r
+               }\r
+               check_modem_status(up);\r
+               if (status & UART_LSR_THRE) {\r
+                       transmit_chars(up);\r
+               }\r
+       }\r
+\r
+       spin_unlock_irqrestore(&up->port.lock, flags);\r
+}\r
+\r
+/*\r
+ * This is the serial driver's interrupt routine.\r
+ */\r
+\r
+static irqreturn_t serial_rk_interrupt(int irq, void *dev_id)\r
+{\r
+       struct uart_rk_port *up = dev_id;\r
+       int handled = 0;\r
+       unsigned int iir;\r
+\r
+       iir = serial_in(up, UART_IIR);\r
+\r
+       DEBUG_INTR("%s(%d) iir = 0x%02x\n", __func__, irq, iir);\r
+\r
+       up->iir = iir;\r
+\r
+       if (!(iir & UART_IIR_NO_INT)) {\r
+               serial_rk_handle_port(up);\r
+               handled = 1;\r
+       } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {\r
+\r
+               /* The DesignWare APB UART has an Busy Detect (0x07)\r
+                * interrupt meaning an LCR write attempt occured while the\r
+                * UART was busy. The interrupt must be cleared by reading\r
+                * the UART status register (USR) and the LCR re-written. */\r
+\r
+               if(!(serial_in(up, UART_USR) & UART_USR_BUSY)){\r
+                       serial_out(up, UART_LCR, up->lcr);\r
+               }\r
+               handled = 1;\r
+               dbg("the serial.%d is busy\n", up->port.line);\r
+       }\r
+       DEBUG_INTR("end(%d).\n", handled);\r
+\r
+       return IRQ_RETVAL(handled);\r
+}\r
+\r
+static unsigned int serial_rk_tx_empty(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned long flags;\r
+       unsigned int lsr;\r
+\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+       spin_lock_irqsave(&up->port.lock, flags);\r
+       lsr = serial_in(up, UART_LSR);\r
+       up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;\r
+       spin_unlock_irqrestore(&up->port.lock, flags);\r
+\r
+       return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;\r
+}\r
+\r
+static unsigned int serial_rk_get_mctrl(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned int status;\r
+       unsigned int ret;\r
+\r
+       status = check_modem_status(up);\r
+\r
+       ret = 0;\r
+       if (status & UART_MSR_DCD)\r
+               ret |= TIOCM_CAR;\r
+       if (status & UART_MSR_RI)\r
+               ret |= TIOCM_RNG;\r
+       if (status & UART_MSR_DSR)\r
+               ret |= TIOCM_DSR;\r
+       if (status & UART_MSR_CTS)\r
+               ret |= TIOCM_CTS;\r
+       dev_dbg(port->dev, "%s 0x%08x\n", __func__, ret);\r
+       return ret;\r
+}\r
+\r
+static void serial_rk_set_mctrl(struct uart_port *port, unsigned int mctrl)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned char mcr = 0;\r
+\r
+       dev_dbg(port->dev, "+%s\n", __func__);\r
+       if (mctrl & TIOCM_RTS)\r
+               mcr |= UART_MCR_RTS;\r
+       if (mctrl & TIOCM_DTR)\r
+               mcr |= UART_MCR_DTR;\r
+       if (mctrl & TIOCM_OUT1)\r
+               mcr |= UART_MCR_OUT1;\r
+       if (mctrl & TIOCM_OUT2)\r
+               mcr |= UART_MCR_OUT2;\r
+       if (mctrl & TIOCM_LOOP)\r
+               mcr |= UART_MCR_LOOP;\r
+\r
+       mcr |= up->mcr;\r
+\r
+       serial_out(up, UART_MCR, mcr);\r
+       dev_dbg(port->dev, "-serial.%d %s mcr: 0x%02x\n", port->line, __func__, mcr);\r
+}\r
+\r
+static void serial_rk_break_ctl(struct uart_port *port, int break_state)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned long flags;\r
+\r
+       dev_dbg(port->dev, "+%s\n", __func__);\r
+       spin_lock_irqsave(&up->port.lock, flags);\r
+       if (break_state == -1)\r
+               up->lcr |= UART_LCR_SBC;\r
+       else\r
+               up->lcr &= ~UART_LCR_SBC;\r
+       serial_lcr_write(up, up->lcr);\r
+       spin_unlock_irqrestore(&up->port.lock, flags);\r
+       dev_dbg(port->dev, "-%s lcr: 0x%02x\n", __func__, up->lcr);\r
+}\r
+\r
+/*\r
+ *     Wait for transmitter & holding register to empty\r
+ */\r
+static void wait_for_xmitr(struct uart_rk_port *up, int bits)\r
+{\r
+       unsigned int status, tmout = 10000;\r
+\r
+       /* Wait up to 10ms for the character(s) to be sent. */\r
+       for (;;) {\r
+               status = serial_in(up, UART_LSR);\r
+\r
+               up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;\r
+\r
+               if ((status & bits) == bits)\r
+                       break;\r
+               if (--tmout == 0)\r
+                       break;\r
+               udelay(1);\r
+       }\r
+}\r
+\r
+#ifdef CONFIG_CONSOLE_POLL\r
+/*\r
+ * Console polling routines for writing and reading from the uart while\r
+ * in an interrupt or debug context.\r
+ */\r
+\r
+static int serial_rk_get_poll_char(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned char lsr = serial_in(up, UART_LSR);\r
+\r
+       while (!(lsr & UART_LSR_DR))\r
+               lsr = serial_in(up, UART_LSR);\r
+\r
+       return serial_in(up, UART_RX);\r
+}\r
+\r
+static void serial_rk_put_poll_char(struct uart_port *port,\r
+                        unsigned char c)\r
+{\r
+       unsigned int ier;\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+\r
+       /*\r
+        *      First save the IER then disable the interrupts\r
+        */\r
+       ier = serial_in(up, UART_IER);\r
+       serial_out(up, UART_IER, 0);\r
+\r
+       wait_for_xmitr(up, BOTH_EMPTY);\r
+       /*\r
+        *      Send the character out.\r
+        *      If a LF, also do CR...\r
+        */\r
+       serial_out(up, UART_TX, c);\r
+       if (c == 10) {\r
+               wait_for_xmitr(up, BOTH_EMPTY);\r
+               serial_out(up, UART_TX, 13);\r
+       }\r
+\r
+       /*\r
+        *      Finally, wait for transmitter to become empty\r
+        *      and restore the IER\r
+        */\r
+       wait_for_xmitr(up, BOTH_EMPTY);\r
+       serial_out(up, UART_IER, ier);\r
+}\r
+\r
+#endif /* CONFIG_CONSOLE_POLL */\r
+\r
+static int serial_rk_startup(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned long flags;\r
+       int retval;\r
+\r
+\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+\r
+       /*\r
+        * Allocate the IRQ\r
+        */\r
+       retval = request_irq(up->port.irq, serial_rk_interrupt, up->port.irqflags,\r
+                               up->name, up);\r
+       if (retval)\r
+               return retval;\r
+\r
+       up->mcr = 0;\r
+\r
+       clk_enable(up->clk);  // enable the config uart clock\r
+\r
+       /*\r
+        * Clear the FIFO buffers and disable them.\r
+        * (they will be reenabled in set_termios())\r
+        */\r
+       serial_rk_clear_fifos(up);\r
+\r
+       /*\r
+        * Clear the interrupt registers.\r
+        */\r
+       (void) serial_in(up, UART_LSR);\r
+       (void) serial_in(up, UART_RX);\r
+       (void) serial_in(up, UART_IIR);\r
+       (void) serial_in(up, UART_MSR);\r
+       (void) serial_in(up, UART_USR);\r
+\r
+       /*\r
+        * Now, initialize the UART\r
+        */\r
+       serial_lcr_write(up, UART_LCR_WLEN8 | UART_LCR_EPAR);\r
+\r
+       spin_lock_irqsave(&up->port.lock, flags);\r
+\r
+       /*\r
+        * Most PC uarts need OUT2 raised to enable interrupts.\r
+        */\r
+//     up->port.mctrl |= TIOCM_OUT2;\r
+\r
+       serial_rk_set_mctrl(&up->port, up->port.mctrl);\r
+\r
+       spin_unlock_irqrestore(&up->port.lock, flags);\r
+\r
+       /*\r
+        * Clear the interrupt registers again for luck, and clear the\r
+        * saved flags to avoid getting false values from polling\r
+        * routines or the previous session.\r
+        */\r
+       (void) serial_in(up, UART_LSR);\r
+       (void) serial_in(up, UART_RX);\r
+       (void) serial_in(up, UART_IIR);\r
+       (void) serial_in(up, UART_MSR);\r
+       (void) serial_in(up, UART_USR);\r
+       up->lsr_saved_flags = 0;\r
+#if 0\r
+       up->msr_saved_flags = 0;\r
+#endif\r
+\r
+       if (1 == up->prk29_uart_dma_t->use_dma) {\r
+\r
+               if(up->port.state->xmit.buf != up->prk29_uart_dma_t->tx_buffer){\r
+                       free_page((unsigned long)up->port.state->xmit.buf);\r
+                       up->port.state->xmit.buf = up->prk29_uart_dma_t->tx_buffer;\r
+               }\r
+\r
+#if 1\r
+               serial_rk_start_rx_dma(&up->port);\r
+#else\r
+               up->ier |= UART_IER_RDI;\r
+               up->ier |= UART_IER_RLSI;\r
+               serial_out(up, UART_IER, up->ier);\r
+#endif\r
+               up->port_activity = jiffies;\r
+\r
+       }else{\r
+               up->ier = 0;\r
+               serial_out(up, UART_IER, up->ier);\r
+       }\r
+\r
+       /*\r
+        * Finally, enable interrupts.  Note: Modem status interrupts\r
+        * are set via set_termios(), which will be occurring imminently\r
+        * anyway, so we don't enable them here.\r
+        */\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+static void serial_rk_shutdown(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned long flags;\r
+\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+       /*\r
+        * Disable interrupts from this port\r
+        */\r
+       up->ier = 0;\r
+       serial_out(up, UART_IER, 0);\r
+\r
+       spin_lock_irqsave(&up->port.lock, flags);\r
+//     up->port.mctrl &= ~TIOCM_OUT2;\r
+       serial_rk_set_mctrl(&up->port, up->port.mctrl);\r
+       spin_unlock_irqrestore(&up->port.lock, flags);\r
+\r
+       /*\r
+        * Disable break condition and FIFOs\r
+        */\r
+       serial_lcr_write(up, serial_in(up, UART_LCR) & ~UART_LCR_SBC);\r
+       serial_rk_clear_fifos(up);\r
+\r
+       /*\r
+        * Read data port to reset things, and then free the irq\r
+        */\r
+       (void) serial_in(up, UART_RX);\r
+\r
+       free_irq(up->port.irq, up);\r
+}\r
+\r
+static void\r
+serial_rk_set_termios(struct uart_port *port, struct ktermios *termios,\r
+                     struct ktermios *old)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+       unsigned char cval, fcr = 0;\r
+       unsigned long flags;\r
+       unsigned int baud, quot;\r
+       int timeout = 1000000;\r
+       dev_dbg(port->dev, "+%s\n", __func__);\r
+\r
+       switch (termios->c_cflag & CSIZE) {\r
+       case CS5:\r
+               cval = UART_LCR_WLEN5;\r
+               break;\r
+       case CS6:\r
+               cval = UART_LCR_WLEN6;\r
+               break;\r
+       case CS7:\r
+               cval = UART_LCR_WLEN7;\r
+               break;\r
+       case CS8:\r
+       default:\r
+               cval = UART_LCR_WLEN8;\r
+               break;\r
+       }\r
+\r
+       if (termios->c_cflag & CSTOPB){\r
+               cval |= UART_LCR_STOP;\r
+       }\r
+       if (termios->c_cflag & PARENB){\r
+               cval |= UART_LCR_PARITY;\r
+       }\r
+       if (!(termios->c_cflag & PARODD)){\r
+               cval |= UART_LCR_EPAR;\r
+       }\r
+#ifdef CMSPAR\r
+       if (termios->c_cflag & CMSPAR)\r
+               cval |= UART_LCR_SPAR;\r
+#endif\r
+\r
+\r
+       /*\r
+        * Ask the core to calculate the divisor for us.\r
+        */\r
+       baud = uart_get_baud_rate(port, termios, old,\r
+                                 port->uartclk / 16 / 0xffff,\r
+                                 port->uartclk / 16);\r
+\r
+       quot = uart_get_divisor(port, baud);\r
+\r
+       dev_info(up->port.dev, "baud:%d\n", baud);\r
+//     dev_info(up->port.dev, "quot:%d\n", quot);\r
+\r
+       /*\r
+        * To wait long enough to avoid writting lcr when the uart is busy\r
+        * because of data communication, so that we can set lcr and baud rate\r
+        * successfully. added by hhb@rock-chips.com\r
+        */\r
+\r
+       while(serial_in(up, UART_USR) & UART_USR_BUSY){\r
+               if(--timeout == 0){\r
+                       if(port->line != DBG_PORT){\r
+                               serial_out(up, UART_SRR, UART_RESET);\r
+                       }\r
+                       dbg("rk_serial_set_termios uart.%d timeout,irq=%d,ret=0x%x  AND uart is reseted\n",\r
+                                       port->line, port->irq, serial_in(up, UART_USR));\r
+                       break;\r
+               }\r
+               cpu_relax();\r
+       }\r
+\r
+\r
+       printk("serial.%d timeout:%d\n", up->port.line,timeout);\r
+\r
+\r
+       if (baud < 2400){\r
+               fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;\r
+       }\r
+       else{\r
+               //added by hhb@rock-chips.com\r
+               if(up->prk29_uart_dma_t->use_timer == 1){\r
+                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_01;\r
+               }\r
+               else{\r
+                       fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | UART_FCR_T_TRIG_01;\r
+               }\r
+       }\r
+\r
+       /*\r
+        * MCR-based auto flow control.  When AFE is enabled, RTS will be\r
+        * deasserted when the receive FIFO contains more characters than\r
+        * the trigger, or the MCR RTS bit is cleared.  In the case where\r
+        * the remote UART is not using CTS auto flow control, we must\r
+        * have sufficient FIFO entries for the latency of the remote\r
+        * UART to respond.  IOW, at least 32 bytes of FIFO.\r
+        */\r
+       up->mcr &= ~UART_MCR_AFE;\r
+       if (termios->c_cflag & CRTSCTS){\r
+               up->mcr |= UART_MCR_AFE;\r
+       }\r
+\r
+       /*\r
+        * Ok, we're now changing the port state.  Do it with\r
+        * interrupts disabled.\r
+        */\r
+       spin_lock_irqsave(&up->port.lock, flags);\r
+\r
+       /*\r
+        * Update the per-port timeout.\r
+        */\r
+       uart_update_timeout(port, termios->c_cflag, baud);\r
+\r
+       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;\r
+       if (termios->c_iflag & INPCK)\r
+               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;\r
+       if (termios->c_iflag & (BRKINT | PARMRK))\r
+               up->port.read_status_mask |= UART_LSR_BI;\r
+\r
+       /*\r
+        * Characteres to ignore\r
+        */\r
+       up->port.ignore_status_mask = 0;\r
+       if (termios->c_iflag & IGNPAR)\r
+               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;\r
+       if (termios->c_iflag & IGNBRK) {\r
+               up->port.ignore_status_mask |= UART_LSR_BI;\r
+               /*\r
+                * If we're ignoring parity and break indicators,\r
+                * ignore overruns too (for real raw support).\r
+                */\r
+               if (termios->c_iflag & IGNPAR)\r
+                       up->port.ignore_status_mask |= UART_LSR_OE;\r
+       }\r
+\r
+       /*\r
+        * ignore all characters if CREAD is not set\r
+        */\r
+       if ((termios->c_cflag & CREAD) == 0)\r
+               up->port.ignore_status_mask |= UART_LSR_DR;\r
+\r
+       /*\r
+        * CTS flow control flag and modem status interrupts\r
+        */\r
+       up->ier &= ~UART_IER_MSI;\r
+#if 0\r
+       if (UART_ENABLE_MS(&up->port, termios->c_cflag))\r
+               up->ier |= UART_IER_MSI;\r
+#endif\r
+\r
+       up->lcr = cval;                         /* Save LCR */\r
+       /* set DLAB */\r
+       if(serial_lcr_write(up, cval | UART_LCR_DLAB)){\r
+               dbg("serial.%d set DLAB fail\n", up->port.line);\r
+               serial_out(up, UART_SRR, UART_RESET);\r
+               goto fail;\r
+       }\r
+\r
+       /* set uart baud rate */\r
+       if(serial_dl_write(up, quot)){\r
+               dbg("serial.%d set dll fail\n", up->port.line);\r
+               serial_out(up, UART_SRR, UART_RESET);\r
+               goto fail;\r
+       }\r
+\r
+       /* reset DLAB */\r
+       if(serial_lcr_write(up, cval)){\r
+               dbg("serial.%d reset DLAB fail\n", up->port.line);\r
+               serial_out(up, UART_SRR, UART_RESET);\r
+               goto fail;\r
+       }\r
+       else{\r
+               serial_rk_set_mctrl(&up->port, up->port.mctrl);\r
+               serial_out(up, UART_FCR, fcr);          /* set fcr */\r
+               up->fcr = fcr;\r
+               /* enable the uart interrupt last */\r
+               up->ier |= UART_IER_RDI;\r
+               up->ier |= UART_IER_RLSI;\r
+               serial_out(up, UART_IER, up->ier);\r
+       }\r
+\r
+       spin_unlock_irqrestore(&up->port.lock, flags);\r
+\r
+       /* Don't rewrite B0 */\r
+       if (tty_termios_baud_rate(termios))\r
+               tty_termios_encode_baud_rate(termios, baud, baud);\r
+       dev_dbg(port->dev, "-%s baud %d\n", __func__, baud);\r
+\r
+       return;\r
+\r
+fail:\r
+       spin_unlock_irqrestore(&up->port.lock, flags);\r
+\r
+}\r
+\r
+#if 0\r
+static void\r
+serial_rk_set_ldisc(struct uart_port *port, int new)\r
+{\r
+       if (new == N_PPS) {\r
+               port->flags |= UPF_HARDPPS_CD;\r
+               serial_rk_enable_ms(port);\r
+       } else\r
+               port->flags &= ~UPF_HARDPPS_CD;\r
+}\r
+#endif\r
+\r
+static void\r
+serial_rk_pm(struct uart_port *port, unsigned int state,\r
+             unsigned int oldstate)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+\r
+       dev_dbg(port->dev, "%s: %s\n", __func__, state ? "disable" : "enable");\r
+       if (state)\r
+               clk_disable(up->clk);\r
+       else\r
+               clk_enable(up->clk);\r
+}\r
+\r
+static void serial_rk_release_port(struct uart_port *port)\r
+{\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+}\r
+\r
+static int serial_rk_request_port(struct uart_port *port)\r
+{\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+       return 0;\r
+}\r
+\r
+static void serial_rk_config_port(struct uart_port *port, int flags)\r
+{\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+       port->type = PORT_RK;\r
+}\r
+\r
+static int\r
+serial_rk_verify_port(struct uart_port *port, struct serial_struct *ser)\r
+{\r
+       /* we don't want the core code to modify any port params */\r
+       dev_dbg(port->dev, "%s\n", __func__);\r
+       return -EINVAL;\r
+}\r
+\r
+static const char *\r
+serial_rk_type(struct uart_port *port)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+\r
+       dev_dbg(port->dev, "%s: %s\n", __func__, up->name);\r
+       return up->name;\r
+}\r
+\r
+static struct uart_ops serial_rk_pops = {\r
+       .tx_empty       = serial_rk_tx_empty,\r
+       .set_mctrl      = serial_rk_set_mctrl,\r
+       .get_mctrl      = serial_rk_get_mctrl,\r
+       .stop_tx        = serial_rk_stop_tx,\r
+       .start_tx       = serial_rk_start_tx,\r
+       .stop_rx        = serial_rk_stop_rx,\r
+       .enable_ms      = serial_rk_enable_ms,\r
+       .break_ctl      = serial_rk_break_ctl,\r
+       .startup        = serial_rk_startup,\r
+       .shutdown       = serial_rk_shutdown,\r
+       .set_termios    = serial_rk_set_termios,\r
+#if 0\r
+       .set_ldisc      = serial_rk_set_ldisc,\r
+#endif\r
+       .pm             = serial_rk_pm,\r
+       .type           = serial_rk_type,\r
+       .release_port   = serial_rk_release_port,\r
+       .request_port   = serial_rk_request_port,\r
+       .config_port    = serial_rk_config_port,\r
+       .verify_port    = serial_rk_verify_port,\r
+#ifdef CONFIG_CONSOLE_POLL\r
+       .poll_get_char = serial_rk_get_poll_char,\r
+       .poll_put_char = serial_rk_put_poll_char,\r
+#endif\r
+};\r
+\r
+#ifdef CONFIG_SERIAL_RK_CONSOLE\r
+\r
+static struct uart_rk_port *serial_rk_console_ports[UART_NR];\r
+\r
+static void serial_rk_console_putchar(struct uart_port *port, int ch)\r
+{\r
+       struct uart_rk_port *up =\r
+               container_of(port, struct uart_rk_port, port);\r
+\r
+       wait_for_xmitr(up, UART_LSR_THRE);\r
+       serial_out(up, UART_TX, ch);\r
+}\r
+\r
+/*\r
+ *     Print a string to the serial port trying not to disturb\r
+ *     any possible real use of the port...\r
+ *\r
+ *     The console_lock must be held when we get here.\r
+ */\r
+static void\r
+serial_rk_console_write(struct console *co, const char *s, unsigned int count)\r
+{\r
+       struct uart_rk_port *up = serial_rk_console_ports[co->index];\r
+       unsigned long flags;\r
+       unsigned int ier;\r
+       int locked = 1;\r
+\r
+       touch_nmi_watchdog();\r
+\r
+       local_irq_save(flags);\r
+       if (up->port.sysrq) {\r
+               /* serial_rk_handle_port() already took the lock */\r
+               locked = 0;\r
+       } else if (oops_in_progress) {\r
+               locked = spin_trylock(&up->port.lock);\r
+       } else\r
+               spin_lock(&up->port.lock);\r
+\r
+       /*\r
+        *      First save the IER then disable the interrupts\r
+        */\r
+       ier = serial_in(up, UART_IER);\r
+\r
+       serial_out(up, UART_IER, 0);\r
+\r
+       uart_console_write(&up->port, s, count, serial_rk_console_putchar);\r
+\r
+       /*\r
+        *      Finally, wait for transmitter to become empty\r
+        *      and restore the IER\r
+        */\r
+       wait_for_xmitr(up, BOTH_EMPTY);\r
+       serial_out(up, UART_IER, ier);\r
+\r
+#if 0\r
+       /*\r
+        *      The receive handling will happen properly because the\r
+        *      receive ready bit will still be set; it is not cleared\r
+        *      on read.  However, modem control will not, we must\r
+        *      call it if we have saved something in the saved flags\r
+        *      while processing with interrupts off.\r
+        */\r
+       if (up->msr_saved_flags)\r
+               check_modem_status(up);\r
+#endif\r
+\r
+       if (locked)\r
+               spin_unlock(&up->port.lock);\r
+       local_irq_restore(flags);\r
+}\r
+\r
+static int __init serial_rk_console_setup(struct console *co, char *options)\r
+{\r
+       struct uart_rk_port *up;\r
+       int baud = 115200;\r
+       int bits = 8;\r
+       int parity = 'n';\r
+       int flow = 'n';\r
+\r
+       if (unlikely(co->index >= UART_NR || co->index < 0))\r
+               return -ENODEV;\r
+\r
+       if (serial_rk_console_ports[co->index] == NULL)\r
+               return -ENODEV;\r
+       up = serial_rk_console_ports[co->index];\r
+\r
+       if (options)\r
+               uart_parse_options(options, &baud, &parity, &bits, &flow);\r
+\r
+       return uart_set_options(&up->port, co, baud, parity, bits, flow);\r
+}\r
+\r
+static struct console serial_rk_console = {\r
+       .name           = "ttyS",\r
+       .write          = serial_rk_console_write,\r
+       .device         = uart_console_device,\r
+       .setup          = serial_rk_console_setup,\r
+       .flags          = CON_PRINTBUFFER | CON_ANYTIME,\r
+       .index          = -1,\r
+       .data           = &serial_rk_reg,\r
+};\r
+\r
+static void serial_rk_add_console_port(struct uart_rk_port *up)\r
+{\r
+       serial_rk_console_ports[up->pdev->id] = up;\r
+}\r
+\r
+#define SERIAL_CONSOLE &serial_rk_console\r
+#else\r
+#define SERIAL_CONSOLE NULL\r
+\r
+static inline void serial_rk_add_console_port(struct uart_rk_port *up)\r
+{}\r
+\r
+#endif\r
+\r
+static struct uart_driver serial_rk_reg = {\r
+       .owner                  = THIS_MODULE,\r
+       .driver_name            = "rk29_serial",\r
+       .dev_name               = "ttyS",\r
+       .major                  = TTY_MAJOR,\r
+       .minor                  = 64,\r
+       .cons                   = SERIAL_CONSOLE,\r
+       .nr                     = UART_NR,\r
+};\r
+\r
+static int __devinit serial_rk_probe(struct platform_device *pdev)\r
+{\r
+       struct uart_rk_port     *up;\r
+       struct resource         *mem;\r
+       int irq;\r
+       int ret = -ENOSPC;\r
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+       if (!mem) {\r
+               dev_err(&pdev->dev, "no mem resource?\n");\r
+               return -ENODEV;\r
+       }\r
+\r
+       irq = platform_get_irq(pdev, 0);\r
+       if (irq < 0) {\r
+               dev_err(&pdev->dev, "no irq resource?\n");\r
+               return irq;\r
+       }\r
+\r
+       if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,\r
+                               pdev->dev.driver->name)) {\r
+               dev_err(&pdev->dev, "memory region already claimed\n");\r
+               return -EBUSY;\r
+       }\r
+\r
+       up = kzalloc(sizeof(*up), GFP_KERNEL);\r
+       if (up == NULL) {\r
+               ret = -ENOMEM;\r
+               goto do_release_region;\r
+       }\r
+\r
+       sprintf(up->name, "rk29_serial.%d", pdev->id);\r
+       up->pdev = pdev;\r
+       up->clk = clk_get(&pdev->dev, "uart");\r
+       if (unlikely(IS_ERR(up->clk))) {\r
+               ret = PTR_ERR(up->clk);\r
+               goto do_free;\r
+       }\r
+       up->tx_loadsz = 30;\r
+       up->prk29_uart_dma_t = &rk29_uart_ports_dma_t[pdev->id];\r
+       up->port.dev = &pdev->dev;\r
+       up->port.type = PORT_RK;\r
+       up->port.irq = irq;\r
+       up->port.iotype = UPIO_DWAPB;\r
+\r
+       up->port.regshift = 2;\r
+       up->port.fifosize = 32;\r
+       up->port.ops = &serial_rk_pops;\r
+       up->port.line = pdev->id;\r
+       up->port.iobase = mem->start;\r
+       up->port.membase = ioremap_nocache(mem->start, mem->end - mem->start + 1);\r
+       if (!up->port.membase) {\r
+               ret = -ENOMEM;\r
+               goto do_put_clk;\r
+       }\r
+       up->port.mapbase = mem->start;\r
+       up->port.irqflags = IRQF_DISABLED;\r
+       up->port.uartclk = clk_get_rate(up->clk);\r
+\r
+       /* set dma config */\r
+       if(1 == up->prk29_uart_dma_t->use_dma) {\r
+               pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);\r
+\r
+               //timer\r
+               up->prk29_uart_dma_t->use_timer = USE_TIMER;\r
+               up->prk29_uart_dma_t->rx_timer.function = serial_rk_rx_timeout;\r
+               up->prk29_uart_dma_t->rx_timer.data = (unsigned long)up;\r
+               up->prk29_uart_dma_t->rx_timeout = 7;\r
+               up->prk29_uart_dma_t->rx_timer.expires = jiffies + msecs_to_jiffies(up->prk29_uart_dma_t->rx_timeout);\r
+               init_timer(&up->prk29_uart_dma_t->rx_timer);\r
+               //tx buffer\r
+               up->prk29_uart_dma_t->tx_buffer_size = UART_XMIT_SIZE;\r
+               up->prk29_uart_dma_t->tx_buffer = dmam_alloc_coherent(up->port.dev, up->prk29_uart_dma_t->tx_buffer_size,\r
+                               &up->prk29_uart_dma_t->tx_phy_addr, DMA_MEMORY_MAP);\r
+               if(!up->prk29_uart_dma_t->tx_buffer){\r
+                       dev_info(up->port.dev, "dmam_alloc_coherent dma_tx_buffer fail\n");\r
+               }\r
+               else{\r
+                       dev_info(up->port.dev, "dma_tx_buffer 0x%08x\n", (unsigned) up->prk29_uart_dma_t->tx_buffer);\r
+                       dev_info(up->port.dev, "dma_tx_phy 0x%08x\n", (unsigned) up->prk29_uart_dma_t->tx_phy_addr);\r
+               }\r
+               //rx buffer\r
+               up->prk29_uart_dma_t->rx_buffer_size = UART_XMIT_SIZE*32;\r
+               up->prk29_uart_dma_t->rx_buffer = dmam_alloc_coherent(up->port.dev, up->prk29_uart_dma_t->rx_buffer_size,\r
+                               &up->prk29_uart_dma_t->rx_phy_addr, DMA_MEMORY_MAP);\r
+               up->prk29_uart_dma_t->rb_pre_pos = 0;\r
+               if(!up->prk29_uart_dma_t->rx_buffer){\r
+                       dev_info(up->port.dev, "dmam_alloc_coherent dma_rx_buffer fail\n");\r
+               }\r
+               else {\r
+                       dev_info(up->port.dev, "dma_rx_buffer 0x%08x\n", (unsigned) up->prk29_uart_dma_t->rx_buffer);\r
+                       dev_info(up->port.dev, "up 0x%08x\n", (unsigned)up->prk29_uart_dma_t);\r
+               }\r
+\r
+               // work queue\r
+               INIT_WORK(&up->uart_work, serial_rk_report_revdata_workfunc);\r
+               INIT_WORK(&up->uart_work_rx, serial_rk_start_dma_rx);\r
+               up->uart_wq = create_singlethread_workqueue("uart_workqueue");\r
+               up->prk29_uart_dma_t->rx_dma_start = 0;\r
+               spin_lock_init(&(up->prk29_uart_dma_t->tx_lock));\r
+               spin_lock_init(&(up->prk29_uart_dma_t->rx_lock));\r
+               serial_rk_init_dma_rx(&up->port);\r
+               serial_rk_init_dma_tx(&up->port);\r
+               up->ier |= THRE_MODE;                   // enable THRE interrupt mode\r
+               serial_out(up, UART_IER, up->ier);\r
+       }\r
+\r
+       serial_rk_add_console_port(up);\r
+       ret = uart_add_one_port(&serial_rk_reg, &up->port);\r
+       if (ret != 0)\r
+               goto do_iounmap;\r
+\r
+       platform_set_drvdata(pdev, up);\r
+       dev_info(&pdev->dev, "membase 0x%08x\n", (unsigned) up->port.membase);\r
+\r
+       return 0;\r
+\r
+do_iounmap:\r
+       iounmap(up->port.membase);\r
+       up->port.membase = NULL;\r
+do_put_clk:\r
+       clk_put(up->clk);\r
+do_free:\r
+       kfree(up);\r
+do_release_region:\r
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
+       return ret;\r
+}\r
+\r
+static int __devexit serial_rk_remove(struct platform_device *pdev)\r
+{\r
+       struct uart_rk_port *up = platform_get_drvdata(pdev);\r
+\r
+       platform_set_drvdata(pdev, NULL);\r
+       if (up) {\r
+               struct resource *mem;\r
+               destroy_workqueue(up->uart_wq);\r
+               uart_remove_one_port(&serial_rk_reg, &up->port);\r
+               mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
+               iounmap(up->port.membase);\r
+               up->port.membase = NULL;\r
+               clk_put(up->clk);\r
+               kfree(up);\r
+               release_mem_region(mem->start, (mem->end - mem->start) + 1);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int serial_rk_suspend(struct platform_device *dev, pm_message_t state)\r
+{\r
+       struct uart_rk_port *up = platform_get_drvdata(dev);\r
+\r
+       if (up && up->port.line != DBG_PORT && POWER_MANEGEMENT){\r
+               uart_suspend_port(&serial_rk_reg, &up->port);\r
+       }\r
+       if(up->port.line == DBG_PORT && POWER_MANEGEMENT){\r
+               serial_rk_pm(&up->port, 1, 0);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int serial_rk_resume(struct platform_device *dev)\r
+{\r
+       struct uart_rk_port *up = platform_get_drvdata(dev);\r
+\r
+       if (up && up->port.line != DBG_PORT && POWER_MANEGEMENT){\r
+               uart_resume_port(&serial_rk_reg, &up->port);\r
+       }\r
+       if(up->port.line == DBG_PORT && POWER_MANEGEMENT){\r
+               serial_rk_pm(&up->port, 0, 1);\r
+       }\r
+       return 0;\r
+}\r
+\r
+static struct platform_driver serial_rk_driver = {\r
+       .probe          = serial_rk_probe,\r
+       .remove         = __devexit_p(serial_rk_remove),\r
+       .suspend        = serial_rk_suspend,\r
+       .resume         = serial_rk_resume,\r
+       .driver         = {\r
+#if defined(CONFIG_SERIAL_RK29)\r
+               .name   = "rk29_serial",\r
+#elif defined(CONFIG_SERIAL_RK2818)\r
+               .name   = "rk2818_serial",\r
+#else\r
+               .name   = "rk_serial",\r
+#endif\r
+               .owner  = THIS_MODULE,\r
+       },\r
+};\r
+\r
+static int __init serial_rk_init(void)\r
+{\r
+       int ret;\r
+\r
+       ret = uart_register_driver(&serial_rk_reg);\r
+       if (ret)\r
+               return ret;\r
+\r
+       ret = platform_driver_register(&serial_rk_driver);\r
+       if (ret != 0)\r
+               uart_unregister_driver(&serial_rk_reg);\r
+\r
+       return ret;\r
+}\r
+\r
+static void __exit serial_rk_exit(void)\r
+{\r
+       platform_driver_unregister(&serial_rk_driver);\r
+       uart_unregister_driver(&serial_rk_reg);\r
+}\r
+\r
+module_init(serial_rk_init);\r
+module_exit(serial_rk_exit);\r
+\r
+MODULE_LICENSE("GPL");\r
+MODULE_DESCRIPTION("RK UART driver");\r
+\r
diff --git a/drivers/tty/serial/sc8800.c b/drivers/tty/serial/sc8800.c
new file mode 100755 (executable)
index 0000000..86f6fdf
--- /dev/null
@@ -0,0 +1,692 @@
+/*
+ *
+ *  Copyright (C) 2010 liuyixing <lyx@rock-chips.com>
+ *
+ *
+ * Example platform data:
+
+ static struct plat_sc8800 sc8800_plat_data = {
+        .slav_rts_pin = RK29_PIN4_PD0,
+        .slav_rdy_pin = RK29_PIN4_PD0,
+        .master_rts_pin = RK29_PIN4_PD0,
+        .master_rdy_pin = RK29_PIN4_PD0,
+        //.poll_time = 100,
+ };
+
+ static struct spi_board_info spi_board_info[] = {
+        {
+        .modalias      = "sc8800",
+        .platform_data = &sc8800_plat_data,
+        .max_speed_hz  = 12*1000*1000,
+        .chip_select   = 0,
+        },
+ };
+
+ * The initial minor number is 209 in the low-density serial port:
+ * mknod /dev/ttySPI0 c 204 209
+ */
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/spi/spi.h>
+#include <linux/freezer.h>
+#include <linux/gpio.h>
+
+#include "sc8800.h"
+
+struct sc8800_port {
+       struct uart_port port;
+       struct spi_device *spi;
+
+       int cts;                /* last CTS received for flow ctrl */
+       int tx_empty;           /* last TX empty bit */
+
+       spinlock_t conf_lock;   /* shared data */
+       int conf;               /* configuration for the SC88000
+                                * (bits 0-7, bits 8-11 are irqs) */
+
+       int rx_enabled;         /* if we should rx chars */
+
+       int irq;                /* irq assigned to the sc8800 */
+
+       int minor;              /* minor number */
+       int loopback;           /* 1 if we are in loopback mode */
+
+       /* for handling irqs: need workqueue since we do spi_sync */
+       struct workqueue_struct *workqueue;
+       struct work_struct work;
+       /* set to 1 to make the workhandler exit as soon as possible */
+       int  force_end_work;
+       /* need to know we are suspending to avoid deadlock on workqueue */
+       int suspending;
+
+       /* hook for suspending SC8800 via dedicated pin */
+       void (*sc8800_hw_suspend) (int suspend);
+
+       /* poll time (in ms) for ctrl lines */
+       int poll_time;
+       /* and its timer */
+       struct timer_list       timer;
+
+       /*signal define, always gpio*/
+       int slav_rts;
+       int slav_rdy;
+       int master_rts;
+       int master_rdy;
+};
+
+#define SC8800_MAJOR 204
+#define SC8800_MINOR 209
+#define MAX_SC8800 1
+
+#define SPI_MAX_PACKET (8192-128)
+#define FREAM_SIZE 64
+#define SPI_DMA_SIZE PAGE_SIZE
+
+void * g_dma_buffer = NULL;
+dma_addr_t g_dma_addr;
+
+#if 1
+#define sc8800_dbg(x...) printk(x)
+#else
+#define sc8800_dbg(x...)
+#endif
+
+static struct sc8800_port *sc8800s[MAX_SC8800]; /* the chips */
+static DEFINE_MUTEX(sc8800s_lock);                /* race on probe */
+
+static int sc8800_get_slave_rts_status(struct sc8800_port *s)
+{
+       return gpio_get_value(s->slav_rts);
+}
+
+static int sc8800_get_slave_rdy_status(struct sc8800_port *s)
+{
+       return gpio_get_value(s->slav_rdy);
+}
+
+static void sc8800_set_master_rts_status(struct sc8800_port *s, int value)
+{
+       gpio_set_value(s->master_rts, value);
+}
+
+static void sc8800_set_master_rdy_status(struct sc8800_port *s, int value)
+{
+       gpio_set_value(s->master_rdy, value);
+}
+
+static int sc8800_send_head_data(struct sc8800_port *s, u32 data_len)
+{
+       char head[64] = {0};
+       struct spi_message message;
+       int status;
+       struct spi_transfer tran;
+
+       head[0] = 0x7f;
+       head[1] = 0x7e;
+       head[2] = 0x55;
+       head[3] = 0xaa;
+       head[4] = data_len & 0xff;
+       head[5] = (data_len>>8) & 0xff;
+       head[6] = (data_len>>16) & 0xff;
+       head[7] = (data_len>>24) & 0xff;
+       
+       tran.tx_buf = (void *)(head);
+       tran.len = FREAM_SIZE;
+       
+       spi_message_init(&message);
+       spi_message_add_tail(&tran, &message);
+       status = spi_sync(s->spi, &message);
+       if (status) {
+               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
+               return -EIO;
+       }
+       
+       return 0;
+}
+static int sc8800_recv_and_parse_head_data(struct sc8800_port *s, u32 *len)
+{
+       struct spi_message message;
+       int status;
+       struct spi_transfer tran;
+       char buf[64] = {0};
+       u32 data_len = 0;
+               
+       tran.rx_buf = (void *)buf;
+       tran.len = FREAM_SIZE;
+       
+       spi_message_init(&message);
+       spi_message_add_tail(&tran, &message);
+       status = spi_sync(s->spi, &message);
+       if (status) {
+               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
+               return -EIO;
+       }
+
+       if ((buf[0]!=0x7f) || (buf[1]!=0x7e) || (buf[2]!=0x55) || (buf[3]!=0xaa)) {
+               dev_warn(&s->spi->dev, "line %d, error head data", __LINE__);
+               return -EIO;
+       }
+       
+       data_len = buf[5] + (buf[6]<<8) + (buf[7]<<16) + (buf[8]<<24);
+
+       *len = data_len;
+       
+       sc8800_dbg("line %d, %d data need to read\n", __LINE__, *len);
+       
+       return 0;
+}
+
+static int sc8800_send_data(struct sc8800_port *s, char *buf, int len)
+{
+#if 1
+       int status;
+       struct spi_message message;
+       struct spi_transfer tran;
+       
+       tran.tx_buf = (void *)buf;
+       tran.len = len;
+       
+       spi_message_init(&message);
+       spi_message_add_tail(&tran, &message);
+       status = spi_sync(s->spi, &message);
+       if (status) {
+               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
+               return -EIO;
+       }
+#else
+       int status;
+       struct spi_message message;
+       struct spi_transfer tran;
+
+       spi_message_init(&message);
+       
+       if (!g_dma_buffer) {
+               g_dma_buffer = dma_alloc_coherent(NULL, SPI_DMA_SIZE, &g_dma_addr, GFP_KERNEL | GFP_DMA);
+               if (!g_dma_buffer) {
+                       dev_err(&s->spi->dev, "alloc dma memory fail\n");
+               }
+       }
+
+       if (!g_dma_buffer) {    //nomal
+               sc8800_dbg("send data nomal");
+               tran.tx_buf = (void *)buf;
+               tran.len = len;
+       }
+       else {  //dma   
+               //message.is_dma_mapped = 1;
+               //memcpy(g_dma_buffer, buf, );
+       }
+
+       spi_message_add_tail(&tran, &message);
+       status = spi_sync(s->spi, &message);
+       if (status) {
+               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
+               return -EIO;
+       }
+#endif
+
+       return 0;
+}
+
+static int sc8800_recv_data(struct sc8800_port *s, char *buf, int len)
+{
+       struct spi_message message;
+       int status;
+       struct spi_transfer tran;
+       
+       tran.rx_buf = (void *)buf;
+       tran.len = len;
+       
+       spi_message_init(&message);
+       spi_message_add_tail(&tran, &message);
+       status = spi_sync(s->spi, &message);
+       if (status) {
+               dev_warn(&s->spi->dev, "error while calling spi_sync\n");
+               return -EIO;
+       }
+       
+       return 0;
+}
+
+static void sc8800_work(struct work_struct *w);
+
+static void sc8800_dowork(struct sc8800_port *s)
+{
+       if (!s->force_end_work && !work_pending(&s->work) &&
+           !freezing(current) && !s->suspending)
+               queue_work(s->workqueue, &s->work);
+}
+
+static void sc8800_timeout(unsigned long data)
+{
+       struct sc8800_port *s = (struct sc8800_port *)data;
+
+       if (s->port.state) {
+               sc8800_dowork(s);
+               mod_timer(&s->timer, jiffies + s->poll_time);
+       }
+}
+
+static void sc8800_work(struct work_struct *w)
+{
+       struct sc8800_port *s = container_of(w, struct sc8800_port, work);
+       struct circ_buf *xmit = &s->port.state->xmit;
+       u32 len,i;
+       char *buf = NULL;
+       unsigned char ch;
+       
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+
+       if (sc8800_get_slave_rts_status(s) == GPIO_HIGH) {      //do wirte, master--->slave
+               if (sc8800_get_slave_rdy_status(s) == GPIO_HIGH) {      /*1.check slave rdy, must be high*/
+                       if (!(uart_circ_empty(xmit))) {
+                               len = uart_circ_chars_pending(xmit);
+                               len = (len > SPI_MAX_PACKET) ? SPI_MAX_PACKET : len;
+                               sc8800_dbg("send data length = %d\n", len);
+                               
+                               sc8800_set_master_rts_status(s, GPIO_LOW);      /*2.set master rts low*/
+                               sc8800_send_head_data(s,len);   /*3.send 64byte head data*/
+                               while (sc8800_get_slave_rdy_status(s)) {        /*4.check slav rdy, wait for low */
+                                       msleep(1);
+                               }
+                               
+                               /*5.long data transmit*/
+                               sc8800_send_data(s, xmit->buf+xmit->tail, len);
+                               
+                               while(sc8800_get_slave_rdy_status(s)==GPIO_LOW) {       /*6.wait for slave rdy high*/
+                                       msleep(1);
+                               }
+
+                               sc8800_set_master_rts_status(s, GPIO_HIGH);     /*end transmit, set master rts high*/
+                               xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);
+                               s->port.icount.tx += len;
+                       }
+               }
+               else {  //slave not ready, do it next time
+                       queue_work(s->workqueue, &s->work);
+               }                       
+       }
+       else {  //do read, slave--->master
+               sc8800_set_master_rdy_status(s, GPIO_LOW);
+               sc8800_recv_and_parse_head_data(s, &len);
+
+               buf = (char *)kzalloc(len, GFP_KERNEL);
+               if (!buf) {
+                       dev_err(&s->spi->dev, "line %d, err while malloc mem\n", __LINE__);
+                       sc8800_set_master_rdy_status(s, GPIO_HIGH);
+                       return ;
+               }
+               memset(buf, 0, len);
+               sc8800_recv_data(s, buf, len);
+               
+               while (sc8800_get_slave_rts_status(s) == GPIO_LOW) {
+                       msleep(1);
+               }
+               sc8800_set_master_rdy_status(s, GPIO_HIGH);
+
+               for (i=0; i<len; i++) {
+                       ch = buf[i];            
+                       uart_insert_char(&s->port, 0, 0, ch, TTY_NORMAL);
+               }
+               tty_flip_buffer_push(s->port.state->port.tty);
+       }
+}
+
+static irqreturn_t sc8800_irq(int irqno, void *dev_id)
+{
+       struct sc8800_port *s = dev_id;
+
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+
+       sc8800_dowork(s);
+       return IRQ_HANDLED;
+}
+
+static void sc8800_enable_ms(struct uart_port *port)
+{
+       struct sc8800_port *s = container_of(port,
+                                             struct sc8800_port,
+                                             port);
+
+       if (s->poll_time > 0)
+               mod_timer(&s->timer, jiffies);
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+}
+
+static void sc8800_start_tx(struct uart_port *port)
+{
+       struct sc8800_port *s = container_of(port,
+                                             struct sc8800_port,
+                                             port);
+
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+       
+       sc8800_dowork(s);
+}
+
+static void sc8800_stop_rx(struct uart_port *port)
+{
+       struct sc8800_port *s = container_of(port,
+                                             struct sc8800_port,
+                                             port);
+
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+
+       s->rx_enabled = 0;
+
+       sc8800_dowork(s);
+}
+
+static void sc8800_shutdown(struct uart_port *port)
+{
+       struct sc8800_port *s = container_of(port,
+                                             struct sc8800_port,
+                                             port);
+
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+
+       if (s->suspending)
+               return;
+
+       s->force_end_work = 1;
+
+       if (s->poll_time > 0)
+               del_timer_sync(&s->timer);
+
+       if (s->workqueue) {
+               flush_workqueue(s->workqueue);
+               destroy_workqueue(s->workqueue);
+               s->workqueue = NULL;
+       }
+       if (s->irq)
+               free_irq(s->irq, s);
+
+       gpio_free(s->master_rdy);
+       gpio_free(s->master_rts);
+       gpio_free(s->slav_rdy);
+       gpio_free(s->slav_rts);
+
+       /* set shutdown mode to save power */
+       if (s->sc8800_hw_suspend)
+               s->sc8800_hw_suspend(1);
+}
+
+static int sc8800_startup(struct uart_port *port)
+{
+       struct sc8800_port *s = container_of(port,
+                                             struct sc8800_port,
+                                             port);
+       int ret;
+       char b[12];
+
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+
+       s->rx_enabled = 1;
+
+       if (s->suspending)
+               return 0;
+       
+       s->force_end_work = 0;
+       
+       sprintf(b, "sc8800-%d", s->minor);
+       s->workqueue = create_freezeable_workqueue(b);
+       if (!s->workqueue) {
+               dev_warn(&s->spi->dev, "cannot create workqueue\n");
+               return -EBUSY;
+       }
+       INIT_WORK(&s->work, sc8800_work);
+
+       ret = gpio_request(s->slav_rts, "slav rts");
+       if (ret) {
+               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
+               ret = -EBUSY;
+               goto gpio_err1;
+       }
+       ret = gpio_request(s->slav_rdy, "slav rdy");
+       if (ret) {
+               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
+               ret = -EBUSY;
+               goto gpio_err2;
+       }
+       ret = gpio_request(s->master_rts, "master rts");
+       if (ret) {
+               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
+               ret = -EBUSY;
+               goto gpio_err3;
+       }
+       ret = gpio_request(s->master_rdy, "master rdy");
+       if (ret) {
+               dev_err(&s->spi->dev, "line %d: gpio request err\n", __LINE__);
+               ret = -EBUSY;
+               goto gpio_err4;
+       }
+
+       gpio_direction_input(s->slav_rts);
+       gpio_pull_updown(s->slav_rts, GPIOPullUp);
+       gpio_direction_input(s->slav_rdy);
+       gpio_pull_updown(s->slav_rdy, GPIOPullUp);
+       gpio_direction_output(s->master_rts, GPIO_HIGH);
+       gpio_direction_output(s->master_rdy, GPIO_HIGH);
+       
+       if (request_irq(s->irq, sc8800_irq,
+                       IRQF_TRIGGER_FALLING, "sc8800", s) < 0) {
+               dev_warn(&s->spi->dev, "cannot allocate irq %d\n", s->irq);
+               s->irq = 0;
+               goto irq_err;
+       }
+
+       if (s->sc8800_hw_suspend)
+               s->sc8800_hw_suspend(0);
+       
+       sc8800_dowork(s);
+
+       sc8800_enable_ms(&s->port);
+
+       return 0;
+       
+irq_err:
+       gpio_free(s->master_rdy);
+gpio_err4:
+       gpio_free(s->master_rts);
+gpio_err3:
+       gpio_free(s->slav_rdy);
+gpio_err2:
+       gpio_free(s->slav_rts);
+gpio_err1:
+       destroy_workqueue(s->workqueue);
+       s->workqueue = NULL;    
+       return ret;
+
+}
+
+static struct uart_ops sc8800_ops = {
+       .start_tx       = sc8800_start_tx,
+       .stop_rx        = sc8800_stop_rx,
+       .startup        = sc8800_startup,
+       .shutdown       = sc8800_shutdown,
+};
+
+static struct uart_driver sc8800_uart_driver = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "ttySPI",
+       .dev_name       = "ttySPI",
+       .major          = SC8800_MAJOR,
+       .minor          = SC8800_MINOR,
+       .nr             = MAX_SC8800,
+};
+static int uart_driver_registered;
+
+static int __devinit sc8800_probe(struct spi_device *spi)
+{
+       int i, retval;
+       struct plat_sc8800 *pdata;
+       
+       mutex_lock(&sc8800s_lock);
+
+       if (!uart_driver_registered) {
+               uart_driver_registered = 1;
+               retval = uart_register_driver(&sc8800_uart_driver);
+               if (retval) {
+                       printk(KERN_ERR "Couldn't register sc8800 uart driver\n");
+                       mutex_unlock(&sc8800s_lock);
+                       return retval;
+               }
+       }
+
+       for (i = 0; i < MAX_SC8800; i++)
+               if (!sc8800s[i])
+                       break;
+       if (i == MAX_SC8800) {
+               dev_warn(&spi->dev, "too many SC8800 chips\n");
+               mutex_unlock(&sc8800s_lock);
+               return -ENOMEM;
+       }
+
+       sc8800s[i] = kzalloc(sizeof(struct sc8800_port), GFP_KERNEL);
+       if (!sc8800s[i]) {
+               dev_warn(&spi->dev,
+                        "kmalloc for sc8800 structure %d failed!\n", i);
+               mutex_unlock(&sc8800s_lock);
+               return -ENOMEM;
+       }
+       sc8800s[i]->spi = spi;
+       spin_lock_init(&sc8800s[i]->conf_lock);
+       dev_set_drvdata(&spi->dev, sc8800s[i]);
+       pdata = spi->dev.platform_data;
+       sc8800s[i]->irq = gpio_to_irq(pdata->slav_rts_pin);
+       sc8800s[i]->slav_rts = pdata->slav_rts_pin;
+       sc8800s[i]->slav_rdy = pdata->slav_rdy_pin;
+       sc8800s[i]->master_rts = pdata->master_rts_pin;
+       sc8800s[i]->master_rdy = pdata->master_rdy_pin;
+       //sc8800s[i]->sc8800_hw_suspend = pdata->sc8800_hw_suspend;
+       sc8800s[i]->minor = i;
+       init_timer(&sc8800s[i]->timer);
+       sc8800s[i]->timer.function = sc8800_timeout;
+       sc8800s[i]->timer.data = (unsigned long) sc8800s[i];
+
+       dev_dbg(&spi->dev, "%s: adding port %d\n", __func__, i);
+       sc8800s[i]->port.irq = sc8800s[i]->irq;
+       sc8800s[i]->port.uartclk = 24000000;
+       sc8800s[i]->port.fifosize = 64;
+       sc8800s[i]->port.ops = &sc8800_ops;
+       sc8800s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+       sc8800s[i]->port.line = i;
+       sc8800s[i]->port.dev = &spi->dev;
+       retval = uart_add_one_port(&sc8800_uart_driver, &sc8800s[i]->port);
+       if (retval < 0)
+               dev_warn(&spi->dev,
+                        "uart_add_one_port failed for line %d with error %d\n",
+                        i, retval);
+
+       /* set shutdown mode to save power. Will be woken-up on open */
+       if (sc8800s[i]->sc8800_hw_suspend)
+               sc8800s[i]->sc8800_hw_suspend(1);
+
+       mutex_unlock(&sc8800s_lock);
+       return 0;
+}
+
+static int __devexit sc8800_remove(struct spi_device *spi)
+{
+       struct sc8800_port *s = dev_get_drvdata(&spi->dev);
+       int i;
+
+       mutex_lock(&sc8800s_lock);
+
+       /* find out the index for the chip we are removing */
+       for (i = 0; i < MAX_SC8800; i++)
+               if (sc8800s[i] == s)
+                       break;
+
+       dev_dbg(&spi->dev, "%s: removing port %d\n", __func__, i);
+       uart_remove_one_port(&sc8800_uart_driver, &sc8800s[i]->port);
+       kfree(sc8800s[i]);
+       sc8800s[i] = NULL;
+
+       /* check if this is the last chip we have */
+       for (i = 0; i < MAX_SC8800; i++)
+               if (sc8800s[i]) {
+                       mutex_unlock(&sc8800s_lock);
+                       return 0;
+               }
+       pr_debug("removing sc8800 driver\n");
+       uart_unregister_driver(&sc8800_uart_driver);
+
+       mutex_unlock(&sc8800s_lock);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int sc8800_suspend(struct spi_device *spi, pm_message_t state)
+{
+       struct sc8800_port *s = dev_get_drvdata(&spi->dev);
+
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+
+       disable_irq(s->irq);
+
+       s->suspending = 1;
+       uart_suspend_port(&sc8800_uart_driver, &s->port);
+
+       if (s->sc8800_hw_suspend)
+               s->sc8800_hw_suspend(1);
+
+       return 0;
+}
+
+static int sc8800_resume(struct spi_device *spi)
+{
+       struct sc8800_port *s = dev_get_drvdata(&spi->dev);
+
+       dev_dbg(&s->spi->dev, "%s\n", __func__);
+
+       if (s->sc8800_hw_suspend)
+               s->sc8800_hw_suspend(0);
+       uart_resume_port(&sc8800_uart_driver, &s->port);
+       s->suspending = 0;
+
+       enable_irq(s->irq);
+
+       if (s->workqueue)
+               sc8800_dowork(s);
+
+       return 0;
+}
+
+#else
+#define sc8800_suspend NULL
+#define sc8800_resume  NULL
+#endif
+
+static struct spi_driver sc8800_driver = {
+       .driver = {
+               .name           = "sc8800",
+               .bus            = &spi_bus_type,
+               .owner          = THIS_MODULE,
+       },
+
+       .probe          = sc8800_probe,
+       .remove         = __devexit_p(sc8800_remove),
+       .suspend        = sc8800_suspend,
+       .resume         = sc8800_resume,
+};
+
+static int __init sc8800_init(void)
+{
+       return spi_register_driver(&sc8800_driver);
+}
+module_init(sc8800_init);
+
+static void __exit sc8800_exit(void)
+{
+       spi_unregister_driver(&sc8800_driver);
+}
+module_exit(sc8800_exit);
+
+MODULE_DESCRIPTION("SC8800 driver");
+MODULE_AUTHOR("liuyixing <lyx@rock-chips.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:SC8800");
diff --git a/drivers/tty/serial/sc8800.h b/drivers/tty/serial/sc8800.h
new file mode 100755 (executable)
index 0000000..b425cb4
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __SC8800_H__\r
+#define __SC8800_H__\r
+\r
+typedef struct _spi_packet_head {\r
+       u16 tag; //HEADER_TAG(0x7e7f) \r
+       u16 type; //HEADER_TYPE(0xaa55) \r
+       u32 length; //the length of data after head  (8192-128 bytes) \r
+       u32 frame_num; //no used , always 0\r
+       u32 reserved2; //reserved \r
+} SPI_PACKET_HEAD_T;\r
+\r
+\r
+/*define flatform data struct*/\r
+struct plat_sc8800 {\r
+       int slav_rts_pin;\r
+       int slav_rdy_pin;\r
+       int master_rts_pin;\r
+       int master_rdy_pin;\r
+       int poll_time;\r
+};\r
+\r
+#endif\r
index 30ddf8dc4f72ed139b381d7389bc9b9bfc322c34..906a9666d75265ad65430701657fff1f49aecc60 100644 (file)
@@ -50,4 +50,5 @@ obj-$(CONFIG_USB_SPEEDTOUCH)  += atm/
 obj-$(CONFIG_USB_MUSB_HDRC)    += musb/
 obj-$(CONFIG_USB_RENESAS_USBHS)        += renesas_usbhs/
 obj-$(CONFIG_USB_OTG_UTILS)    += otg/
+obj-$(CONFIG_DWC_OTG)          += dwc_otg/
 obj-$(CONFIG_USB_GADGET)       += gadget/
old mode 100755 (executable)
new mode 100644 (file)
index 4516712..8706fc9
@@ -1009,6 +1009,7 @@ static int __init usb_init(void)
                pr_info("%s: USB support disabled\n", usbcore_name);
                return 0;
        }
+
        retval = usb_debugfs_init();
        if (retval)
                goto out;
index 69bbadf593987d06c315d40fc0bb182c80b73dba..6540e720b47d56f31945ea5039bd571aa0423df1 100755 (executable)
@@ -2373,8 +2373,13 @@ int dwc_otg_hcd_hub_control(struct usb_hcd *_hcd,
                desc->wHubCharacteristics = 0x08;
                desc->bPwrOn2PwrGood = 1;
                desc->bHubContrCurrent = 0;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+               desc->u.hs.DeviceRemovable[0] = 0;
+               desc->u.hs.DeviceRemovable[1] = 0xff;
+#else
                desc->bitmap[0] = 0;
                desc->bitmap[1] = 0xff;
+#endif
                break;
        case GetHubStatus:
                DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - "
index 8eb9face90966b2bad5704308c33651a277abda0..e5c08d1af2691acea5b5f9a74199873995896c9f 100755 (executable)
@@ -1963,14 +1963,23 @@ void dwc_otg_pcd_remove( struct device *dev )
  * @param _driver The driver being registered
  */
  
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+int usb_gadget_probe_driver(struct usb_gadget_driver *_driver,
+               int (*bind)(struct usb_gadget *))
+#else
 int usb_gadget_register_driver(struct usb_gadget_driver *_driver)
+#endif
 {
        int retval;
 
        DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", _driver->driver.name);
                
        if (!_driver || _driver->speed == USB_SPEED_UNKNOWN || 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+               !bind ||
+#else
                !_driver->bind || 
+#endif
                !_driver->unbind || 
                !_driver->disconnect || 
                !_driver->setup) 
@@ -1994,7 +2003,11 @@ int usb_gadget_register_driver(struct usb_gadget_driver *_driver)
        s_pcd->gadget.dev.driver = &_driver->driver;
 
        DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", _driver->driver.name);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+       retval = bind(&s_pcd->gadget);
+#else
        retval = _driver->bind(&s_pcd->gadget);
+#endif
        if (retval) 
        {
                DWC_ERROR("bind to driver %s --> error %d\n",
@@ -2007,8 +2020,11 @@ int usb_gadget_register_driver(struct usb_gadget_driver *_driver)
                                        _driver->driver.name);
        return 0;
 }
-
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+#else
 EXPORT_SYMBOL(usb_gadget_register_driver);
+#endif
 
 /**
  * This function unregisters a gadget driver
index 144a8c863b3424d90eaf3c34c0baa83421eb30e1..30ce90921f4b306af30abf4a5c4d7062e3791894 100644 (file)
@@ -112,6 +112,7 @@ config      USB_GADGET_SELECTED
 choice
        prompt "USB Peripheral Controller"
        depends on USB_GADGET
+       default USB_GADGET_DWC_OTG
        help
           A USB device uses a controller to talk to its host.
           Systems should have only one such upstream link.
@@ -543,6 +544,19 @@ config USB_LANGWELL
        default USB_GADGET
        select USB_GADGET_SELECTED
 
+config USB_GADGET_DWC_OTG
+       boolean "Synopsys DWC OTG Controller"
+       select USB_GADGET_DUALSPEED
+       help
+         This driver provides USB Device Controller support for the
+         Synopsys DesignWare USB OTG Core used on the Rockchip RK28.
+
+config USB_DWC_OTG
+       tristate
+       depends on USB_GADGET_DWC_OTG
+       default USB_GADGET
+       select USB_GADGET_SELECTED
+
 config USB_GADGET_EG20T
        boolean "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
        depends on PCI
@@ -641,9 +655,9 @@ config USB_GADGET_DUALSPEED
 # USB Gadget Drivers
 #
 choice
-       tristate "USB Gadget Drivers"
+       bool "USB Gadget Drivers"
        depends on USB_GADGET && USB_GADGET_SELECTED
-       default USB_ETH
+       default USB_G_ANDROID
        help
          A Linux "Gadget Driver" talks to the USB Peripheral Controller
          driver through the abstract "gadget" API.  Some other operating
index b13633bb684aa9ed675b26a164dc1335933aefd5..fbfdc8a4e195771d67b5b76faba01c0648637a35 100644 (file)
@@ -64,8 +64,8 @@ MODULE_VERSION("1.0");
 static const char longname[] = "Gadget Android";
 
 /* Default vendor and product IDs, overridden by userspace */
-#define VENDOR_ID              0x18D1
-#define PRODUCT_ID             0x0001
+#define VENDOR_ID              0x2207//0x18D1
+#define PRODUCT_ID             0x2910
 
 struct android_usb_function {
        char *name;
index fe4455e50d10a0096d08fcb0af1c5f45729479ac..9855ad55dcabd4cec54ef0d92f2be7425a3dda04 100644 (file)
@@ -72,7 +72,7 @@ static struct usb_endpoint_descriptor adb_highspeed_in_desc = {
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_IN,
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
-       .wMaxPacketSize         = __constant_cpu_to_le16(512),
+       .wMaxPacketSize         = __constant_cpu_to_le16(64),
 };
 
 static struct usb_endpoint_descriptor adb_highspeed_out_desc = {
index 5440c6d8fc30a39acf739d22b6fe160ab21175e4..4d477b2b84d56ab6377f745091441c5976f804fd 100644 (file)
 #include "gadget_chips.h"
 
 
+#ifdef CONFIG_ARCH_RK29
+/* flush after every 4 meg of writes to avoid excessive block level caching */
+#define MAX_UNFLUSHED_BYTES  (64 * 1024)// (4 * 1024 * 1024) //original value is 4MB,Modifyed by xbw at 2011-08-18
+#define MAX_UNFLUSHED_PACKETS 4//16
+
+#include <linux/power_supply.h>
+#include <linux/reboot.h>
+#include <linux/syscalls.h>
+
+static int usb_msc_connected;  /*usb charge status*/
+
+static void set_msc_connect_flag( int connected )
+{
+       printk("%s status = %d 20101216\n" , __func__, connected);
+       if( usb_msc_connected == connected )
+               return;
+       usb_msc_connected = connected;//usb mass storage is ok
+}
+
+int get_msc_connect_flag( void )
+{
+       return usb_msc_connected;
+}
+EXPORT_SYMBOL(get_msc_connect_flag);
+#endif
+
 /*------------------------------------------------------------------------*/
 
 #define FSG_DRIVER_DESC                "Mass Storage Function"
@@ -797,6 +823,13 @@ static int do_read(struct fsg_common *common)
                        amount = min(amount, (unsigned int)PAGE_CACHE_SIZE -
                                             partial_page);
 
+               /* kever@rk
+                * max size for dwc_otg ctonroller is 64(max pkt sizt) * 1023(pkt)
+                * because of the DOEPTSIZ.PKTCNT has only 10 bits
+                */
+               if((common->gadget->speed != USB_SPEED_HIGH)&&(amount >0x8000))
+                   amount = 0x8000;
+
                /* Wait for the next buffer to become available */
                bh = common->next_buffhd_to_fill;
                while (bh->state != BUF_STATE_EMPTY) {
@@ -975,6 +1008,13 @@ static int do_write(struct fsg_common *common)
                        amount_left_to_req -= amount;
                        if (amount_left_to_req == 0)
                                get_some_more = 0;
+                               
+                       /* kever@rk
+                        * max size for dwc_otg ctonroller is 64(max pkt sizt) * 1023(pkt)
+                        * because of the DOEPTSIZ.PKTCNT has only 10 bits
+                        */
+                       if((common->gadget->speed != USB_SPEED_HIGH)&&(amount >0x8000))
+                           amount = 0x8000;
 
                        /*
                         * amount is always divisible by 512, hence by
@@ -1040,6 +1080,15 @@ static int do_write(struct fsg_common *common)
                        amount_left_to_write -= nwritten;
                        common->residue -= nwritten;
 
+#ifdef MAX_UNFLUSHED_PACKETS
+                       curlun->unflushed_packet ++;
+                       curlun->unflushed_bytes += nwritten;
+                       if( (curlun->unflushed_packet >= MAX_UNFLUSHED_PACKETS) || (curlun->unflushed_bytes >= MAX_UNFLUSHED_BYTES)) {
+                               fsg_lun_fsync_sub(curlun);
+                               curlun->unflushed_packet = 0;
+                               curlun->unflushed_bytes = 0;
+                       }
+#endif
                        /* If an error occurred, report it and its position */
                        if (nwritten < amount) {
                                curlun->sense_data = SS_WRITE_ERROR;
@@ -1940,6 +1989,153 @@ static int check_command(struct fsg_common *common, int cmnd_size,
        return 0;
 }
 
+#ifdef CONFIG_ARCH_RK29
+static void deferred_restart(struct work_struct *dummy)
+{
+       sys_sync();
+       kernel_restart("loader");
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+typedef struct tagLoaderParam
+{
+       int     tag;
+       int     length;
+       char    parameter[1];
+       int     crc;
+} PARM_INFO;
+#define PARM_TAG                       0x4D524150
+#define MSC_EXT_DBG                    1
+extern int  GetParamterInfo(char * pbuf , int len);
+
+/* the buf is bh->buf,it is large enough. */
+static char * get_param_tag( char* buf , const char* tag )
+{
+       PARM_INFO       *pi;
+       int             i;
+       char            *pp = buf+256;
+       char            *spp;
+       i = GetParamterInfo( pp , 1024 );
+       pi = (PARM_INFO*)pp;
+       if( pi->tag != PARM_TAG ){
+error_out:     
+               printk("paramter error,tag=0x%x\n" , pi->tag );
+               return NULL;
+       }
+       if( pi->length+sizeof(PARM_INFO) > i ) {
+               GetParamterInfo( pp , pi->length+sizeof(PARM_INFO)  + 511 );
+       }
+       pp = strstr( pi->parameter , tag );
+       if( !pp ) goto error_out;
+       pp += strlen(tag); // sizeof "MACHINE_MODEL:"
+       while( *pp == ' ' || *pp == '\t' ) {
+               if(pp - pi->parameter >= pi->length)
+                 break;        
+               pp++;
+       }
+       spp = pp;
+       while( *pp != 0x0d && *pp != 0x0a ) {
+               if(pp - pi->parameter >= pi->length)
+                 break;
+               pp++;
+       }
+       *pp = 0;
+       if( spp == pp ) return NULL;
+       return spp;
+}
+
+static int do_get_product_name(int ret ,char *buf)
+{
+       char            *tag = "MACHINE_MODEL:";
+       char            *pname;
+       #if MSC_EXT_DBG
+       char            tbuf[1300];
+       if( buf == NULL )   buf = tbuf;
+       #endif
+       memset( buf , 0 , ret );
+       pname = get_param_tag( buf , tag );
+       if( pname ){
+               strcpy( buf , pname);
+       } 
+       #if MSC_EXT_DBG
+       printk("%s%s\n" , tag , buf );
+       #endif
+       return ret;
+}
+
+static int do_get_versions( int ret ,char* buf )
+{
+       /* get boot version and fireware version from cmdline
+       * bootver=2010-07-08#4.02 firmware_ver=1.0.0 // Firmware Ver:16.01.0000
+       * return format: 0x02 0x04 0x00 0x00 0x00 0x01 
+       * RK29: bootver=2011-07-18#2.05 firmware_ver=0.2.3 (==00.02.0003)
+       * for the old loader,the firmware_ver may be empty,so get the fw ver from paramter.
+       */
+#define ASC_BCD0( c )  (((c-'0'))&0xf)
+#define ASC_BCD1( c )  (((c-'0')<<4)&0xf0)
+
+       char *ver = buf;
+       char *p_l , *p_f;
+       char            *l_tag = "bootver=";
+       char            *fw_tag = "FIRMWARE_VER:";
+       
+       #if MSC_EXT_DBG
+       char            tbuf[1300];
+       if( ver == NULL )   ver = tbuf;
+       #endif
+       
+       memset( ver , 0x00 , ret );
+       p_l = strstr( saved_command_line , l_tag );
+       if( !p_l ) {
+               return ret;
+       } 
+       p_l+=strlen( l_tag );
+       if( (p_l = strchr( p_l,'#')) ) {
+               p_l++;
+               if( p_l[1] == '.' ) {
+                       ver[1] = ASC_BCD0(p_l[0]);
+                       p_l+=2;
+               } else {
+                       ver[1] = ASC_BCD1(p_l[0])|ASC_BCD0(p_l[1]);
+                       p_l+=3;
+               }
+               ver[0] = ASC_BCD1(p_l[0])|ASC_BCD0(p_l[1]);
+       }
+       
+       p_f = get_param_tag( ver , fw_tag );
+       if( !p_f ) return ret;
+       
+       if( p_f[1] == '.' ) {
+               ver[5] = ASC_BCD0(p_f[0]);
+               p_f+=2;
+       } else {
+               ver[5] = ASC_BCD1(p_f[0])|ASC_BCD0(p_f[1]);
+               p_f+=3;
+       } 
+       if( p_f[1] == '.' ) {
+               ver[4] = ASC_BCD0(p_f[0]);
+               p_f+=2;
+       } else {
+               ver[4] = ASC_BCD1(p_f[0])|ASC_BCD0(p_f[1]);
+               p_f+=3;
+       } 
+       ver[2] = ASC_BCD0(p_f[0]);
+       p_f++;
+       if( p_f[0] != ' ' ){
+               ver[2] |= ASC_BCD1(p_f[0]);
+               p_f++;
+       }
+       // only support 2 byte version.
+       ver[3] = 0;
+
+       #if MSC_EXT_DBG
+       printk("VERSION:%02x %02x %02x %02x %02x %02x\n" , 
+               ver[0],ver[1],ver[2],ver[3],ver[4],ver[5]);
+       #endif
+       return ret;
+}
+#endif
+
 static int do_scsi_command(struct fsg_common *common)
 {
        struct fsg_buffhd       *bh;
@@ -1947,6 +2143,9 @@ static int do_scsi_command(struct fsg_common *common)
        int                     reply = -EINVAL;
        int                     i;
        static char             unknown[16];
+#ifdef CONFIG_ARCH_RK29
+       struct fsg_common       *fsg = common;
+#endif
 
        dump_cdb(common);
 
@@ -2137,7 +2336,11 @@ static int do_scsi_command(struct fsg_common *common)
                                      (1<<1) | (0xf<<2) | (3<<7), 1,
                                      "VERIFY");
                if (reply == 0)
+#ifdef CONFIG_ARCH_RK29
+                       reply = 0; //zyf 20100302
+#else
                        reply = do_verify(common);
+#endif
                break;
 
        case WRITE_6:
@@ -2193,6 +2396,26 @@ unknown_cmnd:
                        reply = -EINVAL;
                }
                break;
+#ifdef CONFIG_ARCH_RK29
+       case 0xff:
+               if( fsg->cmnd[1] != 0xe0 ||
+                   fsg->cmnd[2] != 0xff || fsg->cmnd[3] != 0xff ||
+                   fsg->cmnd[4] != 0xff )
+                   break;
+               if (fsg->cmnd_size >= 6 && fsg->cmnd[5] == 0xfe) {
+                       schedule_work(&restart_work);
+               }
+               else if ( fsg->cmnd[5] == 0xf3 ) {
+                       fsg->data_size_from_cmnd = fsg->data_size;
+               /* get product name from parameter section */
+                       reply = do_get_product_name( fsg->data_size,bh->buf );
+               }
+               else if ( fsg->cmnd[5] == 0xff ){
+                       fsg->data_size_from_cmnd = fsg->data_size;
+                       reply = do_get_versions( fsg->data_size,bh->buf ); 
+               }
+               break;
+#endif
        }
        up_read(&common->filesem);
 
@@ -2450,6 +2673,8 @@ static void fsg_disable(struct usb_function *f)
        struct fsg_dev *fsg = fsg_from_func(f);
        fsg->common->new_fsg = NULL;
        raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+       // yk 201009
+       set_msc_connect_flag(0);
 }
 
 
@@ -3178,3 +3403,131 @@ fsg_common_from_params(struct fsg_common *common,
        return fsg_common_init(common, cdev, &cfg);
 }
 
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+
+#ifdef CONFIG_ARCH_RK29
+static enum power_supply_property usb_props[] = {
+//     POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int usb_get_property(struct power_supply *psy,
+                               enum power_supply_property psp,
+                                       union power_supply_propval *val)
+{
+       int ret = 0;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+#ifndef CONFIG_DWC_OTG_HOST_ONLY
+               val->intval = get_msc_connect_flag();
+#else
+               val->intval = 0;
+#endif
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return ret;
+}
+
+static int usb_power_supply_register(struct device* parent)
+{
+       struct power_supply *ps;
+       int retval = 0;
+
+       ps = kzalloc(sizeof(*ps), GFP_KERNEL);
+       if (!ps) {
+               dev_err(parent, "failed to allocate power supply data\n");
+               retval = -ENOMEM;
+               goto out;
+       }
+       ps->name = "usb";
+       ps->type = POWER_SUPPLY_TYPE_USB;
+       ps->properties = usb_props;
+       ps->num_properties = ARRAY_SIZE(usb_props);
+       ps->get_property = usb_get_property;
+       ps->external_power_changed = NULL;
+       retval = power_supply_register(parent, ps);
+       if (retval) {
+               dev_err(parent, "failed to register battery\n");
+               goto out;
+       }
+out:
+       return retval;
+}
+#endif
+
+static struct fsg_config fsg_cfg;
+
+static int fsg_probe(struct platform_device *pdev)
+{
+       struct usb_mass_storage_platform_data *pdata = pdev->dev.platform_data;
+       int i, nluns;
+
+       printk(KERN_INFO "fsg_probe pdev: %p, pdata: %p\n", pdev, pdata);
+       if (!pdata)
+               return -1;
+
+       nluns = pdata->nluns;
+       if (nluns > FSG_MAX_LUNS)
+               nluns = FSG_MAX_LUNS;
+       fsg_cfg.nluns = nluns;
+       for (i = 0; i < nluns; i++)
+               fsg_cfg.luns[i].removable = 1;
+
+       fsg_cfg.vendor_name = pdata->vendor;
+       fsg_cfg.product_name = pdata->product;
+       fsg_cfg.release = pdata->release;
+       fsg_cfg.can_stall = 0;
+       fsg_cfg.pdev = pdev;
+
+#ifdef CONFIG_ARCH_RK29
+{
+       /*
+        * Initialize usb power supply
+        */
+       int retval = usb_power_supply_register(&pdev->dev);
+       if (retval != 0) {
+               dev_err(&pdev->dev, "usb_power_supply_register failed\n");
+       }
+
+       return retval;
+}
+#else
+       return 0;
+#endif
+}
+
+static struct platform_driver fsg_platform_driver = {
+       .driver = { .name = FUNCTION_NAME, },
+       .probe = fsg_probe,
+};
+
+int mass_storage_bind_config(struct usb_configuration *c)
+{
+       struct fsg_common *common = fsg_common_init(NULL, c->cdev, &fsg_cfg);
+       if (IS_ERR(common))
+               return -1;
+       return fsg_add(c->cdev, c, common);
+}
+
+static struct android_usb_function mass_storage_function = {
+       .name = FUNCTION_NAME,
+       .bind_config = mass_storage_bind_config,
+};
+
+static int __init init(void)
+{
+       int             rc;
+       printk(KERN_INFO "f_mass_storage init\n");
+       rc = platform_driver_register(&fsg_platform_driver);
+       if (rc != 0)
+               return rc;
+       android_register_function(&mass_storage_function);
+       return 0;
+}module_init(init);
+
+#endif /* CONFIG_USB_ANDROID_MASS_STORAGE */
+
index a872248f37df9cc4c4b95566d65c66b37954694e..618b3f076c1f394c75f5214d93afcfa6e12e2474 100644 (file)
@@ -233,6 +233,10 @@ struct fsg_lun {
        struct file     *filp;
        loff_t          file_length;
        loff_t          num_sectors;
+#ifdef MAX_UNFLUSHED_PACKETS
+       unsigned int    unflushed_packet;
+       unsigned int    unflushed_bytes;
+#endif
 
        unsigned int    initially_ro:1;
        unsigned int    ro:1;
@@ -763,6 +767,9 @@ static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
        struct rw_semaphore     *filesem = dev_get_drvdata(dev);
        int             rc = 0;
 
+#ifdef CONFIG_ARCH_RK29
+       printk("store_file: \"%s\"\n", buf);
+#endif
 
 #ifndef CONFIG_USB_ANDROID_MASS_STORAGE
        /* disabled in android because we need to allow closing the backing file
index 60b25d8ea0e2c14376ee4fad71d21a680f0502f7..8cf88aa5c8f4158b52a5779ee355573e0b978a3b 100644 (file)
@@ -309,6 +309,7 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_CDMA_TECH                  0xfffe
 #define ZTE_PRODUCT_AC8710                     0xfff1
 #define ZTE_PRODUCT_AC2726                     0xfff5
+#define ZTE_PRODUCT_AC100                      0x0094
 #define ZTE_PRODUCT_AC8710T                    0xffff
 
 #define BENQ_VENDOR_ID                         0x04a5
@@ -394,6 +395,13 @@ static void option_instat_callback(struct urb *urb);
 #define CINTERION_PRODUCT_EU3_P                        0x0052
 #define CINTERION_PRODUCT_PH8                  0x0053
 
+/* Thinkwill products */
+#define THINKWILL_VENDOR_ID    0x19f5
+#define THINKWILL_PRODUCT_ID   0x9909
+#define        THINKWILL_MI900_PRODUCT_ID      0x9013
+
+#define CINTERION_VENDOR_ID                    0x0681
+
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID                     0x0b3c
 #define OLIVETTI_PRODUCT_OLICARD100            0xc000
@@ -412,6 +420,13 @@ static void option_instat_callback(struct urb *urb);
 #define SAMSUNG_VENDOR_ID                       0x04e8
 #define SAMSUNG_PRODUCT_GT_B3730                0x6889
 
+/* leadcore LC1808*/
+#define LEADCORE_VENDOR_ID     0x1ab7
+#define LEADCORE_PRODUCT_LC1808        0x2200
+/*展讯模组*/
+#define SC8800G_VENDOR_ID      0x067b
+#define SC8800G_PRODUCT_ID     0x2303
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -448,6 +463,10 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = {
 
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+       { USB_DEVICE(THINKWILL_VENDOR_ID,THINKWILL_PRODUCT_ID)},
+
+       { USB_DEVICE(THINKWILL_VENDOR_ID,THINKWILL_MI900_PRODUCT_ID)},
+
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
@@ -477,6 +496,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
        { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
        { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
+       { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600)},
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
@@ -936,6 +956,11 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xFFED, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xFFFE, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xFFEB, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xF006, 0xff, 0xff, 0xff) },
+       { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_AC100)},
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
@@ -989,6 +1014,35 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
 
+       { USB_DEVICE(LEADCORE_VENDOR_ID, LEADCORE_PRODUCT_LC1808) },  //zzc
+       { USB_DEVICE(SC8800G_VENDOR_ID,SC8800G_PRODUCT_ID)},
+       { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+       { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+
+// cmy:
+       { USB_DEVICE(0x0685, 0x6000) },
+       { USB_DEVICE(0x1E89, 0x1E16) },
+       { USB_DEVICE(0x7693, 0x0001) },
+       { USB_DEVICE(0x1D09, 0x4308) },
+       { USB_DEVICE(0x1234, 0x0033) },
+       { USB_DEVICE(0xFEED, 0x0001) },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, 0x0017) },
+       { USB_DEVICE(0x1C9E, 0x9E00) },
+       { USB_DEVICE(0x1C9E, 0xF000) },
+       { USB_DEVICE(0x19D2, 0x1303) },
+       { USB_DEVICE(0x19F5, 0x9013) }, // MW100
+       { USB_DEVICE(0x21F5, 0x2008) },
+       { USB_DEVICE(0x12D1, 0x1D09) },
+       { USB_DEVICE(0x04CC, 0x2259) },
+       { USB_DEVICE(0x04CC, 0x226E) },
+       { USB_DEVICE(0x04CC, 0x225A) },
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0015) },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b7) },
+       { USB_DEVICE(ZTE_VENDOR_ID, 0xFFFF) },
+       { USB_DEVICE(LEADCORE_VENDOR_ID, 0x5700) },
+       { USB_DEVICE(LEADCORE_VENDOR_ID, 0x6341) },
+
+       { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) },
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
        { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
old mode 100755 (executable)
new mode 100644 (file)
index 3b14863a0f241a38004de65ac586233940a1634c..f9a3eec2d5580aa32488dcd954c4fa84c6ab153c 100755 (executable)
@@ -183,6 +183,7 @@ static int rk29_backlight_probe(struct platform_device *pdev)
        }
 
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_RAW;
        props.max_brightness = BL_STEP;
        rk29_bl = backlight_device_register("rk28_bl", &pdev->dev, rk29_bl_info, &rk29_bl_ops, &props);
        if (!rk29_bl) {
index d4c6eb248ff997893499a13dd2d824fe4abebabc..cea8e23f093709e763fefa835631e801c604c69f 100755 (executable)
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/pdata.h>
 #include <linux/mfd/wm831x/regulator.h>
-
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/delay.h>
+#include <linux/ktime.h>
+#define BL_SET   255
+#define BL_MISC_VALUE 20
+#define BL_INIT_VALUE 102
 struct wm831x_backlight_data {
        struct wm831x *wm831x;
        int isink_reg;
        int current_brightness;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct  early_suspend early_suspend;
+       struct delayed_work work;
+       int suspend_flag;
+       int shutdown_flag;
+#endif
 };
-
+#define TS_POLL_DELAY (10000*1000*1000)
+int wm831x_bright = 0;
+int max_tp = 0;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static struct backlight_device *gwm831x_bl;
+static struct wm831x_backlight_data *gwm831x_data;
+#endif
 static int wm831x_backlight_set(struct backlight_device *bl, int brightness)
 {
        struct wm831x_backlight_data *data = bl_get_data(bl);
        struct wm831x *wm831x = data->wm831x;
-       int power_up = !data->current_brightness && brightness;
-       int power_down = data->current_brightness && !brightness;
+//     int power_up = !data->current_brightness && brightness;
+//     int power_down = data->current_brightness && !brightness;
+       int power_up;
+       int power_down;
        int ret;
+       int bright_tp;
 
+       bright_tp =( max_tp*brightness)/BL_SET;
+       power_up =!data->current_brightness && bright_tp;
+       power_down = data->current_brightness && !bright_tp;
        if (power_up) {
                /* Enable the ISINK */
                ret = wm831x_set_bits(wm831x, data->isink_reg,
@@ -63,7 +88,7 @@ static int wm831x_backlight_set(struct backlight_device *bl, int brightness)
 
        /* Set the new brightness */
        ret = wm831x_set_bits(wm831x, data->isink_reg,
-                             WM831X_CS1_ISEL_MASK, brightness);
+                             WM831X_CS1_ISEL_MASK, bright_tp);
        if (ret < 0)
                goto err;
 
@@ -94,7 +119,21 @@ err:
 static int wm831x_backlight_update_status(struct backlight_device *bl)
 {
        int brightness = bl->props.brightness;
+       if (brightness<=BL_MISC_VALUE) {
+               brightness = 8*brightness;
+       }
+       else if (brightness<=BL_INIT_VALUE) {
+               brightness = 31*brightness/41 + 145;
+       }
+       else {
+               brightness = 33*brightness/153 + 200;
+       }
 
+       if(gwm831x_data->suspend_flag == 1)
+               brightness = 0;
+       if (gwm831x_data->shutdown_flag == 1)
+               brightness = 0;
+               
        if (bl->props.power != FB_BLANK_UNBLANK)
                brightness = 0;
 
@@ -104,6 +143,8 @@ static int wm831x_backlight_update_status(struct backlight_device *bl)
        if (bl->props.state & BL_CORE_SUSPENDED)
                brightness = 0;
 
+       printk("backlight brightness=%d\n", brightness);
+
        return wm831x_backlight_set(bl, brightness);
 }
 
@@ -118,6 +159,40 @@ static const struct backlight_ops wm831x_backlight_ops = {
        .update_status  = wm831x_backlight_update_status,
        .get_brightness = wm831x_backlight_get_brightness,
 };
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void wm831x_bl_work(struct work_struct *work)
+{
+       //struct wm831x_backlight_data *wm831x_data = container_of(work, struct wm831x_backlight_data,
+                                                  //work.work);
+       backlight_update_status(gwm831x_bl);
+}
+
+static void wm831x_bl_suspend(struct early_suspend *h)
+{
+       struct wm831x_backlight_data *wm831x_data;
+       wm831x_data = container_of(h, struct wm831x_backlight_data, early_suspend);
+       wm831x_data->suspend_flag = 1;
+
+       schedule_delayed_work(&wm831x_data->work, msecs_to_jiffies(100));               
+}
+
+
+static void wm831x_bl_resume(struct early_suspend *h)
+{
+       struct wm831x_backlight_data *wm831x_data;
+       wm831x_data = container_of(h, struct wm831x_backlight_data, early_suspend);
+       wm831x_data->suspend_flag = 0;
+       
+       schedule_delayed_work(&wm831x_data->work, msecs_to_jiffies(100));
+}
+
+#endif
+
+int rk29_backlight_ctrl(int open)
+{
+       gwm831x_data->suspend_flag = !open;
+       schedule_delayed_work(&gwm831x_data->work, 0);
+}
 
 static int wm831x_backlight_probe(struct platform_device *pdev)
 {
@@ -153,7 +228,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
                return -EINVAL;
        }
        max_isel = i - 1;
-
+       max_tp = max_isel;
        if (pdata->max_uA != wm831x_isinkv_values[max_isel])
                dev_warn(&pdev->dev,
                         "Maximum current is %duA not %duA as requested\n",
@@ -194,7 +269,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
        data->isink_reg = isink_reg;
 
        props.type = BACKLIGHT_RAW;
-       props.max_brightness = max_isel;
+       props.max_brightness = BL_SET;
        bl = backlight_device_register("wm831x", &pdev->dev, data,
                                       &wm831x_backlight_ops, &props);
        if (IS_ERR(bl)) {
@@ -203,15 +278,26 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
                return PTR_ERR(bl);
        }
 
-       bl->props.brightness = max_isel;
+       bl->props.brightness = BL_INIT_VALUE;
 
        platform_set_drvdata(pdev, bl);
 
+#ifdef CONFIG_HAS_EARLYSUSPEND 
+       data->early_suspend.level = ~0x0;
+       data->early_suspend.suspend = wm831x_bl_suspend;
+       data->early_suspend.resume = wm831x_bl_resume;
+       register_early_suspend(&data->early_suspend);
+       INIT_DELAYED_WORK(&data->work, wm831x_bl_work);
+       gwm831x_bl = bl;
+       gwm831x_data = data;
+#endif
+
+
        /* Disable the DCDC if it was started so we can bootstrap */
        wm831x_set_bits(wm831x, WM831X_DCDC_ENABLE, WM831X_DC4_ENA, 0);
 
-
-       backlight_update_status(bl);
+       //backlight_update_status(bl);
+       schedule_delayed_work(&data->work, msecs_to_jiffies(100));
 
        return 0;
 }
@@ -222,10 +308,24 @@ static int wm831x_backlight_remove(struct platform_device *pdev)
        struct wm831x_backlight_data *data = bl_get_data(bl);
 
        backlight_device_unregister(bl);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       unregister_early_suspend(&data->early_suspend);
+#endif 
        kfree(data);
        return 0;
 }
 
+static void wm831x_backlight_shutdown(struct platform_device *pdev)
+{
+       struct backlight_device *bl = platform_get_drvdata(pdev);
+       struct wm831x_backlight_data *data = bl_get_data(bl);
+       
+       printk("enter %s\n", __func__);
+       data->shutdown_flag = 1;
+       wm831x_backlight_update_status(bl);
+       return;
+}
+
 static struct platform_driver wm831x_backlight_driver = {
        .driver         = {
                .name   = "wm831x-backlight",
@@ -233,6 +333,7 @@ static struct platform_driver wm831x_backlight_driver = {
        },
        .probe          = wm831x_backlight_probe,
        .remove         = wm831x_backlight_remove,
+       .shutdown       = wm831x_backlight_shutdown,
 };
 
 static int __init wm831x_backlight_init(void)
index dc563788fa896c5f54ad244621161637f3663496..723aa9abbf523adbe1b4f439d7e1737f9382c74c 100644 (file)
@@ -98,7 +98,7 @@ next:
 
        *bh = sb_bread(sb, phys);
        if (*bh == NULL) {
-               fat_msg(sb, KERN_ERR, "Directory bread(block %llu) failed",
+               fat_msg(sb, KERN_DEBUG, "Directory bread(block %llu) failed",
                       (llu)phys);
                /* skip this block */
                *pos = (iblock + 1) << sb->s_blocksize_bits;
index 2e81ac0df7e2eae4b30ad9b2e1db360798f92b2c..38cfeb1908a352077f7c3e9ede42ee221b926d2e 100644 (file)
@@ -95,7 +95,7 @@ static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
 err_brelse:
        brelse(bhs[0]);
 err:
-       fat_msg(sb, KERN_ERR, "FAT read failed (blocknr %llu)", (llu)blocknr);
+       fat_msg(sb, KERN_DEBUG, "FAT read failed (blocknr %llu)", (llu)blocknr);
        return -EIO;
 }
 
@@ -108,7 +108,7 @@ static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
        fatent->fat_inode = MSDOS_SB(sb)->fat_inode;
        fatent->bhs[0] = sb_bread(sb, blocknr);
        if (!fatent->bhs[0]) {
-               fat_msg(sb, KERN_ERR, "FAT read failed (blocknr %llu)",
+               fat_msg(sb, KERN_DEBUG, "FAT read failed (blocknr %llu)",
                       (llu)blocknr);
                return -EIO;
        }
index 9836839e0eb4c063b2e875c8d7cb8c74337e173d..e5d4e9bc0bae4d76ad0dfbf4decac561f965edeb 100644 (file)
@@ -1282,7 +1282,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
        sb_min_blocksize(sb, 512);
        bh = sb_bread(sb, 0);
        if (bh == NULL) {
-               fat_msg(sb, KERN_ERR, "unable to read boot sector");
+               fat_msg(sb, KERN_DEBUG, "unable to read boot sector");
                goto out_fail;
        }
 
@@ -1348,7 +1348,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
                }
                bh = sb_bread(sb, 0);
                if (bh == NULL) {
-                       fat_msg(sb, KERN_ERR, "unable to read boot sector"
+                       fat_msg(sb, KERN_DEBUG, "unable to read boot sector"
                               " (logical sector size = %lu)",
                               sb->s_blocksize);
                        goto out_fail;
index d1643df2c381b89e92b403a09e12732b39a91aac..9420e6ffbf920276bd3dece88e79e4d47fbaee99 100644 (file)
@@ -149,8 +149,13 @@ int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
        if (local_data)
                yaffs_release_temp_buffer(dev, data, __LINE__);
 
+#ifdef CONFIG_MTD_NAND_RK29
+       //dxj 20101221@ if return -EBADMSG then i think the page is badchunk so just set the eccResult=YAFFS_ECC_RESULT_NO_ERROR
+       if (tags && retval == -EBADMSG) {
+#else
        if (tags && retval == -EBADMSG
            && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
+#endif
                tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
                dev->n_ecc_unfixed++;
        }
index d5b875314005a36afe115ba7abd656bf6b3eff39..1fbb7fc246c9cf637a2a63e77fcf5ae6ebc886cb 100644 (file)
@@ -2217,6 +2217,9 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        param->n_reserved_blocks = 5;
        param->n_caches = (options.no_cache) ? 0 : 10;
        param->inband_tags = options.inband_tags;
+#if defined(CONFIG_ARCH_RK2818) || defined(CONFIG_ARCH_RK29)
+       param->inband_tags = 1;
+#endif
 
 #ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
        param->disable_lazy_load = 1;
index c2ccc3e4311bcbe240f481062deb82dfd13dd8c3..cb4089254f01feb22fa7db68841f81e7e6b2569c 100644 (file)
@@ -86,8 +86,6 @@ struct vm_area_struct;
 #define __GFP_NO_KSWAPD        ((__force gfp_t)___GFP_NO_KSWAPD)
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
 
-#define __GFP_NO_KSWAPD        ((__force gfp_t)0x400000u)
-
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
  * allocations that simply cannot be supported (e.g. page tables).
old mode 100755 (executable)
new mode 100644 (file)
index a6c652e..584a700
@@ -61,6 +61,17 @@ extern int i2c_master_send(const struct i2c_client *client, const char *buf,
 extern int i2c_master_recv(const struct i2c_client *client, char *buf,
                           int count);
 
+#if defined (CONFIG_I2C_RK2818) || defined(CONFIG_I2C_RK29)
+/* If everything went ok, return 'count' transmitted, else error code. */
+extern int i2c_master_normal_send(const struct i2c_client *client, const char *buf, int count, int scl_rate);
+extern int i2c_master_normal_recv(const struct i2c_client *client, char *buf, int count, int scl_rate);
+extern int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate);
+extern int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate);
+extern int i2c_master_reg16_send(const struct i2c_client *client, const short regs, const short *buf, int count, int scl_rate);
+extern int i2c_master_reg16_recv(const struct i2c_client *client, const short regs, short *buf, int count, int scl_rate);
+extern int i2c_suspended(struct i2c_adapter *adap);
+#endif
+
 /* Transfer num messages.
  */
 extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
@@ -208,6 +219,7 @@ struct i2c_client {
        struct i2c_driver *driver;      /* and our access routines      */
        struct device dev;              /* the device structure         */
        int irq;                        /* irq issued by device         */
+       int udelay;
        struct list_head detected;
 };
 #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@@ -259,6 +271,7 @@ struct i2c_board_info {
        struct dev_archdata     *archdata;
        struct device_node *of_node;
        int             irq;
+       int             udelay;   //add by kfx
 };
 
 /**
@@ -517,8 +530,13 @@ struct i2c_msg {
 #define I2C_M_IGNORE_NAK       0x1000  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_NO_RD_ACK                0x0800  /* if I2C_FUNC_PROTOCOL_MANGLING */
 #define I2C_M_RECV_LEN         0x0400  /* length will be first received byte */
+#define I2C_M_NEED_DELAY       0x0020  // add by kfx
+#define I2C_M_REG8_DIRECT      0x0040  // add by kfx
        __u16 len;              /* msg length                           */
        __u8 *buf;              /* pointer to msg data                  */
+       __u32 scl_rate;  // add by kfx
+       int udelay;             //add by kfx
+       __u16 read_type;
 };
 
 /* To determine what functionality is present */
diff --git a/include/linux/i2c/tps65910.h b/include/linux/i2c/tps65910.h
deleted file mode 100644 (file)
index 3127470..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/* linux/i2c/tps65910.h
- *
- *  TPS65910 Power Management Device Definitions.
- *
- * Based on include/linux/i2c/twl.h
- *
- * Copyright (C) 2010 Mistral Solutions Pvt Ltd <www.mistralsolutions.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __LINUX_I2C_TPS65910_H
-#define __LINUX_I2C_TPS65910_H
-
-#define TPS65910_NUM_SLAVES    1
-/* I2C Slave Address 7-bit */
-#define        TPS65910_I2C_ID0        0x2D /* general-purpose */
-#define        TPS65910_I2C_ID1        0x12 /* Smart Reflex */
-
-/* TPS65910 to host IRQ */
-#define TPS65910_HOST_IRQ      RK29_PIN4_PD3
-
-/* TPS65910 MAX GPIOs */
-#define TPS65910_GPIO_MAX      1
-
-/*
- * ----------------------------------------------------------------------------
- * Registers, all 8 bits
- * ----------------------------------------------------------------------------
- */
-#define        TPS65910_REG_SECONDS            0x00
-#define TPS65910_REG_MINUTES           0x01
-#define TPS65910_REG_HOURS             0x02
-#define TPS65910_REG_DAYS              0x03
-#define TPS65910_REG_MONTHS            0x04
-#define TPS65910_REG_YEARS             0x05
-#define TPS65910_REG_WEEKS             0x06
-#define TPS65910_REG_ALARM_SECONDS     0x08
-#define TPS65910_REG_ALARM_MINUTES     0x09
-#define TPS65910_REG_ALARM_HOURS       0x0A
-#define TPS65910_REG_ALARM_DAYS                0x0B
-#define TPS65910_REG_ALARM_MONTHS      0x0C
-#define TPS65910_REG_ALARM_YEARS       0x0D
-
-#define TPS65910_REG_RTC_CTRL          0x10
-#define TPS65910_REG_RTC_STATUS                0x11
-#define TPS65910_REG_RTC_INTERRUPTS    0x12
-#define TPS65910_REG_RTC_COMP_LSB      0x13
-#define TPS65910_REG_RTC_COMP_MSB      0x14
-#define TPS65910_REG_RTC_RES_PROG      0x15
-#define TPS65910_REG_RTC_RESET_STATUS  0x16
-#define TPS65910_REG_BCK1              0x17
-#define TPS65910_REG_BCK2              0x18
-#define TPS65910_REG_BCK3              0x19
-#define TPS65910_REG_BCK4              0x1A
-#define TPS65910_REG_BCK5              0x1B
-#define TPS65910_REG_PUADEN            0x1C
-#define TPS65910_REG_REF               0x1D
-#define TPS65910_REG_VRTC              0x1E
-
-#define TPS65910_REG_VIO               0x20
-#define TPS65910_REG_VDD1              0x21
-#define TPS65910_REG_VDD1_OP           0x22
-#define TPS65910_REG_VDD1_SR           0x23
-#define TPS65910_REG_VDD2              0x24
-#define TPS65910_REG_VDD2_OP           0x25
-#define TPS65910_REG_VDD2_SR           0x26
-#define TPS65910_REG_VDD3              0x27
-
-#define TPS65910_REG_VDIG1             0x30
-#define TPS65910_REG_VDIG2             0x31
-#define TPS65910_REG_VAUX1             0x32
-#define TPS65910_REG_VAUX2             0x33
-#define TPS65910_REG_VAUX33            0x34
-#define TPS65910_REG_VMMC              0x35
-#define TPS65910_REG_VPLL              0x36
-#define TPS65910_REG_VDAC              0x37
-#define TPS65910_REG_THERM             0x38
-#define TPS65910_REG_BBCH              0x39
-
-#define TPS65910_REG_DCDCCTRL          0x3E
-#define TPS65910_REG_DEVCTRL           0x3F
-#define TPS65910_REG_DEVCTRL2          0x40
-#define TPS65910_REG_SLEEP_KEEP_LDO_ON 0x41
-#define TPS65910_REG_SLEEP_KEEP_RES_ON 0x42
-#define TPS65910_REG_SLEEP_SET_LDO_OFF 0x43
-#define TPS65910_REG_SLEEP_SET_RES_OFF 0x44
-#define TPS65910_REG_EN1_LDO_ASS       0x45
-#define TPS65910_REG_EN1_SMPS_ASS      0x46
-#define TPS65910_REG_EN2_LDO_ASS       0x47
-#define TPS65910_REG_EN2_SMPS_ASS      0x48
-#define TPS65910_REG_EN3_LDO_ASS       0x49
-#define TPS65910_REG_SPARE             0x4A
-
-#define TPS65910_REG_INT_STS           0x50
-#define TPS65910_REG_INT_MSK           0x51
-#define TPS65910_REG_INT_STS2          0x52
-#define TPS65910_REG_INT_MSK2          0x53
-#define TPS65910_REG_INT_STS3          0x54
-#define TPS65910_REG_INT_MSK3          0x55
-
-#define TPS65910_REG_GPIO0             0x60
-
-#define TPS65910_REG_JTAGVERNUM                0x80
-
-/* TPS65910 GPIO Specific flags */
-#define TPS65910_GPIO_INT_FALLING      0
-#define TPS65910_GPIO_INT_RISING       1
-
-#define TPS65910_DEBOUNCE_91_5_MS      0
-#define TPS65910_DEBOUNCE_150_MS       1
-
-#define TPS65910_GPIO_PUDIS            (1 << 3)
-#define TPS65910_GPIO_CFG_OUTPUT       (1 << 2)
-
-
-
-/* TPS65910 Interrupt events */
-
-/* RTC Driver */
-#define TPS65910_RTC_ALARM_IT          0x80
-#define TPS65910_RTC_PERIOD_IT         0x40
-
-/*Core Driver */
-#define TPS65910_HOT_DIE_IT            0x20
-#define TPS65910_PWRHOLD_IT            0x10
-#define TPS65910_PWRON_LP_IT           0x08
-#define TPS65910_PWRON_IT              0x04
-#define TPS65910_VMBHI_IT              0x02
-#define TPS65910_VMBGCH_IT             0x01
-
-/* GPIO driver */
-#define TPS65910_GPIO_F_IT             0x02
-#define TPS65910_GPIO_R_IT             0x01
-
-
-#define TPS65910_VRTC_OFFMASK          (1<<3)
-
-/* Back-up battery charger control */
-#define TPS65910_BBCHEN                        0x01
-
-/* Back-up battery charger voltage */
-#define TPS65910_BBSEL_3P0             0x00
-#define TPS65910_BBSEL_2P52            0x02
-#define TPS65910_BBSEL_3P15            0x04
-#define TPS65910_BBSEL_VBAT            0x06
-
-/* DEVCTRL_REG flags */
-#define TPS65910_RTC_PWDNN             0x40
-#define TPS65910_CK32K_CTRL            0x20
-#define TPS65910_SR_CTL_I2C_SEL        0x10
-#define TPS65910_DEV_OFF_RST           0x08
-#define TPS65910_DEV_ON                        0x04
-#define TPS65910_DEV_SLP               0x02
-#define TPS65910_DEV_OFF               0x01
-
-/* DEVCTRL2_REG flags */
-#define TPS65910_DEV2_TSLOT_LENGTH     0x30
-#define TPS65910_DEV2_SLEEPSIG_POL     0x08
-#define TPS65910_DEV2_PWON_LP_OFF      0x04
-#define TPS65910_DEV2_PWON_LP_RST      0x02
-#define TPS65910_DEV2_IT_POL           0x01
-
-/* TPS65910 SMPS/LDO's */
-#define TPS65910_VIO                   0
-#define TPS65910_VDD1                  1
-#define TPS65910_VDD2                  2
-#define TPS65910_VDD3                  3
-/* LDOs */
-#define TPS65910_VDIG1                 4
-#define TPS65910_VDIG2                 5
-#define TPS65910_VAUX33                        6
-#define TPS65910_VMMC                  7
-#define TPS65910_VAUX1                 8
-#define TPS65910_VAUX2                 9
-#define TPS65910_VDAC                  10
-#define TPS65910_VPLL                  11
-/* Internal LDO */
-#define TPS65910_VRTC                  12
-
-/* Number of step-down/up converters available */
-#define TPS65910_NUM_DCDC              4
-
-/* Number of LDO voltage regulators  available */
-#define TPS65910_NUM_LDO               9
-
-/* Number of total regulators available */
-#define TPS65910_NUM_REGULATOR  (TPS65910_NUM_DCDC + TPS65910_NUM_LDO)
-
-
-/* Regulator Supply state */
-#define SUPPLY_STATE_FLAG              0x03
-/* OFF States */
-#define TPS65910_REG_OFF_00            0x00
-#define TPS65910_REG_OFF_10            0x02
-/* OHP - on High Power */
-#define TPS65910_REG_OHP               0x01
-/* OLP - on Low Power */
-#define TPS65910_REG_OLP               0x03
-
-#define TPS65910_MAX_IRQS              10
-#define TPS65910_VMBDCH_IRQ            0
-#define TPS65910_VMBHI_IRQ             1
-#define TPS65910_PWRON_IRQ             2
-#define TPS65910_PWRON_LP_IRQ          3
-#define TPS65910_PWRHOLD_IRQ           4
-#define TPS65910_HOTDIE_IRQ            5
-#define TPS65910_RTC_ALARM_IRQ         6
-#define TPS65910_RTC_PERIOD_IRQ        7
-#define TPS65910_GPIO0_R_IRQ           8
-#define TPS65910_GPIO0_F_IRQ           9
-
-/* TPS65910 has 1 GPIO  */
-struct tps65910_gpio {
-       u8      debounce;
-       u8      pullup_pulldown;
-       u8      gpio_config;  /* Input or output */
-       u8      gpio_val;    /* Output value */
-       int (*gpio_setup)(struct tps65910_gpio *pdata);
-       int (*gpio_taredown)(struct tps65910_gpio *pdata);
-};
-
-struct tps65910_platform_data {
-
-       unsigned irq_num;  /* TPS65910 to Host IRQ Number */
-       struct tps65910_gpio    *gpio;
-
-       /* plaform specific data to be initialised in board file */
-       struct regulator_init_data *vio;
-       struct regulator_init_data *vdd1;
-       struct regulator_init_data *vdd2;
-       struct regulator_init_data *vdd3;
-       struct regulator_init_data *vdig1;
-       struct regulator_init_data *vdig2;
-       struct regulator_init_data *vaux33;
-       struct regulator_init_data *vmmc;
-       struct regulator_init_data *vaux1;
-       struct regulator_init_data *vaux2;
-       struct regulator_init_data *vdac;
-       struct regulator_init_data *vpll;
-
-       void  (*handlers[TPS65910_MAX_IRQS]) (void  *data);
-       /* Configure TP65910 to board specific usage*/
-       int (*board_tps65910_config)(struct tps65910_platform_data *pdata);
-};
-
-int tps65910_enable_bbch(u8 voltage);
-int tps65910_disable_bbch(void);
-
-int tps65910_remove_irq_work(int irq);
-int tps65910_add_irq_work(int irq, void (*handler)(void *data));
-
-int tps65910_i2c_write_u8(u8 slave_addr, u8 val, u8 reg);
-int tps65910_i2c_read_u8(u8 slave_addr, u8 *val, u8 reg);
-
-#endif /*  __LINUX_I2C_TPS65910_H */
-
index 0d515ee1c24747319b561f0f0bda98dd1e50903e..4b217b9b8fc741b3a45da3445810a5928fdb4c74 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <linux/completion.h>
 #include <linux/interrupt.h>
+#include <linux/wakelock.h>
+#include <linux/regulator/driver.h>
 
 /*
  * Register values.
 struct regulator_dev;
 
 #define WM831X_NUM_IRQ_REGS 5
+#define WM831X_IRQ_LIST        1
+enum wm831x_parent {
+       WM8310 = 0x8310,
+       WM8311 = 0x8311,
+       WM8312 = 0x8312,
+       WM8320 = 0x8320,
+       WM8321 = 0x8321,
+       WM8325 = 0x8325,
+};
 
 enum wm831x_parent {
        WM8310 = 0x8310,
@@ -260,7 +271,19 @@ struct wm831x {
        void *control_data;
 
        int irq;  /* Our chip IRQ */
+       int flag_suspend;
+       spinlock_t              flag_lock;
        struct mutex irq_lock;
+       struct workqueue_struct *irq_wq;
+       struct delayed_work irq_work;
+       struct wake_lock        irq_wake;
+       struct wake_lock        handle_wake;
+#if WM831X_IRQ_LIST
+       struct workqueue_struct *handle_wq;
+       struct work_struct handle_work;
+       spinlock_t              work_lock;
+       struct list_head        handle_queue;
+#endif
        unsigned int irq_base;
        int irq_masks_cur[WM831X_NUM_IRQ_REGS];   /* Currently active value */
        int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
@@ -284,6 +307,39 @@ struct wm831x {
        unsigned int locked:1;
 };
 
+#define WM831X_DCDC_MAX_NAME 6
+#define WM831X_LDO_MAX_NAME 6
+#define WM831X_ISINK_MAX_NAME 7
+
+struct wm831x_dcdc {
+        char name[WM831X_DCDC_MAX_NAME];
+        struct regulator_desc desc;
+        int base;
+        struct wm831x *wm831x;
+        struct regulator_dev *regulator;
+        int dvs_gpio;
+        int dvs_gpio_state;
+        int on_vsel;
+        int dvs_vsel;
+};
+
+struct wm831x_ldo {
+        char name[WM831X_LDO_MAX_NAME];
+        struct regulator_desc desc;
+        int base;
+        struct wm831x *wm831x;
+        struct regulator_dev *regulator;
+};
+
+struct wm831x_isink {
+        char name[WM831X_ISINK_MAX_NAME];
+        struct regulator_desc desc;
+        int reg;
+        struct wm831x *wm831x;
+        struct regulator_dev *regulator;
+};
+
+
 /* Device I/O API */
 int wm831x_reg_read(struct wm831x *wm831x, unsigned short reg);
 int wm831x_reg_write(struct wm831x *wm831x, unsigned short reg,
@@ -298,6 +354,10 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
 int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
 void wm831x_device_exit(struct wm831x *wm831x);
 int wm831x_device_suspend(struct wm831x *wm831x);
+int wm831x_device_resume(struct wm831x *wm831x);
+int wm831x_device_shutdown(struct wm831x *wm831x);
+int wm831x_read_usb(struct wm831x *wm831x);
+int wm831x_device_restart(struct wm831x *wm831x);
 int wm831x_irq_init(struct wm831x *wm831x, int irq);
 void wm831x_irq_exit(struct wm831x *wm831x);
 
index ff42d700293fc71485d80f092c978fd633919b27..accc729c797097e628934af19da9843e9b3af350 100755 (executable)
@@ -39,6 +39,8 @@ struct wm831x_battery_pdata {
        int eoc_iterm;      /** End of trickle charge current, in mA */
        int fast_ilim;      /** Fast charge current limit, in mA */
        int timeout;        /** Charge cycle timeout, in minutes */
+       int syslo;          /** syslo threshold, in mV**/
+       int sysok;          /** sysok threshold, in mV**/
 };
 
 /**
@@ -98,6 +100,22 @@ struct wm831x_watchdog_pdata {
        int update_gpio;
        unsigned int software:1;
 };
+struct wm831x_gpio_keys_button {
+       /* Configuration parameters */
+       int code;               /* input event code (KEY_*, SW_*) */
+       int gpio;
+       int active_low;
+       char *desc;
+       int type;               /* input event type (EV_KEY, EV_SW) */
+       int wakeup;             /* configure the button as a wake-up source */
+       int debounce_interval;  /* debounce ticks interval in msecs */
+};
+
+struct wm831x_gpio_keys_pdata {
+       struct wm831x_gpio_keys_button *buttons;
+       int nbuttons;
+       unsigned int rep:1;             /* enable input subsystem auto repeat */
+};
 
 #define WM831X_MAX_STATUS 2
 #define WM831X_MAX_DCDC   4
@@ -116,10 +134,21 @@ struct wm831x_pdata {
        int (*pre_init)(struct wm831x *wm831x);
        /** Called after subdevices are set up */
        int (*post_init)(struct wm831x *wm831x);
+<<<<<<< HEAD
 
        /** Put the /IRQ line into CMOS mode */
        bool irq_cmos;
 
+=======
+       /** Called before subdevices are power down */
+       int (*last_deinit)(struct wm831x *wm831x);
+       //add by sxj    
+       unsigned int gpio_pin_num;      
+       struct rk2818_gpio_expander_info  *settinginfo; 
+       int  settinginfolen;    
+       int (*pin_type_init)(struct wm831x *wm831x);    
+       //above add by sxj
+>>>>>>> parent of 15f7fab... temp revert rk change
        int irq_base;
        int gpio_base;
        int gpio_defaults[WM831X_GPIO_NUM];
@@ -128,6 +157,9 @@ struct wm831x_pdata {
        struct wm831x_battery_pdata *battery;
        struct wm831x_touch_pdata *touch;
        struct wm831x_watchdog_pdata *watchdog;
+       //add by srt
+       struct wm831x_gpio_keys_pdata *gpio_keys;
+       //end by srt
 
        /** LED1 = 0 and so on */
        struct wm831x_status_pdata *status[WM831X_MAX_STATUS];
index f0b69cdae41cc94f24c995d9812301d9eb711451..7929fc9d67091c6e2502b9caaf584b35a545943f 100644 (file)
@@ -15,6 +15,7 @@
 #ifndef __MFD_WM8994_CORE_H__
 #define __MFD_WM8994_CORE_H__
 
+<<<<<<< HEAD
 #include <linux/interrupt.h>
 
 enum wm8994_type {
@@ -22,36 +23,16 @@ enum wm8994_type {
        WM8958 = 1,
 };
 
+=======
+>>>>>>> parent of 15f7fab... temp revert rk change
 struct regulator_dev;
 struct regulator_bulk_data;
 
 #define WM8994_NUM_GPIO_REGS 11
-#define WM8994_NUM_LDO_REGS   2
-#define WM8994_NUM_IRQ_REGS   2
-
-#define WM8994_IRQ_TEMP_SHUT           0
-#define WM8994_IRQ_MIC1_DET            1
-#define WM8994_IRQ_MIC1_SHRT           2
-#define WM8994_IRQ_MIC2_DET            3
-#define WM8994_IRQ_MIC2_SHRT           4
-#define WM8994_IRQ_FLL1_LOCK           5
-#define WM8994_IRQ_FLL2_LOCK           6
-#define WM8994_IRQ_SRC1_LOCK           7
-#define WM8994_IRQ_SRC2_LOCK           8
-#define WM8994_IRQ_AIF1DRC1_SIG_DET    9
-#define WM8994_IRQ_AIF1DRC2_SIG_DET    10
-#define WM8994_IRQ_AIF2DRC_SIG_DET     11
-#define WM8994_IRQ_FIFOS_ERR           12
-#define WM8994_IRQ_WSEQ_DONE           13
-#define WM8994_IRQ_DCS_DONE            14
-#define WM8994_IRQ_TEMP_WARN           15
-
-/* GPIOs in the chip are numbered from 1-11 */
-#define WM8994_IRQ_GPIO(x) (x + WM8994_IRQ_TEMP_WARN)
+#define WM8994_NUM_LDO_REGS 2
 
 struct wm8994 {
        struct mutex io_lock;
-       struct mutex irq_lock;
 
        enum wm8994_type type;
 
@@ -64,11 +45,6 @@ struct wm8994 {
        void *control_data;
 
        int gpio_base;
-       int irq_base;
-
-       int irq;
-       u16 irq_masks_cur[WM8994_NUM_IRQ_REGS];
-       u16 irq_masks_cache[WM8994_NUM_IRQ_REGS];
 
        /* Used over suspend/resume */
        bool suspended;
@@ -91,26 +67,4 @@ int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
 int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
                     int count, const u16 *buf);
 
-
-/* Helper to save on boilerplate */
-static inline int wm8994_request_irq(struct wm8994 *wm8994, int irq,
-                                    irq_handler_t handler, const char *name,
-                                    void *data)
-{
-       if (!wm8994->irq_base)
-               return -EINVAL;
-       return request_threaded_irq(wm8994->irq_base + irq, NULL, handler,
-                                   IRQF_TRIGGER_RISING, name,
-                                   data);
-}
-static inline void wm8994_free_irq(struct wm8994 *wm8994, int irq, void *data)
-{
-       if (!wm8994->irq_base)
-               return;
-       free_irq(wm8994->irq_base + irq, data);
-}
-
-int wm8994_irq_init(struct wm8994 *wm8994);
-void wm8994_irq_exit(struct wm8994 *wm8994);
-
 #endif
index d12f8d635a8159b8ce54a144dbf9eda1d90e29d8..3f8ab55bd6fcd1d80d014224831c7eecbb339c57 100644 (file)
@@ -29,6 +29,7 @@ struct wm8994_ldo_pdata {
 #define WM8994_CONFIGURE_GPIO 0x8000
 
 #define WM8994_DRC_REGS 5
+<<<<<<< HEAD
 #define WM8994_EQ_REGS  20
 #define WM8958_MBC_CUTOFF_REGS 20
 #define WM8958_MBC_COEFF_REGS  48
@@ -36,6 +37,9 @@ struct wm8994_ldo_pdata {
 #define WM8958_VSS_HPF_REGS 2
 #define WM8958_VSS_REGS 148
 #define WM8958_ENH_EQ_REGS 32
+=======
+#define WM8994_EQ_REGS  19
+>>>>>>> parent of 15f7fab... temp revert rk change
 
 /**
  * DRC configurations are specified with a label and a set of register
@@ -65,6 +69,7 @@ struct wm8994_retune_mobile_cfg {
         u16 regs[WM8994_EQ_REGS];
 };
 
+<<<<<<< HEAD
 /**
  * Multiband compressor configurations are specified with a label and
  * two sets of values to write.  Configurations are expected to be
@@ -112,6 +117,10 @@ struct wm8958_enh_eq_cfg {
        const char *name;
        u16 regs[WM8958_ENH_EQ_REGS];
 };
+=======
+#define PCM_BB 1
+#define NO_PCM_BB 0
+>>>>>>> parent of 15f7fab... temp revert rk change
 
 struct wm8994_pdata {
        int gpio_base;
@@ -124,7 +133,6 @@ struct wm8994_pdata {
 
        struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO];
 
-       int irq_base;  /** Base IRQ number for WM8994, required for IRQs */
 
         int num_drc_cfgs;
         struct wm8994_drc_cfg *drc_cfgs;
@@ -165,8 +173,39 @@ struct wm8994_pdata {
         unsigned int jd_scthr:2;
         unsigned int jd_thr:2;
 
+<<<<<<< HEAD
        /* WM8958 microphone bias configuration */
        int micbias[2];
+=======
+               //for phonepad
+               unsigned int no_earpiece:1;      // =1  don't have a earpiece,  =0   has a earpiece
+               unsigned int sp_hp_same_channel:1;
+               
+               //BB input can be differential or single ended
+               unsigned int BB_input_diff:1;   //  =0  single ended     =1  differential
+               unsigned int BB_class:1;//PCM_BB= 1  NO_PCM_BB=0
+               
+               //If an external amplifier speakers wm8994              enable>0 disable=0
+               unsigned int PA_control_pin;
+
+               //wm8994 LDO1_ENA and LDO2_ENA
+               unsigned int Power_EN_Pin;
+               char    PowerEN_iomux_name[50];
+               int             PowerEN_iomux_mode;     
+
+       //volume
+       int speaker_incall_vol;                 //max = 6, min = -21
+       int speaker_incall_mic_vol;             //max = 30, min = -22
+       int speaker_normal_vol;                 //max = 6, min = -57
+       int earpiece_incall_vol;                //max = 6, min = -21
+       int headset_incall_vol;                 //max = 6, min = -12
+       int headset_incall_mic_vol;             //max = 30, min = -22
+       int headset_normal_vol;                 //max = 6, min = -57
+       int BT_incall_vol;                              //max = 30, min = -16
+       int BT_incall_mic_vol;                  //max = 6, min = -57
+       int recorder_vol;                               //max = 60 , min = -16
+               
+>>>>>>> parent of 15f7fab... temp revert rk change
 };
 
 #endif
index 1584b5236bbc228bcaa3538f07b69d03c88e9511..5a3ea9025873df70934f84f04516cf0de26024b0 100755 (executable)
@@ -265,6 +265,12 @@ struct mmc_host {
        const struct mmc_bus_ops *bus_ops;      /* current bus driver */
        unsigned int            bus_refs;       /* reference counter */
 
+#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
+       unsigned int            re_initialized_flags; //in order to begin the rescan ;  added by xbw@2011-04-07
+       unsigned int            doneflag; //added by xbw at 2011-08-27
+       int                     (*sdmmc_host_hw_init)(void *data);
+#endif
+
        unsigned int            bus_resume_flags;
 #define MMC_BUSRESUME_MANUAL_RESUME    (1 << 0)
 #define MMC_BUSRESUME_NEEDS_RESUME     (1 << 1)
old mode 100755 (executable)
new mode 100644 (file)
index 9e87c1c..01f597c
@@ -153,6 +153,9 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector);
 int regulator_is_supported_voltage(struct regulator *regulator,
                                   int min_uV, int max_uV);
 int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV);
+#ifdef CONFIG_ARCH_RK29
+int regulator_set_suspend_voltage(struct regulator *regulator, int uV);
+#endif
 int regulator_set_voltage_time(struct regulator *regulator,
                               int old_uV, int new_uV);
 int regulator_get_voltage(struct regulator *regulator);
@@ -243,6 +246,13 @@ static inline int regulator_set_voltage(struct regulator *regulator,
        return 0;
 }
 
+#ifdef CONFIG_ARCH_RK29
+static inline int regulator_set_suspend_voltage(struct regulator *regulator, int uV)
+{
+       return 0;
+}
+#endif
+
 static inline int regulator_get_voltage(struct regulator *regulator)
 {
        return 0;
index a096d24ada1dbaaa6587c133af7004f486bfbed1..492aa649629ab73d98338d050a90d1275c7a1c17 100755 (executable)
@@ -72,6 +72,7 @@ int wake_lock_active(struct wake_lock *lock);
  * number of jiffies until all active wake locks time out.
  */
 long has_wake_lock(int type);
+void print_active_wake_locks(int type);
 
 #else
 
@@ -84,6 +85,7 @@ static inline void wake_unlock(struct wake_lock *lock) {}
 
 static inline int wake_lock_active(struct wake_lock *lock) { return 0; }
 static inline long has_wake_lock(int type) { return 0; }
+static inline void print_active_wake_locks(int type) {}
 
 #endif
 
index b3edb67a83114e10af4409a46388187c84a5c53e..8ba4d6237ab7ba4474da7d8a197025a8b809946c 100755 (executable)
@@ -72,14 +72,23 @@ enum {
        V4L2_IDENT_OV9650 = 254,
        V4L2_IDENT_OV9655 = 255,
        V4L2_IDENT_SOI968 = 256,
-       V4L2_IDENT_OV9640 = 257,
-       V4L2_IDENT_OV6650 = 258,
-       V4L2_IDENT_OV2640 = 259,
-       V4L2_IDENT_OV9740 = 260,
+       V4L2_IDENT_OV2655 = 257,                            /* ddl@rock-chips.com : ov2655 support */
+       V4L2_IDENT_OV2659 = 258,
+       V4L2_IDENT_OV3640 = 259,
+       V4L2_IDENT_OV5640 = 260,
+       V4L2_IDENT_OV5642 = 261,
+       V4L2_IDENT_OV7675 = 262,
+       V4L2_IDENT_OV2640 = 263,
+       V4L2_IDENT_OV9640 = 264,
+       V4L2_IDENT_OV6650 = 265,
+       V4L2_IDENT_OV9740 = 266,
 
        /* module saa7146: reserved range 300-309 */
        V4L2_IDENT_SAA7146 = 300,
 
+       /* Samsung sensors: reserved range 310-319 */
+       V4L2_IDENT_S5K66A = 310,                                                        /* ddl@rock-chips.com : s5k66a support */
+
        /* Conexant MPEG encoder/decoders: reserved range 400-420 */
        V4L2_IDENT_CX23418_843 = 403, /* Integrated A/V Decoder on the '418 */
        V4L2_IDENT_CX23415 = 415,
@@ -290,6 +299,7 @@ enum {
        V4L2_IDENT_MT9M001C12STM        = 45005,
        V4L2_IDENT_MT9M111              = 45007,
        V4L2_IDENT_MT9M112              = 45008,
+       V4L2_IDENT_MT9D112              = 45009,                /* ddl@rock-chips.com : MT9D112 support */
        V4L2_IDENT_MT9V022IX7ATC        = 45010, /* No way to detect "normal" I77ATx */
        V4L2_IDENT_MT9V022IX7ATM        = 45015, /* and "lead free" IA7ATx chips */
        V4L2_IDENT_MT9T031              = 45020,
@@ -298,6 +308,9 @@ enum {
        V4L2_IDENT_MT9V111              = 45031,
        V4L2_IDENT_MT9V112              = 45032,
 
+       V4L2_IDENT_MT9P111              = 45033,     /* ddl@rock-chips.com : MT9P111 support */
+       V4L2_IDENT_MT9D113      = 45034,     /* ddl@rock-chips.com : MT9D113 support */
+
        /* HV7131R CMOS sensor: just ident 46000 */
        V4L2_IDENT_HV7131R              = 46000,
 
@@ -321,6 +334,19 @@ enum {
        /* module upd64083: just ident 64083 */
        V4L2_IDENT_UPD64083 = 64083,
 
+
+    V4L2_IDENT_GT2005 = 64099,       /* ddl@rock-chips.com : GT2005 support */
+    V4L2_IDENT_GC0307 = 64100,      /* ddl@rock-chips.com : GC0308 support */
+    V4L2_IDENT_GC0308 = 64101,      /* ddl@rock-chips.com : GC0308 support */
+    V4L2_IDENT_GC0309 = 64102,      /* ddl@rock-chips.com : GC0309 support */
+    V4L2_IDENT_SIV120B = 64103,      /* ddl@rock-chips.com : siv120b support */
+
+    V4L2_IDENT_GC2015 = 64105,      /* ddl@rock-chips.com : gc2015 support */
+    V4L2_IDENT_HI253 = 64106,      /* ddl@rock-chips.com : hi253 support */
+    V4L2_IDENT_HI704 = 64107,      /* ddl@rock-chips.com : hi704 support */
+    V4L2_IDENT_NT99250 = 64108,    /* ddl@rock-chips.com : nt99250 support */
+    V4L2_IDENT_SID130B = 64109,      /* ddl@rock-chips.com : sid130B support */
+
        /* Don't just add new IDs at the end: KEEP THIS LIST ORDERED BY ID! */
 };
 
index b15f02eba45cb7cc2d5f2bb6854a94124f6967cb..e073695d44f550123d755ec10ae20012bb5597ec 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/syscalls.h> /* sys_sync */
 #include <linux/wakelock.h>
 #include <linux/workqueue.h>
+#include <linux/kallsyms.h>
 
 #include "power.h"
 
@@ -98,6 +99,8 @@ static void early_suspend(struct work_struct *work)
                if (pos->suspend != NULL) {
                        if (debug_mask & DEBUG_VERBOSE)
                                pr_info("early_suspend: calling %pf\n", pos->suspend);
+                       if (debug_mask & DEBUG_VERBOSE)
+                               print_symbol("early_suspend: call %s\n", (unsigned long)pos->suspend);
                        pos->suspend(pos);
                }
        }
@@ -139,6 +142,8 @@ static void late_resume(struct work_struct *work)
                if (pos->resume != NULL) {
                        if (debug_mask & DEBUG_VERBOSE)
                                pr_info("late_resume: calling %pf\n", pos->resume);
+                       if (debug_mask & DEBUG_VERBOSE)
+                               print_symbol("late_resume: call %s\n", (unsigned long)pos->resume);
 
                        pos->resume(pos);
                }
index 31338cdeafc4749766567bbd41546d3dd885dd96..dd7d22d2c0ff76943ad5e6e6bed01b22344d00d5 100644 (file)
@@ -117,6 +117,7 @@ static int try_to_freeze_tasks(bool sig_only)
                        printk("\n");
                        printk(KERN_ERR "Freezing of %s aborted\n",
                                        sig_only ? "user space " : "tasks ");
+                       print_active_wake_locks(WAKE_LOCK_SUSPEND);
                }
                else {
                        printk("\n");
index 2ee459fe44560a1937b4548da652a94d08958670..527d5a9addd8b554f4c016f3815736327a18b4cd 100644 (file)
@@ -202,28 +202,33 @@ static void expire_wake_lock(struct wake_lock *lock)
 }
 
 /* Caller must acquire the list_lock spinlock */
-static void print_active_locks(int type)
+static void print_active_locks_locked(int type)
 {
        struct wake_lock *lock;
-       bool print_expired = true;
 
        BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
        list_for_each_entry(lock, &active_wake_locks[type], link) {
                if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
                        long timeout = lock->expires - jiffies;
-                       if (timeout > 0)
-                               pr_info("active wake lock %s, time left %ld\n",
-                                       lock->name, timeout);
-                       else if (print_expired)
+                       if (timeout <= 0)
                                pr_info("wake lock %s, expired\n", lock->name);
-               } else {
+                       else
+                               pr_info("active wake lock %s, time left %ld.%03lu\n",
+                                       lock->name, timeout / HZ,
+                                       (timeout % HZ) * MSEC_PER_SEC / HZ);
+               } else
                        pr_info("active wake lock %s\n", lock->name);
-                       if (!(debug_mask & DEBUG_EXPIRE))
-                               print_expired = false;
-               }
        }
 }
 
+void print_active_wake_locks(int type)
+{
+       unsigned long irqflags;
+       spin_lock_irqsave(&list_lock, irqflags);
+       print_active_locks_locked(type);
+       spin_unlock_irqrestore(&list_lock, irqflags);
+}
+
 static long has_wake_lock_locked(int type)
 {
        struct wake_lock *lock, *n;
@@ -250,7 +255,7 @@ long has_wake_lock(int type)
        spin_lock_irqsave(&list_lock, irqflags);
        ret = has_wake_lock_locked(type);
        if (ret && (debug_mask & DEBUG_WAKEUP) && type == WAKE_LOCK_SUSPEND)
-               print_active_locks(type);
+               print_active_locks_locked(type);
        spin_unlock_irqrestore(&list_lock, irqflags);
        return ret;
 }
@@ -297,7 +302,7 @@ static void expire_wake_locks(unsigned long data)
                pr_info("expire_wake_locks: start\n");
        spin_lock_irqsave(&list_lock, irqflags);
        if (debug_mask & DEBUG_SUSPEND)
-               print_active_locks(WAKE_LOCK_SUSPEND);
+               print_active_locks_locked(WAKE_LOCK_SUSPEND);
        has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
        if (debug_mask & DEBUG_EXPIRE)
                pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
@@ -337,6 +342,7 @@ void wake_lock_init(struct wake_lock *lock, int type, const char *name)
        if (name)
                lock->name = name;
        BUG_ON(!lock->name);
+       BUG_ON(lock->flags & WAKE_LOCK_INITIALIZED);
 
        if (debug_mask & DEBUG_WAKE_LOCK)
                pr_info("wake_lock_init name=%s\n", lock->name);
@@ -503,7 +509,7 @@ void wake_unlock(struct wake_lock *lock)
                }
                if (lock == &main_wake_lock) {
                        if (debug_mask & DEBUG_SUSPEND)
-                               print_active_locks(WAKE_LOCK_SUSPEND);
+                               print_active_locks_locked(WAKE_LOCK_SUSPEND);
 #ifdef CONFIG_WAKELOCK_STAT
                        update_sleep_wait_stats_locked(0);
 #endif
index e4128b278f2375dc4e91c7244fbb4117b5230fea..378381e9dd70c13f1c0f6475defac653b6e12220 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/unistd.h>
+/***************
+*       DEBUG
+****************/
+#define RESTART_DEBUG
+#ifdef RESTART_DEBUG
+#define restart_dbg(format, arg...) \
+       printk("RESTART_DEBUG : " format "\n" , ## arg)
+#else
+#define restart_dbg(format, arg...) do {} while (0)
+#endif
+
+
 
 #ifndef SET_UNALIGN_CTL
 # define SET_UNALIGN_CTL(a,b)  (-EINVAL)
@@ -329,6 +341,11 @@ void kernel_restart_prepare(char *cmd)
  */
 void kernel_restart(char *cmd)
 {
+       /*
+       *  debug trace
+       */
+       restart_dbg("%s->%d->cmd=%s",__FUNCTION__,__LINE__,cmd);
+       
        kernel_restart_prepare(cmd);
        if (!cmd)
                printk(KERN_EMERG "Restarting system.\n");
@@ -418,6 +435,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
        mutex_lock(&reboot_mutex);
        switch (cmd) {
        case LINUX_REBOOT_CMD_RESTART:
+               /*
+               *  debug trace
+               */
+               restart_dbg("%s->%d->cmd=%x",__FUNCTION__,__LINE__,cmd);
+               
                kernel_restart(NULL);
                break;
 
@@ -435,6 +457,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
                panic("cannot halt");
 
        case LINUX_REBOOT_CMD_POWER_OFF:
+               /*
+               *  debug trace
+               */
+               restart_dbg("%s->%d->cmd=%x",__FUNCTION__,__LINE__,cmd);
+               
                kernel_power_off();
                do_exit(0);
                break;
@@ -445,7 +472,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
                        break;
                }
                buffer[sizeof(buffer) - 1] = '\0';
-
+               /*
+               *  debug trace
+               */
+               restart_dbg("%s->%d->cmd=%x args=%s",__FUNCTION__,__LINE__,cmd,buffer);
+               
                kernel_restart(buffer);
                break;
 
index 98175a096df2496da11822e6772d4f92420ca3bb..bd370c66e76af68c895368d771543429344a0e3c 100644 (file)
@@ -26,6 +26,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_ALC5623 if I2C
        select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
        select SND_SOC_CS42L51 if I2C
+       select SND_SOC_CS42L52 if I2C
        select SND_SOC_CS4270 if I2C
        select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
        select SND_SOC_CX20442
@@ -73,6 +74,9 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI
        select SND_SOC_WM8900 if I2C
+       select SND_SOC_alc5621 if I2C
+       select SND_SOC_alc5631 if I2C
+       select SND_SOC_RT5625 if I2C
        select SND_SOC_WM8903 if I2C
        select SND_SOC_WM8904 if I2C
        select SND_SOC_WM8915 if I2C
@@ -158,6 +162,9 @@ config SND_SOC_CQ0093VC
 config SND_SOC_CS42L51
        tristate
 
+config SND_SOC_CS42L52
+       tristate
+
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
        tristate
@@ -305,6 +312,15 @@ config SND_SOC_WM8804
 config SND_SOC_WM8900
        tristate
 
+config SND_SOC_alc5621
+       tristate
+
+config SND_SOC_alc5631
+       tristate
+
+config SND_SOC_RT5625
+       tristate
+
 config SND_SOC_WM8903
        tristate
 
@@ -371,6 +387,10 @@ config SND_SOC_WM9712
 config SND_SOC_WM9713
        tristate
 
+config SND_SOC_RK1000
+       tristate
+       depends on RK1000_CONTROL
+
 # Amp
 config SND_SOC_LM4857
        tristate
index fd8558406ef002a71aea9a2521d60f6fdcd3c730..d4f5f1599532f1e1e30d512c8c00a18e10e0718c 100644 (file)
@@ -57,6 +57,10 @@ snd-soc-wm8770-objs := wm8770.o
 snd-soc-wm8776-objs := wm8776.o
 snd-soc-wm8804-objs := wm8804.o
 snd-soc-wm8900-objs := wm8900.o
+snd-soc-alc5621-objs := alc5621.o
+snd-soc-alc5631-objs := rt5631.o
+snd-soc-rt5625-objs := rt5625.o
+snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-wm8903-objs := wm8903.o
 snd-soc-wm8904-objs := wm8904.o
 snd-soc-wm8915-objs := wm8915.o
@@ -80,6 +84,7 @@ snd-soc-wm9705-objs := wm9705.o
 snd-soc-wm9712-objs := wm9712.o
 snd-soc-wm9713-objs := wm9713.o
 snd-soc-wm-hubs-objs := wm_hubs.o
+snd-soc-rk1000-objs := rk1000_codec.o
 snd-soc-jz4740-codec-objs := jz4740.o
 
 # Amp
@@ -149,6 +154,10 @@ obj-$(CONFIG_SND_SOC_WM8770)       += snd-soc-wm8770.o
 obj-$(CONFIG_SND_SOC_WM8776)   += snd-soc-wm8776.o
 obj-$(CONFIG_SND_SOC_WM8804)   += snd-soc-wm8804.o
 obj-$(CONFIG_SND_SOC_WM8900)   += snd-soc-wm8900.o
+obj-$(CONFIG_SND_SOC_alc5621)  += snd-soc-alc5621.o
+obj-$(CONFIG_SND_SOC_alc5631)  += snd-soc-alc5631.o
+obj-$(CONFIG_SND_SOC_RT5625)   += snd-soc-rt5625.o
+obj-$(CONFIG_SND_SOC_CS42L52)  += snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_WM8903)   += snd-soc-wm8903.o
 obj-$(CONFIG_SND_SOC_WM8904)   += snd-soc-wm8904.o
 obj-$(CONFIG_SND_SOC_WM8915)   += snd-soc-wm8915.o
@@ -172,6 +181,7 @@ obj-$(CONFIG_SND_SOC_WM9705)        += snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)  += snd-soc-wm-hubs.o
+obj-$(CONFIG_SND_SOC_RK1000)   += snd-soc-rk1000.o
 
 # Amp
 obj-$(CONFIG_SND_SOC_LM4857)   += snd-soc-lm4857.o
index 449ea09a193d6800596c481eb564bee1e35d2997..979e57fdcee58053bcbc90424abba6a46f87bc86 100755 (executable)
 #include <sound/soc.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/rk29_iomap.h>
 
 #include "wm8900.h"
 
+
+#if 0
+#define        WM8900_DBG(x...)        printk(KERN_INFO x)
+#else
+#define        WM8900_DBG(x...)
+#endif
+
 /* WM8900 register space */
 #define WM8900_REG_RESET       0x0
 #define WM8900_REG_ID          0x0
 #define WM8900_REG_CLOCKING1_BCLK_MASK  (~0x01e)
 #define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000)
 
-#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0
-#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
+#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0x1c
+#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0xe0
 
 #define WM8900_REG_DACCTRL_MUTE          0x004
 #define WM8900_REG_DACCTRL_DAC_SB_FILT   0x100
 #define WM8900_REG_HPCTL1_HP_SHORT2      0x04
 
 #define WM8900_LRC_MASK 0xfc00
+#define SPK_CON                RK29_PIN6_PB6
+
+#define WM8900_NO_POWEROFF /* Do not close codec except suspend or poweroff */
+
+#define WM8900_IS_SHUTDOWN     0
+#define WM8900_IS_STARTUP      1
+
+#define WM8900_WORK_NULL       0
+#define WM8900_WORK_POWERDOWN_PLAYBACK 1
+#define WM8900_WORK_POWERDOWN_CAPTURE  2
+#define WM8900_WORK_POWERDOWN_PLAYBACK_CAPTURE 3
+#define WM8900_WORK_HW_SET 4
+
+static void wm8900_work(struct work_struct *work);
+
+static struct workqueue_struct *wm8900_workq;
+static DECLARE_DELAYED_WORK(delayed_work, wm8900_work);
+static int wm8900_current_status = WM8900_IS_SHUTDOWN, wm8900_work_type = WM8900_WORK_NULL;
+
+static struct snd_soc_codec *wm8900_codec;
+static bool isSPKon = true;
 
 struct wm8900_priv {
        enum snd_soc_control_type control_type;
@@ -192,423 +223,126 @@ static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int re
 
 static void wm8900_reset(struct snd_soc_codec *codec)
 {
+       WM8900_DBG("Enter:%s, %d, codec=0x%8X \n", __FUNCTION__, __LINE__,codec);
+
        snd_soc_write(codec, WM8900_REG_RESET, 0);
 
        memcpy(codec->reg_cache, wm8900_reg_defaults,
               sizeof(wm8900_reg_defaults));
 }
 
-static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
-                          struct snd_kcontrol *kcontrol, int event)
+void codec_set_spk(bool on)
 {
-       struct snd_soc_codec *codec = w->codec;
-       u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1);
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               /* Clamp headphone outputs */
-               hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP |
-                       WM8900_REG_HPCTL1_HP_CLAMP_OP;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-               break;
-
-       case SND_SOC_DAPM_POST_PMU:
-               /* Enable the input stage */
-               hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_IP;
-               hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT |
-                       WM8900_REG_HPCTL1_HP_SHORT2 |
-                       WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
-               msleep(400);
-
-               /* Enable the output stage */
-               hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP;
-               hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
-               /* Remove the shorts */
-               hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-               hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-               break;
-
-       case SND_SOC_DAPM_PRE_PMD:
-               /* Short the output */
-               hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
-               /* Disable the output stage */
-               hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-
-               /* Clamp the outputs and power down input */
-               hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP |
-                       WM8900_REG_HPCTL1_HP_CLAMP_OP;
-               hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA;
-               snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1);
-               break;
-
-       case SND_SOC_DAPM_POST_PMD:
-               /* Disable everything */
-               snd_soc_write(codec, WM8900_REG_HPCTL1, 0);
-               break;
-
-       default:
-               BUG();
+       isSPKon = on;
+       if (on) {
+#ifdef SPK_CON
+               gpio_set_value(SPK_CON, GPIO_HIGH);
+#endif
+       } else {
+#ifdef SPK_CON
+               gpio_set_value(SPK_CON, GPIO_LOW);
+#endif
        }
-
-       return 0;
 }
 
-static const DECLARE_TLV_DB_SCALE(out_pga_tlv, -5700, 100, 0);
-
-static const DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 0);
-
-static const DECLARE_TLV_DB_SCALE(in_boost_tlv, -1200, 600, 0);
-
-static const DECLARE_TLV_DB_SCALE(in_pga_tlv, -1200, 100, 0);
-
-static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0);
-
-static const DECLARE_TLV_DB_SCALE(dac_tlv, -7200, 75, 1);
-
-static const DECLARE_TLV_DB_SCALE(adc_svol_tlv, -3600, 300, 0);
-
-static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1);
-
-static const char *mic_bias_level_txt[] = { "0.9*AVDD", "0.65*AVDD" };
-
-static const struct soc_enum mic_bias_level =
-SOC_ENUM_SINGLE(WM8900_REG_INCTL, 8, 2, mic_bias_level_txt);
-
-static const char *dac_mute_rate_txt[] = { "Fast", "Slow" };
-
-static const struct soc_enum dac_mute_rate =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 7, 2, dac_mute_rate_txt);
-
-static const char *dac_deemphasis_txt[] = {
-       "Disabled", "32kHz", "44.1kHz", "48kHz"
-};
-
-static const struct soc_enum dac_deemphasis =
-SOC_ENUM_SINGLE(WM8900_REG_DACCTRL, 4, 4, dac_deemphasis_txt);
-
-static const char *adc_hpf_cut_txt[] = {
-       "Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"
-};
-
-static const struct soc_enum adc_hpf_cut =
-SOC_ENUM_SINGLE(WM8900_REG_ADCCTRL, 5, 4, adc_hpf_cut_txt);
-
-static const char *lr_txt[] = {
-       "Left", "Right"
-};
-
-static const struct soc_enum aifl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 15, 2, lr_txt);
-
-static const struct soc_enum aifr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO1, 14, 2, lr_txt);
-
-static const struct soc_enum dacl_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 15, 2, lr_txt);
+EXPORT_SYMBOL_GPL(codec_set_spk);
 
-static const struct soc_enum dacr_src =
-SOC_ENUM_SINGLE(WM8900_REG_AUDIO2, 14, 2, lr_txt);
-
-static const char *sidetone_txt[] = {
-       "Disabled", "Left ADC", "Right ADC"
-};
+static void wm8900_powerdown(void)
+{
+       printk("Power down wm8900\n");
+#ifndef WM8900_NO_POWEROFF
+       gpio_set_value(RK29_PIN1_PD6, GPIO_LOW);
+#endif
 
-static const struct soc_enum dacl_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 2, 3, sidetone_txt);
-
-static const struct soc_enum dacr_sidetone =
-SOC_ENUM_SINGLE(WM8900_REG_SIDETONE, 0, 3, sidetone_txt);
-
-static const struct snd_kcontrol_new wm8900_snd_controls[] = {
-SOC_ENUM("Mic Bias Level", mic_bias_level),
-
-SOC_SINGLE_TLV("Left Input PGA Volume", WM8900_REG_LINVOL, 0, 31, 0,
-              in_pga_tlv),
-SOC_SINGLE("Left Input PGA Switch", WM8900_REG_LINVOL, 6, 1, 1),
-SOC_SINGLE("Left Input PGA ZC Switch", WM8900_REG_LINVOL, 7, 1, 0),
-
-SOC_SINGLE_TLV("Right Input PGA Volume", WM8900_REG_RINVOL, 0, 31, 0,
-              in_pga_tlv),
-SOC_SINGLE("Right Input PGA Switch", WM8900_REG_RINVOL, 6, 1, 1),
-SOC_SINGLE("Right Input PGA ZC Switch", WM8900_REG_RINVOL, 7, 1, 0),
-
-SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1),
-SOC_ENUM("DAC Mute Rate", dac_mute_rate),
-SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0),
-SOC_ENUM("DAC Deemphasis", dac_deemphasis),
-SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL,
-          12, 1, 0),
-
-SOC_SINGLE("ADC HPF Switch", WM8900_REG_ADCCTRL, 8, 1, 0),
-SOC_ENUM("ADC HPF Cut-Off", adc_hpf_cut),
-SOC_DOUBLE("ADC Invert Switch", WM8900_REG_ADCCTRL, 1, 0, 1, 0),
-SOC_SINGLE_TLV("Left ADC Sidetone Volume", WM8900_REG_SIDETONE, 9, 12, 0,
-              adc_svol_tlv),
-SOC_SINGLE_TLV("Right ADC Sidetone Volume", WM8900_REG_SIDETONE, 5, 12, 0,
-              adc_svol_tlv),
-SOC_ENUM("Left Digital Audio Source", aifl_src),
-SOC_ENUM("Right Digital Audio Source", aifr_src),
-
-SOC_SINGLE_TLV("DAC Input Boost Volume", WM8900_REG_AUDIO2, 10, 4, 0,
-              dac_boost_tlv),
-SOC_ENUM("Left DAC Source", dacl_src),
-SOC_ENUM("Right DAC Source", dacr_src),
-SOC_ENUM("Left DAC Sidetone", dacl_sidetone),
-SOC_ENUM("Right DAC Sidetone", dacr_sidetone),
-SOC_DOUBLE("DAC Invert Switch", WM8900_REG_DACCTRL, 1, 0, 1, 0),
-
-SOC_DOUBLE_R_TLV("Digital Playback Volume",
-                WM8900_REG_LDAC_DV, WM8900_REG_RDAC_DV,
-                1, 96, 0, dac_tlv),
-SOC_DOUBLE_R_TLV("Digital Capture Volume",
-                WM8900_REG_LADC_DV, WM8900_REG_RADC_DV, 1, 119, 0, adc_tlv),
-
-SOC_SINGLE_TLV("LINPUT3 Bypass Volume", WM8900_REG_LOUTMIXCTL1, 4, 7, 0,
-              out_mix_tlv),
-SOC_SINGLE_TLV("RINPUT3 Bypass Volume", WM8900_REG_ROUTMIXCTL1, 4, 7, 0,
-              out_mix_tlv),
-SOC_SINGLE_TLV("Left AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 4, 7, 0,
-              out_mix_tlv),
-SOC_SINGLE_TLV("Right AUX Bypass Volume", WM8900_REG_AUXOUT_CTL, 0, 7, 0,
-              out_mix_tlv),
-
-SOC_SINGLE_TLV("LeftIn to RightOut Mixer Volume", WM8900_REG_BYPASS1, 0, 7, 0,
-              out_mix_tlv),
-SOC_SINGLE_TLV("LeftIn to LeftOut Mixer Volume", WM8900_REG_BYPASS1, 4, 7, 0,
-              out_mix_tlv),
-SOC_SINGLE_TLV("RightIn to LeftOut Mixer Volume", WM8900_REG_BYPASS2, 0, 7, 0,
-              out_mix_tlv),
-SOC_SINGLE_TLV("RightIn to RightOut Mixer Volume", WM8900_REG_BYPASS2, 4, 7, 0,
-              out_mix_tlv),
-
-SOC_SINGLE_TLV("IN2L Boost Volume", WM8900_REG_INBOOSTMIX1, 0, 3, 0,
-              in_boost_tlv),
-SOC_SINGLE_TLV("IN3L Boost Volume", WM8900_REG_INBOOSTMIX1, 4, 3, 0,
-              in_boost_tlv),
-SOC_SINGLE_TLV("IN2R Boost Volume", WM8900_REG_INBOOSTMIX2, 0, 3, 0,
-              in_boost_tlv),
-SOC_SINGLE_TLV("IN3R Boost Volume", WM8900_REG_INBOOSTMIX2, 4, 3, 0,
-              in_boost_tlv),
-SOC_SINGLE_TLV("Left AUX Boost Volume", WM8900_REG_AUXBOOST, 4, 3, 0,
-              in_boost_tlv),
-SOC_SINGLE_TLV("Right AUX Boost Volume", WM8900_REG_AUXBOOST, 0, 3, 0,
-              in_boost_tlv),
-
-SOC_DOUBLE_R_TLV("LINEOUT1 Volume", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
-              0, 63, 0, out_pga_tlv),
-SOC_DOUBLE_R("LINEOUT1 Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
-            6, 1, 1),
-SOC_DOUBLE_R("LINEOUT1 ZC Switch", WM8900_REG_LOUT1CTL, WM8900_REG_ROUT1CTL,
-            7, 1, 0),
-
-SOC_DOUBLE_R_TLV("LINEOUT2 Volume",
-                WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL,
-                0, 63, 0, out_pga_tlv),
-SOC_DOUBLE_R("LINEOUT2 Switch",
-            WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 6, 1, 1),
-SOC_DOUBLE_R("LINEOUT2 ZC Switch",
-            WM8900_REG_LOUT2CTL, WM8900_REG_ROUT2CTL, 7, 1, 0),
-SOC_SINGLE("LINEOUT2 LP -12dB", WM8900_REG_LOUTMIXCTL1,
-          0, 1, 1),
+       snd_soc_write(wm8900_codec, WM8900_REG_POWER1, 0x210D);
 
-};
-
-static const struct snd_kcontrol_new wm8900_dapm_loutput2_control =
-SOC_DAPM_SINGLE("LINEOUT2L Switch", WM8900_REG_POWER3, 6, 1, 0);
+       if (wm8900_current_status != WM8900_IS_SHUTDOWN) {
+#ifdef SPK_CON
+               gpio_set_value(SPK_CON, GPIO_LOW);
+#endif
+               msleep(20);
+               snd_soc_write(wm8900_codec, WM8900_REG_RESET, 0);
+               wm8900_current_status = WM8900_IS_SHUTDOWN;
+       }
+}
 
-static const struct snd_kcontrol_new wm8900_dapm_routput2_control =
-SOC_DAPM_SINGLE("LINEOUT2R Switch", WM8900_REG_POWER3, 5, 1, 0);
+static void wm8900_set_hw(struct snd_soc_codec *codec)
+{
+       u16 reg;
 
-static const struct snd_kcontrol_new wm8900_loutmix_controls[] = {
-SOC_DAPM_SINGLE("LINPUT3 Bypass Switch", WM8900_REG_LOUTMIXCTL1, 7, 1, 0),
-SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 7, 1, 0),
-SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 7, 1, 0),
-SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 3, 1, 0),
-SOC_DAPM_SINGLE("DACL Switch", WM8900_REG_LOUTMIXCTL1, 8, 1, 0),
-};
+       if (wm8900_current_status & WM8900_IS_STARTUP)
+               return;
+
+       printk("Power up wm8900\n");
+//CLK , PATH, VOL,POW.
+       
+       snd_soc_write(codec, WM8900_REG_HPCTL1, 0x30);
+       snd_soc_write(codec, WM8900_REG_POWER1, 0x0100);
+       snd_soc_write(codec, WM8900_REG_POWER3, 0x60);
+       snd_soc_write(codec, WM8900_REG_POWER1, 0x0101);
+       msleep(400);
+       snd_soc_write(codec, WM8900_REG_POWER1, 0x0109);
+       snd_soc_write(codec, WM8900_REG_ADDCTL, 0x02);
+       snd_soc_write(codec, WM8900_REG_POWER1, 0x09);
+       snd_soc_write(codec, WM8900_REG_POWER3, 0xEF);
+       snd_soc_write(codec, WM8900_REG_DACCTRL, WM8900_REG_DACCTRL_MUTE);
+       snd_soc_write(codec, WM8900_REG_LOUTMIXCTL1, 0x150);
+       snd_soc_write(codec, WM8900_REG_ROUTMIXCTL1, 0x150);
+
+       snd_soc_write(codec, WM8900_REG_HPCTL1, 0xB0);
+       snd_soc_write(codec, WM8900_REG_HPCTL1, 0xF0);
+       snd_soc_write(codec, WM8900_REG_HPCTL1, 0xC0);
+
+       //for recorder
+       snd_soc_write(codec, WM8900_REG_POWER1, 0x210D);
+       snd_soc_write(codec, WM8900_REG_POWER2, 0xC1AF);
+
+       snd_soc_write(codec, WM8900_REG_LADC_DV, 0x01C0);
+       snd_soc_write(codec, WM8900_REG_RADC_DV, 0x01C0);
+
+       snd_soc_write(codec, WM8900_REG_INCTL, 0x0040);
+
+       snd_soc_write(codec, WM8900_REG_LINVOL, 0x011A);
+       snd_soc_write(codec, WM8900_REG_RINVOL, 0x011A);
+       snd_soc_write(codec, WM8900_REG_INBOOSTMIX1, 0x0042);
+       snd_soc_write(codec, WM8900_REG_INBOOSTMIX2, 0x0042);
+       snd_soc_write(codec, WM8900_REG_ADCPATH, 0x0055);
 
-static const struct snd_kcontrol_new wm8900_routmix_controls[] = {
-SOC_DAPM_SINGLE("RINPUT3 Bypass Switch", WM8900_REG_ROUTMIXCTL1, 7, 1, 0),
-SOC_DAPM_SINGLE("AUX Bypass Switch", WM8900_REG_AUXOUT_CTL, 3, 1, 0),
-SOC_DAPM_SINGLE("Left Input Mixer Switch", WM8900_REG_BYPASS1, 3, 1, 0),
-SOC_DAPM_SINGLE("Right Input Mixer Switch", WM8900_REG_BYPASS2, 7, 1, 0),
-SOC_DAPM_SINGLE("DACR Switch", WM8900_REG_ROUTMIXCTL1, 8, 1, 0),
-};
+       reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
 
-static const struct snd_kcontrol_new wm8900_linmix_controls[] = {
-SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INBOOSTMIX1, 2, 1, 1),
-SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INBOOSTMIX1, 6, 1, 1),
-SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 6, 1, 1),
-SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 6, 1, 0),
-};
+       reg &= ~WM8900_REG_DACCTRL_MUTE;
+       snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
 
-static const struct snd_kcontrol_new wm8900_rinmix_controls[] = {
-SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INBOOSTMIX2, 2, 1, 1),
-SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INBOOSTMIX2, 6, 1, 1),
-SOC_DAPM_SINGLE("AUX Switch", WM8900_REG_AUXBOOST, 2, 1, 1),
-SOC_DAPM_SINGLE("Input PGA Switch", WM8900_REG_ADCPATH, 2, 1, 0),
-};
+       snd_soc_write(codec, WM8900_REG_LOUT1CTL, 0x130);
+       snd_soc_write(codec, WM8900_REG_ROUT1CTL, 0x130);
 
-static const struct snd_kcontrol_new wm8900_linpga_controls[] = {
-SOC_DAPM_SINGLE("LINPUT1 Switch", WM8900_REG_INCTL, 6, 1, 0),
-SOC_DAPM_SINGLE("LINPUT2 Switch", WM8900_REG_INCTL, 5, 1, 0),
-SOC_DAPM_SINGLE("LINPUT3 Switch", WM8900_REG_INCTL, 4, 1, 0),
-};
+       /* Turn up vol slowly, for HP out pop noise */
 
-static const struct snd_kcontrol_new wm8900_rinpga_controls[] = {
-SOC_DAPM_SINGLE("RINPUT1 Switch", WM8900_REG_INCTL, 2, 1, 0),
-SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0),
-SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0),
-};
+       for (reg = 0; reg <= 0x33; reg += 0x10) {
+                       snd_soc_write(codec, WM8900_REG_LOUT2CTL, 0x100 + reg);
+                       snd_soc_write(codec, WM8900_REG_ROUT2CTL, 0x100 + reg);
+                       msleep(5);
+       }
+       snd_soc_write(codec, WM8900_REG_LOUT2CTL, 0x133);
+       snd_soc_write(codec, WM8900_REG_ROUT2CTL, 0x133);
 
-static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" };
-
-static const struct soc_enum wm8900_lineout2_lp_mux =
-SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux);
-
-static const struct snd_kcontrol_new wm8900_lineout2_lp =
-SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux);
-
-static const struct snd_soc_dapm_widget wm8900_dapm_widgets[] = {
-
-/* Externally visible pins */
-SND_SOC_DAPM_OUTPUT("LINEOUT1L"),
-SND_SOC_DAPM_OUTPUT("LINEOUT1R"),
-SND_SOC_DAPM_OUTPUT("LINEOUT2L"),
-SND_SOC_DAPM_OUTPUT("LINEOUT2R"),
-SND_SOC_DAPM_OUTPUT("HP_L"),
-SND_SOC_DAPM_OUTPUT("HP_R"),
-
-SND_SOC_DAPM_INPUT("RINPUT1"),
-SND_SOC_DAPM_INPUT("LINPUT1"),
-SND_SOC_DAPM_INPUT("RINPUT2"),
-SND_SOC_DAPM_INPUT("LINPUT2"),
-SND_SOC_DAPM_INPUT("RINPUT3"),
-SND_SOC_DAPM_INPUT("LINPUT3"),
-SND_SOC_DAPM_INPUT("AUX"),
-
-SND_SOC_DAPM_VMID("VMID"),
-
-/* Input */
-SND_SOC_DAPM_MIXER("Left Input PGA", WM8900_REG_POWER2, 3, 0,
-                  wm8900_linpga_controls,
-                  ARRAY_SIZE(wm8900_linpga_controls)),
-SND_SOC_DAPM_MIXER("Right Input PGA", WM8900_REG_POWER2, 2, 0,
-                  wm8900_rinpga_controls,
-                  ARRAY_SIZE(wm8900_rinpga_controls)),
-
-SND_SOC_DAPM_MIXER("Left Input Mixer", WM8900_REG_POWER2, 5, 0,
-                  wm8900_linmix_controls,
-                  ARRAY_SIZE(wm8900_linmix_controls)),
-SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0,
-                  wm8900_rinmix_controls,
-                  ARRAY_SIZE(wm8900_rinmix_controls)),
-
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0),
-
-SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0),
-SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0),
-
-/* Output */
-SND_SOC_DAPM_DAC("DACL", "Left HiFi Playback", WM8900_REG_POWER3, 1, 0),
-SND_SOC_DAPM_DAC("DACR", "Right HiFi Playback", WM8900_REG_POWER3, 0, 0),
-
-SND_SOC_DAPM_PGA_E("Headphone Amplifier", WM8900_REG_POWER3, 7, 0, NULL, 0,
-                  wm8900_hp_event,
-                  SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-                  SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
-
-SND_SOC_DAPM_PGA("LINEOUT1L PGA", WM8900_REG_POWER2, 8, 0, NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT1R PGA", WM8900_REG_POWER2, 7, 0, NULL, 0),
-
-SND_SOC_DAPM_MUX("LINEOUT2 LP", SND_SOC_NOPM, 0, 0, &wm8900_lineout2_lp),
-SND_SOC_DAPM_PGA("LINEOUT2L PGA", WM8900_REG_POWER3, 6, 0, NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2R PGA", WM8900_REG_POWER3, 5, 0, NULL, 0),
-
-SND_SOC_DAPM_MIXER("Left Output Mixer", WM8900_REG_POWER3, 3, 0,
-                  wm8900_loutmix_controls,
-                  ARRAY_SIZE(wm8900_loutmix_controls)),
-SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0,
-                  wm8900_routmix_controls,
-                  ARRAY_SIZE(wm8900_routmix_controls)),
-};
+       msleep(20);
 
-/* Target, Path, Source */
-static const struct snd_soc_dapm_route audio_map[] = {
-/* Inputs */
-{"Left Input PGA", "LINPUT1 Switch", "LINPUT1"},
-{"Left Input PGA", "LINPUT2 Switch", "LINPUT2"},
-{"Left Input PGA", "LINPUT3 Switch", "LINPUT3"},
-
-{"Right Input PGA", "RINPUT1 Switch", "RINPUT1"},
-{"Right Input PGA", "RINPUT2 Switch", "RINPUT2"},
-{"Right Input PGA", "RINPUT3 Switch", "RINPUT3"},
-
-{"Left Input Mixer", "LINPUT2 Switch", "LINPUT2"},
-{"Left Input Mixer", "LINPUT3 Switch", "LINPUT3"},
-{"Left Input Mixer", "AUX Switch", "AUX"},
-{"Left Input Mixer", "Input PGA Switch", "Left Input PGA"},
-
-{"Right Input Mixer", "RINPUT2 Switch", "RINPUT2"},
-{"Right Input Mixer", "RINPUT3 Switch", "RINPUT3"},
-{"Right Input Mixer", "AUX Switch", "AUX"},
-{"Right Input Mixer", "Input PGA Switch", "Right Input PGA"},
-
-{"ADCL", NULL, "Left Input Mixer"},
-{"ADCR", NULL, "Right Input Mixer"},
-
-/* Outputs */
-{"LINEOUT1L", NULL, "LINEOUT1L PGA"},
-{"LINEOUT1L PGA", NULL, "Left Output Mixer"},
-{"LINEOUT1R", NULL, "LINEOUT1R PGA"},
-{"LINEOUT1R PGA", NULL, "Right Output Mixer"},
-
-{"LINEOUT2L PGA", NULL, "Left Output Mixer"},
-{"LINEOUT2 LP", "Disabled", "LINEOUT2L PGA"},
-{"LINEOUT2 LP", "Enabled", "Left Output Mixer"},
-{"LINEOUT2L", NULL, "LINEOUT2 LP"},
-
-{"LINEOUT2R PGA", NULL, "Right Output Mixer"},
-{"LINEOUT2 LP", "Disabled", "LINEOUT2R PGA"},
-{"LINEOUT2 LP", "Enabled", "Right Output Mixer"},
-{"LINEOUT2R", NULL, "LINEOUT2 LP"},
-
-{"Left Output Mixer", "LINPUT3 Bypass Switch", "LINPUT3"},
-{"Left Output Mixer", "AUX Bypass Switch", "AUX"},
-{"Left Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
-{"Left Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
-{"Left Output Mixer", "DACL Switch", "DACL"},
-
-{"Right Output Mixer", "RINPUT3 Bypass Switch", "RINPUT3"},
-{"Right Output Mixer", "AUX Bypass Switch", "AUX"},
-{"Right Output Mixer", "Left Input Mixer Switch", "Left Input Mixer"},
-{"Right Output Mixer", "Right Input Mixer Switch", "Right Input Mixer"},
-{"Right Output Mixer", "DACR Switch", "DACR"},
-
-/* Note that the headphone output stage needs to be connected
- * externally to LINEOUT2 via DC blocking capacitors.  Other
- * configurations are not supported.
- *
- * Note also that left and right headphone paths are treated as a
- * mono path.
- */
-{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
-{"Headphone Amplifier", NULL, "LINEOUT2 LP"},
-{"HP_L", NULL, "Headphone Amplifier"},
-{"HP_R", NULL, "Headphone Amplifier"},
-};
+#ifdef SPK_CON
+       if (isSPKon) {
+               gpio_set_value(SPK_CON, GPIO_HIGH);
+       }
+#endif
+#ifndef WM8900_NO_POWEROFF
+       msleep(350);
+       gpio_set_value(RK29_PIN1_PD6, GPIO_HIGH);
+#endif
+       wm8900_current_status |= WM8900_IS_STARTUP;
+}
 
-static int wm8900_add_widgets(struct snd_soc_codec *codec)
+static void wm8900_work(struct work_struct *work)
 {
+<<<<<<< HEAD
        struct snd_soc_dapm_context *dapm = &codec->dapm;
 
        snd_soc_dapm_new_controls(dapm, wm8900_dapm_widgets,
@@ -616,6 +350,27 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec)
        snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
        return 0;
+=======
+        WM8900_DBG("Enter::wm8900_work : wm8900_work_type = %d\n", wm8900_work_type);
+
+        switch (wm8900_work_type) {
+        case WM8900_WORK_POWERDOWN_PLAYBACK :
+                break;
+        case WM8900_WORK_POWERDOWN_CAPTURE:
+                snd_soc_write(wm8900_codec, WM8900_REG_POWER1, 0x210D);
+                break;
+        case WM8900_WORK_POWERDOWN_PLAYBACK_CAPTURE:
+                wm8900_powerdown();
+                break;
+        case WM8900_WORK_HW_SET:
+                wm8900_set_hw(wm8900_codec);
+                break;
+        default:
+                break;
+        }
+
+        wm8900_work_type = WM8900_WORK_NULL;
+>>>>>>> parent of 15f7fab... temp revert rk change
 }
 
 static int wm8900_hw_params(struct snd_pcm_substream *substream,
@@ -626,6 +381,8 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_codec *codec = rtd->codec;
        u16 reg;
 
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+
        reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
 
        switch (params_format(params)) {
@@ -646,17 +403,6 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
 
        snd_soc_write(codec, WM8900_REG_AUDIO1, reg);
 
-       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
-
-               if (params_rate(params) <= 24000)
-                       reg |= WM8900_REG_DACCTRL_DAC_SB_FILT;
-               else
-                       reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT;
-
-               snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
-       }
-
        return 0;
 }
 
@@ -680,8 +426,10 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
        unsigned int K, Ndiv, Nmod, target;
        unsigned int div;
 
-       BUG_ON(!Fout);
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
 
+       BUG_ON(!Fout);
+        
        /* The FLL must run at 90-100MHz which is then scaled down to
         * the output value by FLLCLK_DIV. */
        target = Fout;
@@ -744,6 +492,8 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
        struct _fll_div fll_div;
        unsigned int reg;
 
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+
        if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out)
                return 0;
 
@@ -811,6 +561,9 @@ reenable:
 static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
                int source, unsigned int freq_in, unsigned int freq_out)
 {
+
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+
        return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out);
 }
 
@@ -820,6 +573,8 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        unsigned int reg;
 
+       WM8900_DBG("Enter:%s, %d, div_id=%d, div=%d \n", __FUNCTION__, __LINE__, div_id, div);
+
        switch (div_id) {
        case WM8900_BCLK_DIV:
                reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
@@ -870,6 +625,8 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        unsigned int clocking1, aif1, aif3, aif4;
 
+       WM8900_DBG("Enter:%s, %d, fmt=0x%08X \n", __FUNCTION__, __LINE__, fmt);
+
        clocking1 = snd_soc_read(codec, WM8900_REG_CLOCKING1);
        aif1 = snd_soc_read(codec, WM8900_REG_AUDIO1);
        aif3 = snd_soc_read(codec, WM8900_REG_AUDIO3);
@@ -979,24 +736,106 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
 
 static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 {
-       struct snd_soc_codec *codec = codec_dai->codec;
-       u16 reg;
+       WM8900_DBG("Enter:%s, %d , mute = %d \n", __FUNCTION__, __LINE__, mute);
 
-       reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
+       return 0;
+}
 
-       if (mute)
-               reg |= WM8900_REG_DACCTRL_MUTE;
-       else
-               reg &= ~WM8900_REG_DACCTRL_MUTE;
+static int wm8900_startup(struct snd_pcm_substream *substream,
+                         struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_device *socdev = rtd->socdev;
+       struct snd_soc_codec *codec = socdev->card->codec;
+       struct snd_soc_dai_link *machine = rtd->dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
 
-       snd_soc_write(codec, WM8900_REG_DACCTRL, reg);
+       WM8900_DBG("Enter::%s----%d substream->stream:%s \n",__FUNCTION__,__LINE__,
+                  substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE");
+
+       cancel_delayed_work_sync(&delayed_work);
+       wm8900_work_type = WM8900_WORK_NULL;
+
+       wm8900_set_hw(codec);
+
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE ||
+            codec_dai->capture.active) {
+               snd_soc_write(codec, WM8900_REG_POWER1, 0x211D);
+       } else if (!codec_dai->capture.active) {
+               snd_soc_write(codec, WM8900_REG_POWER1, 0x210D);
+       }
+
+       return 0;
+}
+
+static void wm8900_shutdown(struct snd_pcm_substream *substream,
+                           struct snd_soc_dai *dai)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai_link *machine = rtd->dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
+
+       WM8900_DBG("Enter::%s----%d substream->stream:%s \n",__FUNCTION__,__LINE__,
+                  substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE");
+
+       if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
+           wm8900_work_type == WM8900_WORK_NULL) {
+               cancel_delayed_work_sync(&delayed_work);
+               wm8900_work_type = WM8900_WORK_POWERDOWN_CAPTURE;
+               queue_delayed_work(wm8900_workq, &delayed_work,
+                       msecs_to_jiffies(3000));
+       }
+#ifdef WM8900_NO_POWEROFF
+       return; /* Let codec not going to power off for pop noise */
+#endif
+
+       if (!codec_dai->capture.active && !codec_dai->playback.active) {
+
+               cancel_delayed_work_sync(&delayed_work);
+               wm8900_work_type = WM8900_WORK_NULL;
+
+               /* If codec is already shutdown, return */
+               if (wm8900_current_status == WM8900_IS_SHUTDOWN)
+                       return;
+
+               WM8900_DBG("Is going to power down wm8900\n");
+
+               wm8900_work_type = WM8900_WORK_POWERDOWN_PLAYBACK_CAPTURE;
+
+               /* If codec is useless, queue work to close it */
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+                       queue_delayed_work(wm8900_workq, &delayed_work,
+                               msecs_to_jiffies(1000));
+               } else {
+                       queue_delayed_work(wm8900_workq, &delayed_work,
+                               msecs_to_jiffies(3000));
+               }
+       }
+}
+
+static int wm8900_trigger(struct snd_pcm_substream *substream,
+                         int status,
+                         struct snd_soc_dai *dai)
+{      
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct snd_soc_dai_link *machine = rtd->dai;
+       struct snd_soc_dai *codec_dai = machine->codec_dai;
+
+       WM8900_DBG("Enter::%s----%d status = %d substream->stream:%s \n",__FUNCTION__, __LINE__, status,
+                  substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? "PLAYBACK":"CAPTURE");      
+
+       if(status == 1 || status == 0){
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK){
+                       codec_dai->playback.active = status;
+               }else{
+                       codec_dai->capture.active = status;
+               }
+       }
 
        return 0;
 }
 
-#define WM8900_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
-                     SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
-                     SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
+#define WM8900_RATES SNDRV_PCM_RATE_44100
 
 #define WM8900_PCM_FORMATS \
        (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
@@ -1008,6 +847,9 @@ static struct snd_soc_dai_ops wm8900_dai_ops = {
        .set_pll        = wm8900_set_dai_pll,
        .set_fmt        = wm8900_set_dai_fmt,
        .digital_mute   = wm8900_digital_mute,
+       .startup        = wm8900_startup,
+       .shutdown       = wm8900_shutdown,
+       .trigger        = wm8900_trigger,
 };
 
 static struct snd_soc_dai_driver wm8900_dai = {
@@ -1034,6 +876,11 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
 {
        u16 reg;
 
+       WM8900_DBG("Enter:%s, %d, level=0x%08X \n", __FUNCTION__, __LINE__, level);
+
+       codec->bias_level = level;
+       return 0;
+
        switch (level) {
        case SND_SOC_BIAS_ON:
                /* Enable thermal shutdown */
@@ -1118,7 +965,12 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
                             WM8900_REG_POWER2_SYSCLK_ENA);
                break;
        }
+<<<<<<< HEAD
        codec->dapm.bias_level = level;
+=======
+
+       codec->bias_level = level;
+>>>>>>> parent of 15f7fab... temp revert rk change
        return 0;
 }
 
@@ -1129,6 +981,15 @@ static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
        int fll_in  = wm8900->fll_in;
        int ret;
 
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+
+       cancel_delayed_work_sync(&delayed_work);
+       wm8900_work_type = WM8900_WORK_NULL;
+
+#ifdef WM8900_NO_POWEROFF
+       wm8900_powerdown();
+#endif
+
        /* Stop the FLL in an orderly fashion */
        ret = wm8900_set_fll(codec, 0, 0, 0);
        if (ret != 0) {
@@ -1147,17 +1008,12 @@ static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
 static int wm8900_resume(struct snd_soc_codec *codec)
 {
        struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
-       u16 *cache;
-       int i, ret;
-
-       cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults),
-                       GFP_KERNEL);
 
-       wm8900_reset(codec);
        wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
        /* Restart the FLL? */
        if (wm8900->fll_out) {
+               int ret;
                int fll_out = wm8900->fll_out;
                int fll_in  = wm8900->fll_in;
 
@@ -1171,20 +1027,48 @@ static int wm8900_resume(struct snd_soc_codec *codec)
                }
        }
 
+<<<<<<< HEAD
        if (cache) {
                for (i = 0; i < WM8900_MAXREG; i++)
                        snd_soc_write(codec, i, cache[i]);
                kfree(cache);
        } else
                dev_err(codec->dev, "Unable to allocate register cache\n");
+=======
+#ifdef WM8900_NO_POWEROFF
+       if (wm8900_current_status == WM8900_IS_SHUTDOWN) {
+
+               cancel_delayed_work_sync(&delayed_work);
+               wm8900_work_type = WM8900_WORK_HW_SET;
+               queue_delayed_work(wm8900_workq, &delayed_work,
+                                  msecs_to_jiffies(1000));
+       }
+#endif
+>>>>>>> parent of 15f7fab... temp revert rk change
 
        return 0;
 }
 
+<<<<<<< HEAD
 static int wm8900_probe(struct snd_soc_codec *codec)
 {
        struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
        int ret = 0, reg;
+=======
+static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
+                                     const struct i2c_device_id *id)
+{
+       struct wm8900_priv *wm8900;
+       struct snd_soc_codec *codec;
+       unsigned int reg;
+       int ret;
+
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+        
+       wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
+       if (wm8900 == NULL)
+               return -ENOMEM;
+>>>>>>> parent of 15f7fab... temp revert rk change
 
        ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type);
        if (ret != 0) {
@@ -1203,6 +1087,7 @@ static int wm8900_probe(struct snd_soc_codec *codec)
        /* Turn the chip on */
        wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
+<<<<<<< HEAD
        /* Latch the volume update bits */
        snd_soc_write(codec, WM8900_REG_LINVOL,
                      snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
@@ -1231,6 +1116,9 @@ static int wm8900_probe(struct snd_soc_codec *codec)
        snd_soc_add_controls(codec, wm8900_snd_controls,
                                ARRAY_SIZE(wm8900_snd_controls));
        wm8900_add_widgets(codec);
+=======
+       wm8900_dai.dev = &i2c->dev;
+>>>>>>> parent of 15f7fab... temp revert rk change
 
        return 0;
 }
@@ -1276,10 +1164,17 @@ static int __devinit wm8900_spi_probe(struct spi_device *spi)
 
 static int __devexit wm8900_spi_remove(struct spi_device *spi)
 {
+<<<<<<< HEAD
        snd_soc_unregister_codec(&spi->dev);
        kfree(spi_get_drvdata(spi));
        return 0;
 }
+=======
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+        
+       snd_soc_unregister_dai(&wm8900_dai);
+       snd_soc_unregister_codec(wm8900_codec);
+>>>>>>> parent of 15f7fab... temp revert rk change
 
 static struct spi_driver wm8900_spi_driver = {
        .driver = {
@@ -1319,6 +1214,12 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+void wm8900_i2c_shutdown(struct i2c_client *client)
+{
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+       wm8900_powerdown();
+}
+
 static const struct i2c_device_id wm8900_i2c_id[] = {
        { "wm8900", 0 },
        { }
@@ -1330,8 +1231,14 @@ static struct i2c_driver wm8900_i2c_driver = {
                .name = "wm8900-codec",
                .owner = THIS_MODULE,
        },
+<<<<<<< HEAD
        .probe =    wm8900_i2c_probe,
        .remove =   __devexit_p(wm8900_i2c_remove),
+=======
+       .probe = wm8900_i2c_probe,
+       .remove = __devexit_p(wm8900_i2c_remove),
+       .shutdown = wm8900_i2c_shutdown,
+>>>>>>> parent of 15f7fab... temp revert rk change
        .id_table = wm8900_i2c_id,
 };
 #endif
@@ -1339,6 +1246,7 @@ static struct i2c_driver wm8900_i2c_driver = {
 static int __init wm8900_modinit(void)
 {
        int ret = 0;
+<<<<<<< HEAD
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&wm8900_i2c_driver);
        if (ret != 0) {
@@ -1353,6 +1261,48 @@ static int __init wm8900_modinit(void)
                       ret);
        }
 #endif
+=======
+
+#ifndef WM8900_NO_POWEROFF
+       gpio_set_value(RK29_PIN1_PD6, GPIO_LOW);
+#endif
+
+       WM8900_DBG("Enter:%s, %d \n", __FUNCTION__, __LINE__);
+        
+       if (!wm8900_codec) {
+               dev_err(&pdev->dev, "I2C client not yet instantiated\n");
+               return -ENODEV;
+       }
+
+#if defined(SPK_CON)
+       gpio_request(SPK_CON,NULL);
+       gpio_direction_output(SPK_CON, GPIO_LOW);
+#endif
+
+       codec = wm8900_codec;
+       socdev->card->codec = codec;
+
+       /* Register pcms */
+       ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to register new PCMs\n");
+               goto pcm_err;
+       }
+
+       wm8900_workq = create_freezeable_workqueue("wm8900");
+       if (wm8900_workq == NULL) {
+               kfree(codec);
+               return -ENOMEM;
+       }
+
+#ifdef WM8900_NO_POWEROFF
+       wm8900_set_hw(codec);
+#endif
+
+       return ret;
+
+pcm_err:
+>>>>>>> parent of 15f7fab... temp revert rk change
        return ret;
 }
 module_init(wm8900_modinit);
index 039b9532b270cb8c1bb300efd0d1a7f385d95aa4..d6af67fb39f7ee7e19c104b9dab65d76fffa1874 100644 (file)
@@ -165,6 +165,7 @@ static unsigned int do_i2c_read(struct snd_soc_codec *codec,
        xfer[0].flags = 0;
        xfer[0].len = reglen;
        xfer[0].buf = reg;
+       xfer[0].scl_rate = 100 * 1000;
 
        /* Read data */
        xfer[1].addr = client->addr;