diff options
| author | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
|---|---|---|
| committer | Yuval Adam <_@yuv.al> | 2017-08-30 08:25:59 +0000 |
| commit | 8e4bff4cab0ddac6060645b0715210484d02ff40 (patch) | |
| tree | 3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/misc/sdiodev | |
Diffstat (limited to 'drivers/misc/sdiodev')
| -rw-r--r-- | drivers/misc/sdiodev/Kconfig | 23 | ||||
| -rw-r--r-- | drivers/misc/sdiodev/Makefile | 20 | ||||
| -rw-r--r-- | drivers/misc/sdiodev/sdio_dev.c | 1734 | ||||
| -rwxr-xr-x | drivers/misc/sdiodev/sdio_dev.h | 207 | ||||
| -rw-r--r-- | drivers/misc/sdiodev/sdio_dev_test.c | 1219 | ||||
| -rw-r--r-- | drivers/misc/sdiodev/sdio_dev_test.h | 47 |
6 files changed, 3250 insertions, 0 deletions
diff --git a/drivers/misc/sdiodev/Kconfig b/drivers/misc/sdiodev/Kconfig new file mode 100644 index 00000000..caf7eddb --- /dev/null +++ b/drivers/misc/sdiodev/Kconfig @@ -0,0 +1,23 @@ + +menu "SDIODEV modules" + +config SDIODEV + tristate "SPRD SDIO DEV SUPPORT" + ---help--- + PLEASE INSMOD THIS MODULE BEFORE OTHER SDIO DEV MODULES + +config SDIODEV_TEST + bool "SDIO DEV TEST" + default n + depends on SDIODEV + help + FOR RUN SDIODEV TEST CASE,DO NOT OPEN IT IN NORMAL MODE + +config WCN_EXTENSION + bool "WCN EXTENSION" + default n + depends on SDIODEV + help + FOR SUPPORTING MARLIN SS BRANCH + +endmenu diff --git a/drivers/misc/sdiodev/Makefile b/drivers/misc/sdiodev/Makefile new file mode 100644 index 00000000..3aa092ef --- /dev/null +++ b/drivers/misc/sdiodev/Makefile @@ -0,0 +1,20 @@ +#sdiodevhal +obj-$(CONFIG_SDIODEV) := sdiodevhal.o + +sdiodevhal-c-objs += sdio_dev.o + +ifeq ($(CONFIG_SDIODEV_TEST),y) +ccflags-y += -DSDIO_TEST_CASE6 +#SDIO_TEST_CASE1 +#SDIO_TEST_CASE2 +#SDIO_TEST_CASE4 +#SDIO_TEST_CASE5 +#SDIO_TEST_CASE6 +#SDIO_TEST_CASE7 +#SDIO_TEST_CASE8 +#SDIO_TEST_CASE9 +sdiodevhal-c-objs += sdio_dev_test.o +endif + +sdiodevhal-objs += $(sdiodevhal-c-objs) + diff --git a/drivers/misc/sdiodev/sdio_dev.c b/drivers/misc/sdiodev/sdio_dev.c new file mode 100644 index 00000000..b79a2bdf --- /dev/null +++ b/drivers/misc/sdiodev/sdio_dev.c @@ -0,0 +1,1734 @@ +/* + * Copyright (C) 2013 Spreadtrum Communications Inc. + * + * Filename : sdio_dev.c + * Abstract : This file is a implementation for itm sipc command/event function + * + * Authors : gaole.zhang + * + * + * 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 "sdio_dev.h" + +#if defined(CONFIG_SDIODEV_TEST) + +#include "sdio_dev_test.h" + +#endif + +static struct mutex g_sdio_func_lock; +static struct timeval ack_irq_time = {0}; +static int ack_gpio_status = 0; + +static int marlin_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id); +static void marlin_sdio_remove(struct sdio_func *func); +static int marlin_sdio_suspend(struct device *dev); +static int marlin_sdio_resume(struct device *dev); + +extern void set_bt_pm_func(void *wakeup,void *sleep); + +struct sdio_func *sprd_sdio_func[SDIODEV_MAX_FUNCS]; +struct sdio_func sdio_func_0; +SDIO_CHN_HANDLER sdio_tran_handle[17] = {0}; + +static struct sdio_data *sdio_data=NULL; +static int sdio_irq_num; +static int marlinwake_irq_num; + +static int marlin_sdio_ready_irq_num; + + +static struct wake_lock marlin_wakelock; +static struct wake_lock BT_AP_wakelock; + +static struct wake_lock marlinpub_wakelock; + + +static struct work_struct marlin_wq; +static struct work_struct marlinwake_wq; + +static bool ap_sdio_ready = 0; +static bool have_card = 0; +static MARLIN_SDIO_READY_T marlin_sdio_ready = {0}; + + + +static const struct sdio_device_id marlin_sdio_ids[] = { + {SDIO_DEVICE(MARLIN_VENDOR_ID, MARLIN_DEVICE_ID)}, + {}, +}; + +static const struct dev_pm_ops marlin_sdio_pm_ops = { + .suspend = marlin_sdio_suspend, + .resume = marlin_sdio_resume, +}; + +static struct sdio_driver marlin_sdio_driver = { + .probe = marlin_sdio_probe, + .remove = marlin_sdio_remove, + .name = "marlin_sdio", + .id_table = marlin_sdio_ids, + .drv = { + .pm = &marlin_sdio_pm_ops, + }, +}; + +static struct mmc_host *sdio_dev_host = NULL; +char *sync_data_ptr = NULL; +static int gpio_marlin_req_tag = 0; +static int gpio_marlinwake_tag = 0; + +static bool sdio_w_flag = 0; +//static bool req_marlin_wait_tag = 0; //0: don't wait 1: wait +//atomic_t req_marlin_wait_tag; +atomic_t gpioreq_need_pulldown; +static bool bt_wake_flag = 0; + +static bool marlin_bt_wake_flag = 0; + + +static struct completion marlin_ack = {0}; + +static SLEEP_POLICY_T sleep_para = {0}; +spinlock_t sleep_spinlock ; +MARLIN_PM_RESUME_WAIT_INIT(marlin_sdio_wait); + +/************************************************************************/ +typedef struct +{ + struct mutex func_lock; + struct early_suspend early_suspend; + atomic_t in_early_suspend; + atomic_t refcnt; +}mgr_suspend_t; + +#define SDIO_OS_LOCK() do{\ + if(1 == atomic_read(&g_mgr_suspend.in_early_suspend)) \ + {\ + mutex_lock(&(g_mgr_suspend.func_lock));\ + lock_flag = 1;\ + }else{\ + lock_flag = 0;\ + atomic_inc(&(g_mgr_suspend.refcnt));\ + }\ +}while(0) + +#define SDIO_OS_UNLOCK() do{\ + if(lock_flag){\ + mutex_unlock(&(g_mgr_suspend.func_lock));\ + }else{\ + atomic_dec(&(g_mgr_suspend.refcnt));}\ +}while(0) + + +mgr_suspend_t g_mgr_suspend = {0}; + +static void sdio_early_suspend(struct early_suspend *es) +{ + unsigned long timeout; + SDIOTRAN_ERR("[%s]enter\n", __func__); + timeout = jiffies + msecs_to_jiffies(3000); + atomic_set(&g_mgr_suspend.in_early_suspend, 1); + while(0 != atomic_read(&(g_mgr_suspend.refcnt)) ) + { + usleep_range(50, 100); + if (time_after(jiffies, timeout)) + { + SDIOTRAN_ERR("[%s][timeout 3000ms][EEROR]\n", __func__); + return; + } + } + SDIOTRAN_ERR("[%s]ok\n", __func__); + return; +} + +static void sdio_late_resume(struct early_suspend *es) +{ + atomic_set(&g_mgr_suspend.in_early_suspend, 0); + SDIOTRAN_ERR("[%s]ok\n", __func__); + return; +} + +int mgr_suspend_init(void ) +{ + int ret; + atomic_set(&g_mgr_suspend.refcnt, 0); + atomic_set(&g_mgr_suspend.in_early_suspend, 0); + mutex_init(&g_mgr_suspend.func_lock); + g_mgr_suspend.early_suspend.suspend = sdio_early_suspend; + g_mgr_suspend.early_suspend.resume = sdio_late_resume; + register_early_suspend(&g_mgr_suspend.early_suspend); + return 0; +} + +void mgr_suspend_defint(void ) +{ + unregister_early_suspend(&g_mgr_suspend.early_suspend); + return; +} + +/************************************************************************/ + +static int get_sdio_dev_func(struct sdio_func *func) +{ + if(SDIODEV_MAX_FUNCS <= func->num) + { + SDIOTRAN_ERR("func num err!!! func num is %d!!!",func->num); + return -1; + } + SDIOTRAN_DEBUG("func num is %d!!!",func->num); + + if (func->num == 1) + { + sdio_func_0.num = 0; + sdio_func_0.card = func->card; + sprd_sdio_func[0] = &sdio_func_0; + } + + sprd_sdio_func[func->num] = func; + + return 0; +} + +static int free_sdio_dev_func(struct sdio_func *func) +{ + if(SDIODEV_MAX_FUNCS <= func->num) + { + SDIOTRAN_ERR("func num err!!! func num is %d!!!",func->num); + return -1; + } + + sprd_sdio_func[0] = NULL; + sprd_sdio_func[func->num] = NULL; + sdio_func_0.num = 0; + sdio_func_0.card = NULL; + + return 0; + +} + +static int wakeup_slave_pin_init(void) +{ + int ret; + ret = gpio_request(sdio_data->wake_out,"marlin_wakeup"); + if (ret<0) + { + SDIOTRAN_ERR("req gpio sdio_data->wake_out = %d fail!!!",\ + sdio_data->wake_out); + return ret; + } + + ret = gpio_direction_output(sdio_data->wake_out,0); + if (ret) + { + SDIOTRAN_ERR("sdio_data->wake_out = %d input set fail!!!",\ + sdio_data->wake_out); + return ret; + } + + SDIOTRAN_ERR("req sdio_data->wake_out = %d succ!!!",\ + sdio_data->wake_out); + + return ret; +} +void gpio_timer_handler(unsigned long data) +{ + if(gpio_get_value(sdio_data->wake_ack)) + { + sleep_para.gpio_opt_tag = 1; + mod_timer(&(sleep_para.gpio_timer),\ + jiffies + msecs_to_jiffies(sleep_para.ack_high_time));// 250<300<2000-1500 + SDIOTRAN_ERR("ack high"); + } + else + { + sleep_para.gpio_opt_tag = 0; + SDIOTRAN_ERR("gpio_opt_tag=0\n" ); + } +} + +int fwdownload_fin = 0; + +int get_sprd_download_fin(void) +{ + return fwdownload_fin; +} +EXPORT_SYMBOL_GPL(get_sprd_download_fin); + +void set_sprd_download_fin(int dl_tag) +{ + marlin_sdio_ready.marlin_sdio_init_end_tag = 1; + return fwdownload_fin = dl_tag; +} +EXPORT_SYMBOL_GPL(set_sprd_download_fin); + +unsigned int irq_count_change = 0; +unsigned int irq_count_change_last = 0; +bool get_sprd_marlin_status(void) +{ + printk(KERN_INFO "irq_count_change:%d\n",irq_count_change); + printk(KERN_INFO "irq_count_change_last:%d\n",irq_count_change_last); + + if((irq_count_change == 0)&&(irq_count_change_last == 0)) + return 1; + else if(irq_count_change != irq_count_change_last) + { + irq_count_change_last = irq_count_change; + return 1; + } + else + return 0; +} +EXPORT_SYMBOL_GPL(get_sprd_marlin_status); + +atomic_t is_wlan_open; //0: wlan close, 1: wlan open +atomic_t set_marlin_cmplete; //0: not complete, 1: complete +int set_wlan_status(int status) +{ + atomic_set(&(is_wlan_open), status); + return 0; +} +EXPORT_SYMBOL_GPL(set_wlan_status); + +/*add start by sam.sun, 20150108, for get the screen status (on or off) + return: 1 screen on + 0 screen off +*/ +#define BRIGHTNESS_PATH "/sys/class/backlight/sprd_backlight/brightness" +int get_screen_status(void) +{ + struct file *file = NULL; + int is_screen_on = 1; + char * buf; //0~255 + mm_segment_t old_fs; + int size =0; + loff_t pos = 0; + + file=filp_open(BRIGHTNESS_PATH, O_RDONLY, 0); + if (IS_ERR(file)) + SDIOTRAN_ERR("Open file %s failed /n",BRIGHTNESS_PATH); + + + old_fs = get_fs(); + set_fs(KERNEL_DS); + + buf = (int *)kzalloc(4,GFP_KERNEL); + + vfs_read(file, buf, 3, &pos); + + size = strlen(buf); + + if( strncmp(buf,"0",(size-1))==0 ) + is_screen_on = 0; //screen off 224 + else + is_screen_on = 1; + + //SDIOTRAN_ERR("*brightness is %s, is_screen_on is %d\r",buf, is_screen_on); + kfree(buf); + filp_close(file, NULL); + set_fs(old_fs); + return is_screen_on; +} +/*add end by sam.sun, for get the screen status (on or off)*/ + +extern bool get_bt_state(void); // 1: bt open , 0: bt close +int set_marlin_wakeup(uint32 chn,uint32 user_id) +{ + //user_id: wifi=0x1;bt=0x2 +#if !defined(CONFIG_MARLIN_NO_SLEEP) + + int ret; + int flags; + int screen_status = 1; + int bt_state ; + SDIOTRAN_DEBUG("entry"); + + if(get_sprd_download_fin() != 1) + { + SDIOTRAN_ERR("marlin unready"); + return -1; + } + + /* when bt only, marlin will don't stay 2s wakeup; + so add for avoid bt ack 250ms high, then in below cases ap don't req cp and send data directly; + case1: first open wlan, then user_id = 1; + case2: send AT cmd or loop check, then user_id = 3; mdbg module has done re-try action + */ + if((1 == atomic_read(&(is_wlan_open))) && (1 == user_id) ) + { + if((gpio_get_value(sdio_data->wake_ack)) && (0 == sleep_para.gpio_opt_tag) ) + msleep(sleep_para.ack_high_time); + if(gpio_get_value(sdio_data->wake_ack)) + SDIOTRAN_ERR("err:bt req delay 300ms\n"); + atomic_set(&is_wlan_open, 0); // avoid repeat into this func + } + + //screen_status = get_screen_status(); // for wifi screen download + //bt_state = get_bt_state(); + + spin_lock_irqsave(&sleep_spinlock, flags); + //if((0 == sleep_para.gpio_opt_tag) ||((!screen_status) && (1 == user_id) && (!bt_state)) ) + if(0 == sleep_para.gpio_opt_tag) + { + if(gpio_get_value(sdio_data->wake_ack)) //bt ack 250ms + { + spin_unlock_irqrestore(&sleep_spinlock, flags); + SDIOTRAN_ERR("%d-high,user_id-%d \n", sdio_data->wake_ack,user_id); + return -2; + } + if(0 != ack_gpio_status) //bt ack low,then lose the marlinwake irq + { + spin_unlock_irqrestore(&sleep_spinlock, flags); + SDIOTRAN_ERR("ack_gpio_status-%d\n", ack_gpio_status); + return -2; + } + if(0 == atomic_read(&(set_marlin_cmplete))) //last wakeup don't complete + { + spin_unlock_irqrestore(&sleep_spinlock, flags); + SDIOTRAN_ERR("set_marlin_complete -%d\n", set_marlin_cmplete); + return -3; + } + + atomic_set(&(set_marlin_cmplete), 0); //invoid re-entry this func. + if((0x1 == user_id) ||(0x3 == user_id)) + { + sdio_w_flag = 1; + } + + if(0x2 == user_id) + { + bt_wake_flag = 1; + } + atomic_set(&gpioreq_need_pulldown, 1);//sleep_para.gpioreq_need_pulldown = 1; + + gpio_direction_output(sdio_data->wake_out,1); + spin_unlock_irqrestore(&sleep_spinlock, flags); + + SDIOTRAN_ERR("%d-1\n", sdio_data->wake_out ); + + if((0x1 == user_id) ||(0x3 == user_id)) + { + ret = wait_for_completion_timeout( &marlin_ack, msecs_to_jiffies(100) ); + if (ret == 0){ + atomic_set(&(set_marlin_cmplete), 1); + SDIOTRAN_ERR("marlin chn %d ack timeout, user_id-%d!!!",chn, user_id); + return -ETIMEDOUT;//timeout + } + } + } + else + { + spin_unlock_irqrestore(&sleep_spinlock, flags); + } + + atomic_set(&(set_marlin_cmplete), 1); +#endif + return 0; +} +EXPORT_SYMBOL_GPL(set_marlin_wakeup); + + +int set_marlin_sleep(uint32 chn,uint32 user_id) +{ + //user_id: wifi=0x1;bt=0x2 +#if !defined(CONFIG_MARLIN_NO_SLEEP) + SDIOTRAN_DEBUG("entry"); + if( atomic_read(&gpioreq_need_pulldown) )//if(sleep_para.gpioreq_need_pulldown) + { + gpio_direction_output(sdio_data->wake_out,0); + if((user_id == 0x1) ||(user_id == 0x3)) + { + sdio_w_flag = 0; + } + if(user_id == 0x2) + { + bt_wake_flag = 0; + } + atomic_set(&gpioreq_need_pulldown, 0);//sleep_para.gpioreq_need_pulldown = 0; + SDIOTRAN_ERR("gpio%d-0,user_id-%d\n", sdio_data->wake_out, user_id); + } +#endif + return 0; +} +EXPORT_SYMBOL_GPL(set_marlin_sleep); + + +/*only idle chn can be used for ap write*/ +int sdio_dev_chn_idle(uint32 chn) +{ + uint32 active_status; + uint8 status0,status1; + int err_ret; + + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + if(NULL == sprd_sdio_func[SDIODEV_FUNC_0]) + { + SDIOTRAN_ERR("func uninit!!!"); + return -1; + } + + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + status0 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x840,&err_ret); + + status1 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x841,&err_ret); + + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + active_status = (uint32)(status0) + ((uint32)(status1) << 8); + + if( BIT_0 & ( active_status >> chn )){ + SDIOTRAN_DEBUG("SDIO channel num = %x is active!!",chn); + return 0; //active + } + else{ + SDIOTRAN_DEBUG("SDIO channel num = %x is idle!!",chn); + return 1; //idle + } +} +EXPORT_SYMBOL_GPL(sdio_dev_chn_idle); + +#if defined(CONFIG_SDIODEV_TEST) + +/*only active chn can be readed*/ +int sdio_dev_get_read_chn(void) +{ + uint8 rw_flag0,rw_flag1; + uint8 status0,status1; + uint32 chn_status; + uint32 chn_rw_flag; + uint32 tmp; + int err_ret,read_chn; + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + status0 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x840,&err_ret); + + status1 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x841,&err_ret); + + rw_flag0 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x842,&err_ret); + + rw_flag1 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x843,&err_ret); + + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + chn_status = (uint32)(status0) + ((uint32)(status1) << 8); + chn_rw_flag = (uint32)(rw_flag0) + ((uint32)(rw_flag1) << 8); + + SDIOTRAN_DEBUG("ap recv: chn_status is 0x%x!!!",chn_status); + SDIOTRAN_DEBUG("ap read: chn_rw_flag is 0x%x!!!",chn_rw_flag); + + tmp = (chn_status&(~chn_rw_flag))&(0x0000ffff); + + for(read_chn=0;read_chn<16;read_chn++) + { + if(BIT_0 & (tmp>>read_chn)) + { + return read_chn; + } + } + return -1; + +} + + + +#else + +int sdio_dev_get_read_chn(void) +{ + uint8 chn_status; + int err_ret; + int lock_flag; + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + SDIO_OS_LOCK();//mutex_lock(&g_sdio_func_lock); + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + chn_status = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x841,&err_ret); + + while( chn_status == 0 ){ + chn_status = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x841,&err_ret); + } + + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_0]); + SDIO_OS_UNLOCK();//mutex_unlock(&g_sdio_func_lock); + SDIOTRAN_DEBUG("ap read: chn_status is 0x%x!!!",chn_status); + + if(chn_status == 0xff) + { + SDIOTRAN_ERR("Sdio Err!!!chn status 0x%x!!!",chn_status); + return -1; + } + else if(chn_status & SDIO_CHN_8) + return 8; + else if(chn_status & SDIO_CHN_9) + return 9; + else if(chn_status & SDIO_CHN_11) + return 11; + else if(chn_status & SDIO_CHN_12) + return 12; + else if(chn_status & SDIO_CHN_13) + return 13; + else if(chn_status & SDIO_CHN_14) + return 14; + else if(chn_status & SDIO_CHN_15) + return 15; + else + { + SDIOTRAN_ERR("Invalid sdio read chn!!!chn status 0x%x!!!",chn_status); + return -1; + } +} + +#endif +EXPORT_SYMBOL_GPL(sdio_dev_get_read_chn); + + +/*ONLY WIFI WILL USE THIS FUNC*/ +int sdio_chn_status(unsigned short chn, unsigned short *status) +{ + unsigned char status0 = 0; + unsigned char status1 = 0; + int err_ret; + int ret = 0; + int lock_flag; + SDIOTRAN_DEBUG("ENTRY"); + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + if(NULL == sprd_sdio_func[SDIODEV_FUNC_0]) + { + SDIOTRAN_ERR("func err"); + return -1; + } + SDIO_OS_LOCK();//mutex_lock(&g_sdio_func_lock); + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + if (0x00FF & chn) { + status0 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x840,&err_ret); + if (status0 == 0xFF){ + SDIOTRAN_ERR("sdio chn reg0 err"); + ret = -1; + } + } + + if (0xFF00 & chn) { + status1 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x841,&err_ret); + if (status1 == 0xFF){ + SDIOTRAN_ERR("sdio chn reg1 err"); + ret = -1; + } + } + + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_0]); + SDIO_OS_UNLOCK();//mutex_unlock(&g_sdio_func_lock); + *status = ( (status0+(status1 << 8)) & chn ); + + return ret; +} +EXPORT_SYMBOL_GPL(sdio_chn_status); + +int sdio_dev_get_chn_datalen(uint32 chn) +{ + uint32 usedata; + uint8 status0,status1,status2; + int err_ret; + int lock_flag; + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + if(NULL == sprd_sdio_func[SDIODEV_FUNC_0]) + { + SDIOTRAN_ERR("func uninit!!!"); + return -1; + } + SDIO_OS_LOCK();//mutex_lock(&g_sdio_func_lock); + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + status0 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],(0x800+ 4*chn),&err_ret); + + status1 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],(0x801+ 4*chn),&err_ret); + + status2 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],(0x802+ 4*chn),&err_ret); + + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_0]); + SDIO_OS_UNLOCK();//mutex_unlock(&g_sdio_func_lock); + usedata = ((uint32)(status0) ) + ((uint32)(status1) << 8) + ((uint32)(status2) << 16); + + if(status0 == 0xff || status1 == 0xff || status2 == 0xff) + { + SDIOTRAN_ERR("read err!!!"); + return -1; + } + + return usedata; + +} +EXPORT_SYMBOL_GPL(sdio_dev_get_chn_datalen); + + +int sdio_dev_write(uint32 chn,void* data_buf,uint32 count) +{ + int ret,data_len; + int lock_flag; + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + + if(NULL == sprd_sdio_func[SDIODEV_FUNC_1]) + { + SDIOTRAN_ERR("func uninit!!!"); + return -1; + } + + if(chn != 0 && chn != 1) + { + data_len = sdio_dev_get_chn_datalen(chn); + if(data_len < count || data_len <= 0) + { + SDIOTRAN_ERR("chn %d, len %d, cnt %d, err!!!",chn,data_len,count); + return -1; + } + } + SDIO_OS_LOCK();//mutex_lock(&g_sdio_func_lock); + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_1]); + + ret = sdio_memcpy_toio(sprd_sdio_func[SDIODEV_FUNC_1],chn,data_buf,count); + SDIOTRAN_DEBUG("chn %d send ok!!!",chn); + + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_1]); + SDIO_OS_UNLOCK();//mutex_unlock(&g_sdio_func_lock); + return ret; + +} +EXPORT_SYMBOL_GPL(sdio_dev_write); + + +int sdio_dev_read(uint32 chn,void* read_buf,uint32 *count) +{ + int err_ret,data_len; + int lock_flag; + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + + if(NULL == sprd_sdio_func[SDIODEV_FUNC_1]) + { + SDIOTRAN_ERR("func uninit!!!"); + return -1; + } + + data_len = sdio_dev_get_chn_datalen(chn); + if(data_len <= 0) + { + SDIOTRAN_ERR("chn %d,datelen %d err!!!",chn,data_len); + return -1; + } + SDIOTRAN_DEBUG("ap recv chn %d: read_datalen is 0x%x!!!",chn,data_len); + + SDIO_OS_LOCK();//mutex_lock(&g_sdio_func_lock); + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_1]); + err_ret = sdio_memcpy_fromio(sprd_sdio_func[SDIODEV_FUNC_1],read_buf,chn,data_len); + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_1]); + SDIO_OS_UNLOCK();//mutex_unlock(&g_sdio_func_lock); + if(NULL != count) + *count = data_len; + + return err_ret; + +} + +EXPORT_SYMBOL_GPL(sdio_dev_read); + +int sdio_read_wlan(uint32 chn,void* read_buf,uint32 *count) +{ + int err_ret,data_len; + data_len = 16384; + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + if(NULL == sprd_sdio_func[SDIODEV_FUNC_1]) + { + SDIOTRAN_ERR("func uninit!!!"); + return -1; + } + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_1]); + err_ret = sdio_memcpy_fromio(sprd_sdio_func[SDIODEV_FUNC_1],read_buf,chn,data_len); + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_1]); + if(NULL != count) + *count = data_len; + return err_ret; + +} + +EXPORT_SYMBOL_GPL(sdio_read_wlan); + +int sdiodev_readchn_init(uint32 chn,void* callback,bool with_para) +{ + SDIOTRAN_DEBUG("Param, chn = %d, callback = %p",chn,callback); + if(chn >= INVALID_SDIO_CHN) + { + SDIOTRAN_ERR("err input chn %d",chn); + return -1; + } + sdio_tran_handle[chn].chn = chn; + + if(with_para == 1) + { + sdio_tran_handle[chn].tran_callback_para = callback; + SDIOTRAN_DEBUG("sdio_tran_handle, chn = %d, callback = %p",sdio_tran_handle[chn].chn,sdio_tran_handle[chn].tran_callback_para); + } + else + { + sdio_tran_handle[chn].tran_callback = callback; + SDIOTRAN_DEBUG("sdio_tran_handle, chn = %d, callback = %p",sdio_tran_handle[chn].chn,sdio_tran_handle[chn].tran_callback); + } + + return 0; +} +EXPORT_SYMBOL_GPL(sdiodev_readchn_init); + +int sdiodev_readchn_uninit(uint32 chn) +{ + if(chn >= INVALID_SDIO_CHN) + { + SDIOTRAN_ERR("err input chn %d",chn); + return -1; + } + + sdio_tran_handle[chn].chn = INVALID_SDIO_CHN; + sdio_tran_handle[chn].tran_callback = NULL; + sdio_tran_handle[chn].tran_callback_para = NULL; + + return 0; +} +EXPORT_SYMBOL_GPL(sdiodev_readchn_uninit); + +void invalid_recv_flush(uint32 chn) +{ + int len ; + char* pbuff = NULL; + + if(chn < 0 || chn > 15) + { + SDIOTRAN_ERR("err chn"); + return; + } + + len = sdio_dev_get_chn_datalen(chn); + if(len <= 0){ + SDIOTRAN_ERR("chn %d, len err %d!!",chn,len); + return; + } + SDIOTRAN_ERR("NO VALID DATA! CHN %d FLUSH! DATALEN %d!",chn,len); + pbuff = kmalloc(len,GFP_KERNEL); + if(pbuff){ + SDIOTRAN_DEBUG("Read to Flush,chn=%d,pbuff=%p,len=%d",chn, pbuff, len); + sdio_dev_read(chn, pbuff, NULL); + kfree(pbuff); + }else{ + SDIOTRAN_ERR("Kmalloc %d failed!",len); + } +} +EXPORT_SYMBOL_GPL(invalid_recv_flush); + +void flush_blkchn(void) +{ + uint8 rw_flag0,rw_flag1; + uint8 status0,status1; + uint32 chn_status; + uint32 chn_rw_flag; + uint32 tmp; + int err_ret,read_chn; + MARLIN_PM_RESUME_WAIT(marlin_sdio_wait); + MARLIN_PM_RESUME_RETURN_ERROR(-1); + + sdio_claim_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + status0 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x840,&err_ret); + if (status0 == 0xFF){ + SDIOTRAN_ERR("sdio chn reg0 err"); + return; + } + + status1 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x841,&err_ret); + if (status1 == 0xFF){ + SDIOTRAN_ERR("sdio chn reg1 err"); + return; + } + + rw_flag0 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x842,&err_ret); + if (rw_flag0 == 0xFF){ + SDIOTRAN_ERR("sdio RW reg0 err"); + return; + } + + rw_flag1 = sdio_readb(sprd_sdio_func[SDIODEV_FUNC_0],0x843,&err_ret); + if (rw_flag1 == 0xFF){ + SDIOTRAN_ERR("sdio RW reg1 err"); + return; + } + + sdio_release_host(sprd_sdio_func[SDIODEV_FUNC_0]); + + chn_status = (uint32)(status0) + ((uint32)(status1) << 8); + chn_rw_flag = (uint32)(rw_flag0) + ((uint32)(rw_flag1) << 8); + + SDIOTRAN_ERR("chn_status is 0x%x!!!",chn_status); + SDIOTRAN_ERR("chn_rw_flag is 0x%x!!!",chn_rw_flag); + + tmp = (chn_status&(~chn_rw_flag))&(0x0000ffff); + + for(read_chn=0;read_chn<16;read_chn++) + { + if(BIT_0 & (tmp>>read_chn)) + { + SDIOTRAN_ERR("BLK CHN is 0x%x!!!",read_chn); + invalid_recv_flush(read_chn); + return; + } + } + + SDIOTRAN_ERR("NO BLK CHN!!!"); + return; + +} +EXPORT_SYMBOL_GPL(flush_blkchn); + + +int sdiolog_handler(void) +{ + if(NULL != sdio_tran_handle[SDIOLOG_CHN].tran_callback) + { + SDIOTRAN_DEBUG("SDIOLOG_CHN tran_callback=%p",sdio_tran_handle[SDIOLOG_CHN].tran_callback); + sdio_tran_handle[SDIOLOG_CHN].tran_callback(); + return 0; + } + else + { + return -1; + } +} + +int sdio_download_handler(void) +{ + if(NULL != sdio_tran_handle[DOWNLOAD_CHANNEL_READ].tran_callback) + { + SDIOTRAN_DEBUG("DOWNLOAD_CHN tran_callback=%p",sdio_tran_handle[DOWNLOAD_CHANNEL_READ].tran_callback); + sdio_tran_handle[DOWNLOAD_CHANNEL_READ].tran_callback(); + return 0; + } + else + { + return -1; + } +} + +int sdio_pseudo_atc_handler(void) +{ + SDIOTRAN_ERR("ENTRY"); + + if(NULL != sdio_tran_handle[PSEUDO_ATC_CHANNEL_READ].tran_callback) + { + SDIOTRAN_ERR("tran_callback=%p",sdio_tran_handle[PSEUDO_ATC_CHANNEL_READ].tran_callback); + sdio_tran_handle[PSEUDO_ATC_CHANNEL_READ].tran_callback(); + return 0; + } + else + { + return -1; + } +} + +int sdio_pseudo_loopcheck_handler(void) +{ + SDIOTRAN_ERR("ENTRY"); + + if(NULL != sdio_tran_handle[PSEUDO_ATC_CHANNEL_LOOPCHECK].tran_callback) + { + SDIOTRAN_ERR("tran_callback=%p",sdio_tran_handle[PSEUDO_ATC_CHANNEL_LOOPCHECK].tran_callback); + sdio_tran_handle[PSEUDO_ATC_CHANNEL_LOOPCHECK].tran_callback(); + return 0; + } + else + { + return -1; + } +} + + +int sdio_wifi_handler(uint32 chn) +{ + if(NULL != sdio_tran_handle[chn].tran_callback_para) + { + SDIOTRAN_DEBUG("wifi_handle_chn %d tran_callback=%p",chn,sdio_tran_handle[chn].tran_callback_para); + sdio_tran_handle[chn].tran_callback_para(chn); + return 0; + } + else + { + return -1; + } +} + +int sdio_assertinfo_handler(void) +{ + SDIOTRAN_ERR("ENTRY"); + + if(NULL != sdio_tran_handle[MARLIN_ASSERTINFO_CHN].tran_callback) + { + SDIOTRAN_ERR("tran_callback=%p",sdio_tran_handle[MARLIN_ASSERTINFO_CHN].tran_callback); + sdio_tran_handle[MARLIN_ASSERTINFO_CHN].tran_callback(); + return 0; + } + else + { + return -1; + } +} + + +static void marlin_workq(void) +{ + int read_chn; + int ret = 0; + + SDIOTRAN_DEBUG("ENTRY"); + +#if !defined(CONFIG_SDIODEV_TEST) + + read_chn = sdio_dev_get_read_chn(); + switch(read_chn) + { + case SDIOLOG_CHN: + ret = sdiolog_handler(); + break; + case DOWNLOAD_CHANNEL_READ: + ret = sdio_download_handler(); + break; + case PSEUDO_ATC_CHANNEL_READ: + ret = sdio_pseudo_atc_handler(); + break; + case PSEUDO_ATC_CHANNEL_LOOPCHECK: + ret = sdio_pseudo_loopcheck_handler(); + break; + case MARLIN_ASSERTINFO_CHN: + ret = sdio_assertinfo_handler(); + break; + case WIFI_CHN_8: + case WIFI_CHN_9: + ret = sdio_wifi_handler(read_chn); + break; + default: + SDIOTRAN_ERR("no handler for this chn",read_chn); + invalid_recv_flush(read_chn); + } + + if(-1 == ret) + invalid_recv_flush(read_chn); + +#else + +#if defined(SDIO_TEST_CASE4) + case4_workq_handler(); +#endif + +#if defined(SDIO_TEST_CASE5) + case5_workq_handler(); +#endif + +#if defined(SDIO_TEST_CASE6) + case6_workq_handler(); +#endif + +#if defined(SDIO_TEST_CASE9) + case9_workq_handler(); +#endif + +#endif//CONFIG_SDIODEV_TEST + + wake_unlock(&marlin_wakelock); + +} + + + + +static irqreturn_t marlin_irq_handler(int irq, void * para) +{ + wake_lock(&marlin_wakelock); + irq_set_irq_type(irq,IRQF_TRIGGER_RISING); + + if(get_sprd_download_fin() != 1) + { + schedule_work(&marlin_wq); + } + else if(NULL != sdio_tran_handle[WIFI_CHN_8].tran_callback_para) + { + sdio_tran_handle[WIFI_CHN_8].tran_callback_para(WIFI_CHN_8); + wake_unlock(&marlin_wakelock); + } + else + schedule_work(&marlin_wq); + + return IRQ_HANDLED; +} + +static int sdio_dev_intr_init(void) +{ + int ret; + + + wake_lock_init(&marlin_wakelock, WAKE_LOCK_SUSPEND, "marlin_wakelock"); + + INIT_WORK(&marlin_wq, marlin_workq); + + ret = gpio_request(sdio_data->data_irq,"marlin_irq"); + if (ret<0) + { + SDIOTRAN_ERR("req gpio sdio_data->data_irq = %d fail!!!",\ + sdio_data->data_irq); + return ret; + } + + ret = gpio_direction_input(sdio_data->data_irq); + if (ret<0) + { + SDIOTRAN_ERR("sdio_data->data_irq = %d input set fail!!!",\ + sdio_data->data_irq); + return ret; + + } + + sdio_irq_num = gpio_to_irq(sdio_data->data_irq); + + ret = request_irq(sdio_irq_num, marlin_irq_handler,IRQF_TRIGGER_RISING |IRQF_NO_SUSPEND, "sdio_dev_intr", NULL ); + //ret = request_irq(sdio_irq_num, marlin_irq_handler,IRQF_TRIGGER_HIGH | IRQF_ONESHOT |IRQF_NO_SUSPEND, "sdio_dev_intr", NULL ); + if (ret != 0) { + SDIOTRAN_ERR("request irq err!!!gpio is %d!!!",sdio_data->data_irq); + return ret; + } + + SDIOTRAN_ERR("ok!!!irq is %d!!!",sdio_irq_num); + + return 0; +} + +static void sdio_dev_intr_uninit(void) +{ + disable_irq_nosync(sdio_irq_num); + free_irq(sdio_irq_num,NULL); + gpio_free(sdio_data->data_irq); + gpio_free(sdio_data->wake_out); + + cancel_work_sync(&marlin_wq); + //flush_workqueue(&marlin_wq); + //destroy_workqueue(&marlin_wq); + + wake_lock_destroy(&marlin_wakelock); + + SDIOTRAN_ERR("ok!!!"); + +} +static void set_apsdiohal_ready(void) +{ + ap_sdio_ready = 1; +} + +static void set_apsdiohal_unready(void) +{ + ap_sdio_ready = 0; +} + +//return 1 means ap sdiohal ready +bool get_apsdiohal_status(void) +{ + return ap_sdio_ready; +} +EXPORT_SYMBOL_GPL(get_apsdiohal_status); + +//return 1 means marlin sdiohal ready +bool get_sdiohal_status(void) +{ + return marlin_sdio_ready.marlin_sdio_init_end_tag; +} +EXPORT_SYMBOL_GPL(get_sdiohal_status); + +static void clear_sdiohal_status(void) +{ + marlin_sdio_ready.marlin_sdio_init_start_tag = 0; + marlin_sdio_ready.marlin_sdio_init_end_tag = 0; +} + +static irqreturn_t marlinsdio_ready_irq_handler(int irq, void * para) +{ + disable_irq_nosync(irq); + + + SDIOTRAN_ERR("entry"); + + if(!marlin_sdio_ready.marlin_sdio_init_start_tag){ + SDIOTRAN_ERR("start"); + irq_set_irq_type(irq,IRQF_TRIGGER_LOW); + marlin_sdio_ready.marlin_sdio_init_start_tag = 1;} + else{ + SDIOTRAN_ERR("end"); + irq_set_irq_type(irq,IRQF_TRIGGER_HIGH); + marlin_sdio_ready.marlin_sdio_init_end_tag = 1;} + + if(!marlin_sdio_ready.marlin_sdio_init_end_tag) + enable_irq(irq); + + + return IRQ_HANDLED; + +} + +static int marlin_sdio_sync_init(void) +{ +#if !(defined CONFIG_MACH_SP8730SEEA || defined CONFIG_MACH_SP8730SEEA_QHD) + int ret; + + SDIOTRAN_ERR("entry"); + + sci_glb_clr(SPRD_PIN_BASE + sdio_data->rfctl_off,(BIT(3)|BIT(7)|0)); + sci_glb_set(SPRD_PIN_BASE + sdio_data->rfctl_off,(BIT(4)|BIT(5)|BIT(2)|BIT(6))); + + ret = gpio_request(sdio_data->io_ready,"marlin_sdio_ready_irq"); + if (ret<0) + { + SDIOTRAN_ERR("req gpio sdio_data->io_ready = %d fail!!!",\ + sdio_data->io_ready); + return ret; + } + + ret = gpio_direction_input(sdio_data->io_ready); + if (ret<0) + { + SDIOTRAN_ERR("sdio_data->io_ready = %d input set fail!!!",\ + sdio_data->io_ready); + return ret; + + } + + marlin_sdio_ready_irq_num = gpio_to_irq(sdio_data->io_ready); + SDIOTRAN_ERR("req irq"); + ret = request_irq(marlin_sdio_ready_irq_num, marlinsdio_ready_irq_handler,IRQF_TRIGGER_RISING |IRQF_NO_SUSPEND, "m_sdio_ready_intr", NULL ); + if (ret != 0) { + SDIOTRAN_ERR("request irq err!!!gpio is %d!!!",sdio_data->io_ready); + return ret; + } + + SDIOTRAN_ERR("ok!!!irq is %d!!!",marlin_sdio_ready_irq_num); +#endif + return 0; +} + +void marlin_sdio_sync_uninit(void) +{ + free_irq(marlin_sdio_ready_irq_num,NULL); + gpio_free(sdio_data->io_ready); +#if !(defined CONFIG_MACH_SP8730SEEA || defined CONFIG_MACH_SP8730SEEA_QHD) + sci_glb_clr(SPRD_PIN_BASE + sdio_data->rfctl_off,(BIT(4)|BIT(5)|0)); + sci_glb_set(SPRD_PIN_BASE + sdio_data->rfctl_off,(BIT(4))); +#endif + SDIOTRAN_ERR("ok!!!"); +} +EXPORT_SYMBOL_GPL(marlin_sdio_sync_uninit); + + +static void marlinack_workq(void) +{ + int read_chn; + int ret = 0; + + SDIOTRAN_ERR("ENTRY"); + if(sdio_w_flag == 1) + complete(&marlin_ack); + +} + +int time_d_value(struct timeval *start, struct timeval *end) +{ + return (end->tv_sec - start->tv_sec)*1000000 + (end->tv_usec - start->tv_usec); +} + +static irqreturn_t marlinwake_irq_handler(int irq, void * para) +{ + struct timeval cur_time; + uint32 gpio_wake_status = 0, usec; + //irq_set_irq_type(irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING); + gpio_wake_status = gpio_get_value(sdio_data->wake_ack); + + if(get_sprd_download_fin() != 1) + { + if(!marlin_sdio_ready.marlin_sdio_init_start_tag && gpio_wake_status){ + SDIOTRAN_ERR("start,g_val=%d",gpio_wake_status); + irq_set_irq_type(irq,IRQF_TRIGGER_LOW); + marlin_sdio_ready.marlin_sdio_init_start_tag = 1; + } + else if(!marlin_sdio_ready.marlin_sdio_init_end_tag && (!gpio_wake_status)){ + SDIOTRAN_ERR("end,g_val=%d",gpio_wake_status); + irq_set_irq_type(irq,IRQF_TRIGGER_RISING); + marlin_sdio_ready.marlin_sdio_init_end_tag = 1; + } + else + { + SDIOTRAN_ERR("marlin gpio0 err interupt,g_val=%d",gpio_wake_status); + } + } + else + { + /*add count irq for loopcheck*/ + irq_count_change++; + + /* avoid gpio jump , so need check the last and cur gpio value.*/ + do_gettimeofday(&cur_time); + if(ack_gpio_status == gpio_wake_status) + { + // usec = time_d_value(&ack_irq_time, &cur_time); + // if(usec < 200) //means invalid gpio value, so discard + { + SDIOTRAN_ERR("discard gpio%d irq\n", sdio_data->wake_ack); + return IRQ_HANDLED; + } + // SDIOTRAN_ERR("gpio%d %d-->%d\n",sdio_data->wake_ack, gpio_wake_status, 1 - gpio_wake_status ); + // gpio_wake_status = 1 - gpio_wake_status; + + } + ack_irq_time = cur_time; + ack_gpio_status = gpio_wake_status; + SDIOTRAN_ERR("%d-%d\n",sdio_data->wake_ack, gpio_wake_status ); + + if(gpio_wake_status) + irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); + else + irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); + + if(gpio_wake_status) + { + wake_lock(&marlinpub_wakelock); + sleep_para.gpio_up_time = jiffies; + } + else + { + wake_unlock(&marlinpub_wakelock); + sleep_para.gpio_down_time = jiffies; + } + + if((!gpio_wake_status) && time_after(sleep_para.gpio_down_time,sleep_para.gpio_up_time)) + { + if(jiffies_to_msecs(sleep_para.gpio_down_time -\ + sleep_para.gpio_up_time)> sleep_para.bt_req_time) + { + SDIOTRAN_ERR("BT REQ!!!"); + marlin_bt_wake_flag = 1; + wake_lock_timeout(&BT_AP_wakelock, sleep_para.wake_lock_time); //wsh + } + + } + + //schedule_work(&marlinack_wq); + if(gpio_wake_status) + { + if( atomic_read(&gpioreq_need_pulldown) )//if(sleep_para.gpioreq_need_pulldown) + { + sleep_para.gpio_opt_tag = 1; + SDIOTRAN_ERR("gpio_opt_tag-1\n"); + mod_timer(&(sleep_para.gpio_timer), jiffies + msecs_to_jiffies(sleep_para.marlin_waketime) ); + if(sdio_w_flag == 1) + { + complete(&marlin_ack); + SDIOTRAN_ERR("ack-sem\n"); + set_marlin_sleep(0xff,0x1); + } + else + { + SDIOTRAN_ERR("sdio_w_flag:%d\n", sdio_w_flag); + set_marlin_sleep(0xff,0x2); + } + } + } + } + + return IRQ_HANDLED; +} + + + +static int marlin_wake_intr_init(void) +{ + int ret; + sdio_w_flag = 0; + bt_wake_flag = 0; + + INIT_WORK(&marlinwake_wq, marlinack_workq); + + init_completion (&marlin_ack); + + + wake_lock_init(&BT_AP_wakelock, WAKE_LOCK_SUSPEND, "marlinbtup_wakelock"); + + wake_lock_init(&marlinpub_wakelock, WAKE_LOCK_SUSPEND, "marlinpub_wakelock"); + + ret = gpio_request(sdio_data->wake_ack,"marlinwake_irq"); + if (ret<0) + { + SDIOTRAN_ERR("req gpio sdio_data->wake_ack = %d fail!!!",\ + sdio_data->wake_ack); + return ret; + } + + ret = gpio_direction_input(sdio_data->wake_ack); + if (ret<0) + { + SDIOTRAN_ERR("sdio_data->wake_ack = %d input set fail!!!",\ + sdio_data->wake_ack); + return ret; + + } + + marlinwake_irq_num = gpio_to_irq(sdio_data->wake_ack); + + ret = request_irq(marlinwake_irq_num, marlinwake_irq_handler,IRQF_TRIGGER_RISING |IRQF_NO_SUSPEND, "marlin_wake_intr", NULL ); + //ret = request_irq(marlinwake_irq_num, marlinwake_irq_handler,IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, "marlin_wake_intr", NULL ); + if (ret != 0) { + SDIOTRAN_ERR("request irq err!!!gpio is %d!!!",sdio_data->wake_ack); + return ret; + } + + SDIOTRAN_ERR("ok!!!irq is %d!!!",marlinwake_irq_num); + + return 0; +} + +static void marlin_wake_intr_uninit(void) +{ + disable_irq_nosync(marlinwake_irq_num); + free_irq(marlinwake_irq_num,NULL); + gpio_free(sdio_data->wake_ack); + + + cancel_work_sync(&marlinwake_wq); + //flush_workqueue(&marlinwake_wq); + //destroy_workqueue(&marlinwake_wq); + + + wake_lock_destroy(&BT_AP_wakelock); + wake_lock_destroy(&marlinpub_wakelock); + + SDIOTRAN_ERR("ok!!!"); + +} + + + +static void sdio_tran_sync(void) +{ + + int datalen,i,j; + + SDIOTRAN_ERR("entry"); + + set_blklen(4); + + while(!sdio_dev_chn_idle(SDIO_SYNC_CHN)) + { + SDIOTRAN_ERR("sync chn is active!!!"); + //return; + } + + while(1) + { + datalen = sdio_dev_get_chn_datalen(SDIO_SYNC_CHN); + if(datalen > 0) + { + SDIOTRAN_ERR("channel %d len is =%d!!!",SDIO_SYNC_CHN,datalen); + break; + } + else + SDIOTRAN_ERR("channel %d len is =%d!!!",SDIO_SYNC_CHN,datalen); + + } + + sync_data_ptr = kmalloc(4,GFP_KERNEL); + if (NULL == sync_data_ptr) + { + SDIOTRAN_ERR("kmalloc sync buf err!!!"); + return -1; + } + + SDIOTRAN_ERR("kmalloc sync buf ok!!!"); + + for(i=0;i<4;i++) + *(sync_data_ptr+i) = i; + + sdio_dev_write(SDIO_SYNC_CHN,sync_data_ptr,\ + ((datalen > 4) ? 4: datalen)); + + kfree(sync_data_ptr); + + set_blklen(512); +} + + +void set_blklen(int blklen) +{ + sdio_claim_host(sprd_sdio_func[1]); + sdio_set_block_size(sprd_sdio_func[1], blklen); + sdio_release_host(sprd_sdio_func[1]); + + SDIOTRAN_ERR("set blklen = %d!!!",blklen); + +} + +static void sdio_init_timer(void) +{ + init_timer(&sleep_para.gpio_timer); + sleep_para.gpio_timer.function = gpio_timer_handler; + +#if defined(CONFIG_WCN_EXTENSION) + sleep_para.marlin_waketime = 350; + sleep_para.bt_req_time = 100; + sleep_para.ack_high_time = 200; + sleep_para.wake_lock_time = HZ/2; +#else + sleep_para.marlin_waketime = 1500; + sleep_para.bt_req_time = 200; + sleep_para.ack_high_time = 300; + sleep_para.wake_lock_time = HZ*2; +#endif + + sleep_para.gpio_opt_tag = 0; + atomic_set(&gpioreq_need_pulldown, 1);//sleep_para.gpioreq_need_pulldown = 1; +} + + +static void sdio_uninit_timer(void) +{ + del_timer(&sleep_para.gpio_timer); + sleep_para.marlin_waketime = 0; + sleep_para.bt_req_time = 0; + sleep_para.ack_high_time = 0; + sleep_para.wake_lock_time = 0; + sleep_para.gpio_opt_tag = 0; + atomic_set(&gpioreq_need_pulldown, 1);//sleep_para.gpioreq_need_pulldown = 1; +} + +static int marlin_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int ret; + + SDIOTRAN_ERR("sdio drv and dev match!!!"); + mutex_init(&g_sdio_func_lock); + ret = get_sdio_dev_func(func); + if(ret < 0) + { + SDIOTRAN_ERR("get func err!!!\n"); + return ret; + } + SDIOTRAN_ERR("get func ok!!!\n"); + + /* Enable Function 1 */ + sdio_claim_host(sprd_sdio_func[1]); + ret = sdio_enable_func(sprd_sdio_func[1]); + sdio_set_block_size(sprd_sdio_func[1], 512); + sdio_release_host(sprd_sdio_func[1]); + if (ret < 0) { + SDIOTRAN_ERR("enable func1 err!!! ret is %d",ret); + return ret; + } + SDIOTRAN_ERR("enable func1 ok!!!"); + + spin_lock_init(&sleep_spinlock); + sdio_init_timer(); + clear_sdiohal_status(); + wakeup_slave_pin_init(); + marlin_wake_intr_init(); + //marlin_sdio_sync_init(); +//case6 +#if defined(CONFIG_SDIODEV_TEST) + gaole_creat_test(); +#endif + + sdio_dev_intr_init(); + +#if defined(CONFIG_SDIODEV_TEST) + sdio_tran_sync(); +#endif + +/*case1 +#if defined(CONFIG_SDIODEV_TEST) + gaole_creat_test(); +#endif +*/ + //set_bt_pm_func(set_marlin_wakeup,set_marlin_sleep); + + set_apsdiohal_ready(); + have_card = 1; + return 0; +} + +static void marlin_sdio_remove(struct sdio_func *func) +{ + SDIOTRAN_DEBUG("entry"); + sdio_uninit_timer(); + free_sdio_dev_func(func); + sdio_dev_intr_uninit(); + marlin_wake_intr_uninit(); + //marlin_sdio_sync_uninit(); + set_apsdiohal_unready(); + clear_sdiohal_status(); + + SDIOTRAN_DEBUG("ok"); + +} + +static int marlin_sdio_suspend(struct device *dev) +{ + mutex_lock(&g_mgr_suspend.func_lock); + SDIOTRAN_ERR("[%s]enter\n", __func__); + + gpio_marlin_req_tag = gpio_get_value(sdio_data->data_irq); + + if(gpio_marlin_req_tag) + SDIOTRAN_ERR("err marlin_req!!!"); + else + irq_set_irq_type(sdio_irq_num,IRQF_TRIGGER_HIGH); + + gpio_marlinwake_tag = gpio_get_value(sdio_data->wake_ack); + + if(gpio_marlinwake_tag) + SDIOTRAN_ERR("err marlinwake!!!"); + else + irq_set_irq_type(marlinwake_irq_num,IRQF_TRIGGER_HIGH); + + + + smp_mb(); + SDIOTRAN_ERR("[%s]ok\n", __func__); + return 0; +} +static int marlin_sdio_resume(struct device *dev) +{ + SDIOTRAN_ERR("[%s]enter\n", __func__); + /****************/ + mutex_unlock(&g_mgr_suspend.func_lock); + sleep_para.gpio_opt_tag = 0; + set_marlin_wakeup(0, 1); + mod_timer(&(sleep_para.gpio_timer),jiffies + msecs_to_jiffies(sleep_para.marlin_waketime)); + /***************/ + smp_mb(); + SDIOTRAN_ERR("[%s]ok\n", __func__); + return 0; +} + +static void* sdio_dev_get_host(void) +{ + struct device *dev; + + struct sdhci_host *host; + + struct platform_device *pdev; + + dev = bus_find_device_by_name(&platform_bus_type, NULL, sdio_data->sdhci); + if(dev == NULL) + { + SDIOTRAN_ERR("sdio find dev by name failed!!!"); + return NULL; + } + + pdev = to_platform_device(dev); + if(pdev == NULL) + { + SDIOTRAN_ERR("sdio dev get platform device failed!!!"); + return NULL; + } + + host = platform_get_drvdata(pdev); + return container_of(host, struct mmc_host, private); + + +} + +void marlin_sdio_uninit(void) +{ + set_sprd_download_fin(0); + sdio_unregister_driver(&marlin_sdio_driver); + mgr_suspend_defint(); + sdio_dev_host = NULL; + have_card = 0; + + kfree(sdio_data); + sdio_data = NULL; + SDIOTRAN_ERR("ok"); +} + +int marlin_sdio_init(void) +{ + int ret; + struct device_node *np; + SDIOTRAN_ERR("entry"); + if(have_card == 1){ + marlin_sdio_uninit(); + } + mgr_suspend_init(); + //atomic_set(&req_marlin_wait_tag, 0); + atomic_set(&gpioreq_need_pulldown, 1); + atomic_set(&is_wlan_open, 0); + atomic_set(&set_marlin_cmplete, 1); + + sdio_data = kzalloc(sizeof(*sdio_data), GFP_KERNEL); + if (!sdio_data) + return -ENOMEM; + np = of_find_node_by_name(NULL, "sprd-marlin"); + if (!np) { + SDIOTRAN_ERR("sprd-marlin not found"); + return -1; + } + + sdio_data->wake_ack = of_get_gpio(np, 0); + sdio_data->data_irq = of_get_gpio(np, 1); + sdio_data->wake_out = of_get_gpio(np, 2); + sdio_data->io_ready = of_get_gpio(np, 3); + + of_property_read_u32(np, "cp-rfctl-offset", &(sdio_data->rfctl_off)); + + ret = of_property_read_string(np, "sdhci-name", &(sdio_data->sdhci)); + if (ret) { + SDIOTRAN_ERR("get sdhci-name failed"); + return -1; + } + + sdio_dev_host = sdio_dev_get_host(); + if(NULL == sdio_dev_host) + { + SDIOTRAN_ERR("get host failed!!!"); + return -1; + } + SDIOTRAN_ERR("sdio get host ok!!!"); + + ret = sdio_register_driver(&marlin_sdio_driver); + if(0 != ret) + { + SDIOTRAN_ERR("sdio register drv err!!!ret is %d!!!",ret); + return -1; + } + + SDIOTRAN_ERR("sdio register drv succ!!!"); + + flush_delayed_work(&sdio_dev_host->detect); + mmc_detect_change(sdio_dev_host, 0); + + return ret; +} +EXPORT_SYMBOL_GPL(marlin_sdio_init); + + diff --git a/drivers/misc/sdiodev/sdio_dev.h b/drivers/misc/sdiodev/sdio_dev.h new file mode 100755 index 00000000..3e950770 --- /dev/null +++ b/drivers/misc/sdiodev/sdio_dev.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2013 Spreadtrum Communications Inc. + * + * Filename : sdio_dev.h + * Abstract : This file is a implementation for itm sipc command/event function + * + * Authors : gaole.zhang + * + * + * 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 __SDIO_DEV_H__ +#define __SDIO_DEV_H__ + +#include <linux/module.h> +#include <linux/export.h> +#include <linux/err.h> +#include <linux/regulator/consumer.h> +#include <soc/sprd/regulator.h> +#include <linux/platform_device.h> +#include <linux/kthread.h> +#include <linux/sched.h> +#include <linux/mmc/host.h> +#include <linux/mmc/card.h> +#include <linux/mmc/sdio.h> +#include <linux/mmc/sdio_func.h> +#include <soc/sprd/gpio.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/time.h> +#include <linux/timer.h> +#include <linux/irq.h> +#include <linux/suspend.h> +#include <soc/sprd/sci_glb_regs.h> +#include <soc/sprd/sci.h> +#include <soc/sprd/board.h> +#include <linux/sprd_iommu.h> +#include <linux/spinlock.h> +//#include <asm/system.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/syscalls.h> +#include <asm/unistd.h> +#include <asm/uaccess.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/of_device.h> + +typedef unsigned int uint32; +typedef unsigned char uint8; +typedef irqreturn_t (*sdiodev_handler_t)(int, void *); +typedef void (*SDIO_TRAN_CALLBACK)(void); +typedef void (*SDIO_TRAN_CALLBACK_PARA)(int); +typedef struct _sdio_chn_handler +{ + uint32 chn; + SDIO_TRAN_CALLBACK tran_callback; + SDIO_TRAN_CALLBACK_PARA tran_callback_para; +}SDIO_CHN_HANDLER; + +typedef struct _sleep_policy +{ + struct timer_list gpio_timer; + uint32 marlin_waketime; + uint32 bt_req_time; + uint32 ack_high_time; + uint32 wake_lock_time; + uint32 gpio_opt_tag; // 1:dont't pull gpio 0:pull gpio + unsigned long gpioreq_up_time; + unsigned long gpioreq_need_pulldown; + unsigned long gpio_up_time; + unsigned long gpio_down_time; +}SLEEP_POLICY_T; + + +typedef struct _marlin_sdio_ready +{ + bool marlin_sdio_init_start_tag; + bool marlin_sdio_init_end_tag; + +}MARLIN_SDIO_READY_T; + +struct sdio_data { + u32 wake_ack; + u32 data_irq; + u32 wake_out; + u32 io_ready; + u32 rfctl_off; + const char *sdhci; +}; + +#define MARLIN_SDIO_VERSION "1.0" +#define INVALID_SDIO_CHN 16 +#define INVALID_SDIO_WCHN 8 + +#define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) +#define LINUX_VERSION_CODE KERNEL_VERSION(3, 10, 0) +#define BIT_0 0x01 +#define SDIODEV_MAX_FUNCS 2 +#define SDIODEV_FUNC_0 0 +#define SDIODEV_FUNC_1 1 +#define MARLIN_VENDOR_ID 0x00 +#define MARLIN_DEVICE_ID 0x2331 +#define SDIO_CHN_8 0x1 +#define SDIO_CHN_9 0x2 +#define SDIO_CHN_11 0x8 +#define SDIO_CHN_12 0x10 +#define SDIO_CHN_13 0x20 + +#define SDIO_CHN_14 0x40 +#define SDIO_CHN_15 0x80 + +#define SDIOLOG_CHN 14 +#define SDIO_SYNC_CHN 10 +#define DOWNLOAD_CHANNEL_READ 12 +#define PSEUDO_ATC_CHANNEL_READ 11 +#define PSEUDO_ATC_CHANNEL_LOOPCHECK (15) +#define MARLIN_ASSERTINFO_CHN (13) + + +#define WIFI_CHN_8 8 +#define WIFI_CHN_9 9 + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define SMP_BARRIER(x) smp_read_barrier_depends(x) +#else +#define SMP_BARRIER(x) smp_rmb(x) +#endif + + + +#define SDIOTRAN_HEADER "[SDIOTRAN]" + +#define SDIOTRAN_ERR(fmt,args...) \ + pr_err(SDIOTRAN_HEADER "%s:" fmt "\n", __func__, ## args) + +#define SDIOTRAN_DEBUG(fmt,args...) \ + pr_debug(SDIOTRAN_HEADER "%s:" fmt "\n", __func__, ## args) + +int set_wlan_status(int status); + +int set_marlin_wakeup(uint32 chn,uint32 user_id); +int set_marlin_sleep(uint32 chn,uint32 user_id); + + + +#if 0//#if !defined(CONFIG_MARLIN_NO_SLEEP) + +#define MARLIN_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); +#define _MARLIN_PM_RESUME_WAIT(a, b) do {\ + int retry = 0; \ + SMP_BARRIER(); \ + while (marlin_mmc_suspend && retry++ != b) { \ + SMP_BARRIER(); \ + wait_event_interruptible_timeout(a, !marlin_mmc_suspend, HZ/100); \ + } \ + } while (0) +#define MARLIN_PM_RESUME_WAIT(a) _MARLIN_PM_RESUME_WAIT(a, 200) +#define MARLIN_PM_RESUME_WAIT_FOREVER(a) _MARLIN_PM_RESUME_WAIT(a, ~0) +#define MARLIN_PM_RESUME_RETURN_ERROR(a) do { \ + if (marlin_mmc_suspend) {\ + SDIOTRAN_ERR("ERR!!!");\ + return a;} \ + } while (0) +#else +#define MARLIN_PM_RESUME_WAIT_INIT(a) +#define _MARLIN_PM_RESUME_WAIT(a, b) +#define MARLIN_PM_RESUME_WAIT(a) +#define MARLIN_PM_RESUME_WAIT_FOREVER(a) +#define MARLIN_PM_RESUME_RETURN_ERROR(a) +#endif + + + + + +int sdio_dev_chn_idle(uint32 chn); +int sdio_dev_get_chn_datalen(uint32 chn); +int sdio_dev_get_read_chn(void); +bool get_sdiohal_status(void); +bool get_apsdiohal_status(void); +void marlin_sdio_sync_uninit(void); +int sdio_dev_write(uint32 chn,void* data_buf,uint32 count); +int sdio_dev_read(uint32 chn,void* read_buf,uint32 *count); +int sdiodev_readchn_init(uint32 chn,void* callback,bool with_para); +int sdiodev_readchn_uninit(uint32 chn); +void set_sprd_download_fin(int dl_tag); +int marlin_sdio_init(void); +bool get_sprd_marlin_status(void); + +void set_blklen(int blklen); +void flush_blkchn(void); + + +#endif diff --git a/drivers/misc/sdiodev/sdio_dev_test.c b/drivers/misc/sdiodev/sdio_dev_test.c new file mode 100644 index 00000000..31385b0a --- /dev/null +++ b/drivers/misc/sdiodev/sdio_dev_test.c @@ -0,0 +1,1219 @@ +/* + * Copyright (C) 2013 Spreadtrum Communications Inc. + * + * Filename : sdio_dev_test.c + * Abstract : This file is a implementation for itm sipc command/event function + * + * Authors : gaole.zhang + * + * + * 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 "sdio_dev.h" + + +#if defined(SDIO_TEST_CASE1) + +#define SEND_BUF_LEN 1024//SDIO_TEST_CASE1 + +char *data_send_ptr[17] = {0}; + + +static void test_sdio_send_func(int chn,int senddatalen,void* data_buf) +{ + + uint32 chndatalen,ret; + + char *tmp = (char*)data_buf; + + //SDIOTRAN_ERR("\nrun to test_sdio_send_func,senddatalen is %d!!!\n",senddatalen); + SDIOTRAN_ERR("entry"); + + + + set_marlin_wakeup(chn,1); + + + + if(!sdio_dev_chn_idle(chn)) + { + SDIOTRAN_ERR("send chn active,can't send right now,chn is %d!!!",chn); + return; + } + + + chndatalen = sdio_dev_get_chn_datalen(chn); + if(senddatalen > chndatalen) + { + SDIOTRAN_ERR("channel %d chndatalen is =%d,senddatalen is =%d, can't send!!",chn,chndatalen,senddatalen); + return; + } + + SDIOTRAN_ERR("ap chn %d send len %d data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",chn,senddatalen,\ + tmp[0],\ + tmp[1],\ + tmp[2],\ + tmp[3], \ + tmp[101], \ + tmp[102], \ + tmp[103], \ + tmp[104], \ + tmp[230], \ + tmp[231], \ + tmp[232], \ + tmp[233] \ + ); + + sdio_dev_write(chn,data_buf,senddatalen); + set_marlin_sleep(chn,1); + + +} + + + +static int gaole_test_thread(void *data) +{ + int i,j,k; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + /*for(i=0;i<16;i++){ + + data_send_ptr[i] = kmalloc(SEND_BUF_LEN,GFP_KERNEL); + if (NULL == data_send_ptr[i]) + { + SDIOTRAN_ERR("kmalloc send buf%d err!!!",i); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc send buf%d ok!!!",i); + + for(j=0,k=0;j<SEND_BUF_LEN;j++,k++) + *(data_send_ptr[i]+j) = ((k+i)<=255?(k+i):(k=0,k+i)); + + }*/ + set_blklen(512); + + while(1) + { + + /* + for(j=0;j<8;j++) + { + set_blklen(32<<j); + for(i=0;i<9;i++) + { + if(((32<<j)<<i) > 8192) + break; + + test_sdio_send_func(j,(32<<j)<<i,data_send_ptr[1]); + } + } + */ + + /* + for(j=1;j<128;j++) + test_sdio_send_func(0,j,data_send_ptr[1]); + break; + + msleep(1000); + test_sdio_send_func(0,64,data_send_ptr[1]); + test_sdio_send_func(0,128,data_send_ptr[1]); + test_sdio_send_func(0,192,data_send_ptr[1]); + */ + + + + + /*if test CASE3 please unmark msleep func and modify sleep time, + CP side need not to change*/ + //msleep(1000); + + for(i=0;i<16;i++) + { + msleep(1000); + for(j=0;j<2;j++) + { + msleep(1000); + test_sdio_send_func(i,0x200<<j,data_send_ptr[i]); + } + + SDIOTRAN_ERR("chn %d test finish!!!",i); + } + + SDIOTRAN_ERR("sdio test write finish!!!"); + break; + } + + return 0; +} + +void gaole_creat_test(void) +{ + struct task_struct * task; + int i,j,k; + for(i=0;i<16;i++){ + + data_send_ptr[i] = kmalloc(SEND_BUF_LEN,GFP_KERNEL); + if (NULL == data_send_ptr[i]) + { + SDIOTRAN_ERR("kmalloc send buf%d err!!!",i); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc send buf%d ok!!!",i); + + for(j=0,k=0;j<SEND_BUF_LEN;j++,k++) + *(data_send_ptr[i]+j) = ((k+i)<=255?(k+i):(k=0,k+i)); + + } + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} + + +#endif//SDIO_TEST_CASE1 + +#if defined(SDIO_TEST_CASE2) + +#define RECV_BUF_LEN 1024//SDIO_TEST_CASE2 + +char *data_recv_ptr[17] = {0}; + +int invalid_num = 0; + +static int active_chn = 0; +static int last_chn = 1; +static int dummy_recv = 0; + +static int read_datalen = 0; + +void test_sdio_recv_func(void) +{ + int i,j; + SDIOTRAN_DEBUG("entry"); + + if((active_chn = sdio_dev_get_read_chn()) == -1) + { + invalid_num++; + return; + } + + if(last_chn == active_chn) + { + dummy_recv++; + } + else + { + last_chn = active_chn; + dummy_recv--; + } + + for(j=0;j<RECV_BUF_LEN;j++) + *(data_recv_ptr[active_chn]+j) = 0; + + sdio_dev_read(active_chn,(data_recv_ptr[active_chn]+10),&read_datalen); + + SDIOTRAN_ERR("ap recv: active_chn is %d!!!",active_chn); + SDIOTRAN_ERR("ap recv: read_datalen is 0x%x!!!",read_datalen); + + SDIOTRAN_ERR("ap recv data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",\ + *((data_recv_ptr[active_chn]+10)+read_datalen-9),\ + *((data_recv_ptr[active_chn]+10)+read_datalen-8),\ + *((data_recv_ptr[active_chn]+10)+read_datalen-7),\ + *((data_recv_ptr[active_chn]+10)+read_datalen-6), \ + *((data_recv_ptr[active_chn]+10)+read_datalen-5), \ + *((data_recv_ptr[active_chn]+10)+read_datalen-4), \ + *((data_recv_ptr[active_chn]+10)+read_datalen-3), \ + *((data_recv_ptr[active_chn]+10)+read_datalen-2), \ + *((data_recv_ptr[active_chn]+10)+read_datalen-1), \ + *((data_recv_ptr[active_chn]+10)+read_datalen), \ + *((data_recv_ptr[active_chn]+10)+read_datalen+1), \ + *((data_recv_ptr[active_chn]+10)+read_datalen+2) \ + ); + + active_chn = 0; + read_datalen = 0; +} + +static int gaole_test_thread(void *data) +{ + int i,j; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + for(i=0;i<16;i++){ + + data_recv_ptr[i] = kmalloc(RECV_BUF_LEN,GFP_KERNEL); + if (NULL == data_recv_ptr[i]) + { + SDIOTRAN_ERR("kmalloc recv buf%d err!!!",i); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc recv buf%d ok!!!",i); + + for(j=0;j<RECV_BUF_LEN;j++) + *(data_recv_ptr[i]+j) = 0; + + } + + set_blklen(512); + + while(1) + { + + test_sdio_recv_func(); + + + if(dummy_recv > 50) + break; + + if(invalid_num > 50) + break; + } + + return 0; +} + +void gaole_creat_test(void) +{ + struct task_struct * task; + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} + + + +#endif//SDIO_TEST_CASE2 + + + +#if defined(SDIO_TEST_CASE4) + +#define BUF_LEN 1024//SDIO_TEST_CASE4 + +char *data_ptr[10] = {0}; + +bool continue_send = 1; + +static int test_send_chn = 0; + + + +static void test_sdio_send_func(int chn,void* data_buf) +{ + + uint32 datalen; + + char *tmp = (char*)data_buf; + + //SDIOTRAN_ERR("\nrun to test_sdio_send_func!!!\n"); + + while(!sdio_dev_chn_idle(chn)); + + while(1) + { + datalen = sdio_dev_get_chn_datalen(chn); + if(datalen) + { + SDIOTRAN_ERR("channel %d len is =%d!!!",chn,datalen); + break; + } + else + SDIOTRAN_ERR("channel %d len is =%d!!!",chn,datalen); + + } + + SDIOTRAN_ERR("ap %d send data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",chn,\ + tmp[0],\ + tmp[1],\ + tmp[2],\ + tmp[3], \ + tmp[101], \ + tmp[102], \ + tmp[103], \ + tmp[104], \ + tmp[230], \ + tmp[231], \ + tmp[232], \ + tmp[233] \ + ); + + sdio_dev_write(chn,data_buf,datalen); + +} + +void case4_workq_handler(void) +{ + int i; + + int read_chn = 0; + int datalen = 0; + + read_chn = sdio_dev_get_read_chn(); + + if(-1 == read_chn) + return; + + + SDIOTRAN_DEBUG("ap recv: active_chn is %d!!!",read_chn); + + + for(i=0;i<BUF_LEN;i++) + *(data_ptr[read_chn-7]+i) = 0; + + + sdio_dev_read(read_chn,data_ptr[read_chn-7],&datalen); + + SDIOTRAN_ERR("ap recv chn %d data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",read_chn,\ + *(data_ptr[read_chn-7]+0),\ + *(data_ptr[read_chn-7]+1),\ + *(data_ptr[read_chn-7]+2),\ + *(data_ptr[read_chn-7]+3), \ + *(data_ptr[read_chn-7]+100), \ + *(data_ptr[read_chn-7]+101), \ + *(data_ptr[read_chn-7]+102), \ + *(data_ptr[read_chn-7]+103), \ + *(data_ptr[read_chn-7]+230), \ + *(data_ptr[read_chn-7]+231), \ + *(data_ptr[read_chn-7]+232), \ + *(data_ptr[read_chn-7]+233) \ + ); + + continue_send = 1; +} + + + + +static int gaole_test_thread(void *data) +{ + int i,j,k; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + for(i=0;i<10;i++){ + + data_ptr[i] = kmalloc(BUF_LEN,GFP_KERNEL); + if (NULL == data_ptr[i]) + { + SDIOTRAN_ERR("kmalloc send buf%d err!!!",i); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc send buf%d ok!!!",i); + + for(j=0;j<BUF_LEN;j++) + *(data_ptr[i]+j) = 0; + + } + + for(j=0,k=0;j<BUF_LEN;j++,k++) + *(data_ptr[0]+j) = (k<=255?k:(k=0,k)); + + while(1) + { + + if(1 == continue_send) + { + continue_send = 0; + test_sdio_send_func(test_send_chn,data_ptr[test_send_chn]); + + + test_send_chn++; + if(8 == test_send_chn) + { + test_send_chn = 0; + } + } + else + msleep(1); + } + return 0; +} + + +void gaole_creat_test(void) +{ + struct task_struct * task; + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} + + +#endif//SDIO_TEST_CASE4 + + +#if defined(SDIO_TEST_CASE5) + +#define TEST_BUF_LEN 8192 //SDIO_TEST_CASE5 + +#define TEST_SEND_CHN 0 + +char *data_test_ptr[17] = {0}; + + +int active_chn = 0; +int read_datalen = 0; + +void case5_workq_handler(void) +{ + int i; + + active_chn = 0; + read_datalen = 0; + + active_chn = sdio_dev_get_read_chn(); + + if(-1 == active_chn) + return; + + SDIOTRAN_DEBUG("ap recv: active_chn is %d!!!",active_chn); + + + for(i=0;i<TEST_BUF_LEN;i++) + *(data_test_ptr[active_chn]+i) = 0; + + + sdio_dev_read(active_chn,data_test_ptr[active_chn],&read_datalen); + + SDIOTRAN_ERR("ap recv chn %d data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",active_chn,\ + *(data_test_ptr[active_chn]+0),\ + *(data_test_ptr[active_chn]+1),\ + *(data_test_ptr[active_chn]+2),\ + *(data_test_ptr[active_chn]+3), \ + *(data_test_ptr[active_chn]+100), \ + *(data_test_ptr[active_chn]+101), \ + *(data_test_ptr[active_chn]+102), \ + *(data_test_ptr[active_chn]+103), \ + *(data_test_ptr[active_chn]+230), \ + *(data_test_ptr[active_chn]+231), \ + *(data_test_ptr[active_chn]+232), \ + *(data_test_ptr[active_chn]+233) \ + ); +} + + +static void test_sdio_send_func(void) +{ + + uint32 datalen; + + SDIOTRAN_ERR("entry"); + + while(!sdio_dev_chn_idle(TEST_SEND_CHN)); + + while(1) + { + datalen = sdio_dev_get_chn_datalen(TEST_SEND_CHN); + if(datalen) + { + SDIOTRAN_ERR("channel %d len is =%d!!!",TEST_SEND_CHN,datalen); + break; + } + else + SDIOTRAN_ERR("channel %d len is =%d!!!",TEST_SEND_CHN,datalen); + + } + + SDIOTRAN_ERR("ap send data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",\ + *(data_test_ptr[active_chn]+0),\ + *(data_test_ptr[active_chn]+1),\ + *(data_test_ptr[active_chn]+2),\ + *(data_test_ptr[active_chn]+3), \ + *(data_test_ptr[active_chn]+100), \ + *(data_test_ptr[active_chn]+101), \ + *(data_test_ptr[active_chn]+102), \ + *(data_test_ptr[active_chn]+103), \ + *(data_test_ptr[active_chn]+230), \ + *(data_test_ptr[active_chn]+231), \ + *(data_test_ptr[active_chn]+232), \ + *(data_test_ptr[active_chn]+233)\ + ); + + sdio_dev_write(TEST_SEND_CHN,data_test_ptr[active_chn],datalen); + +} + + +static int gaole_test_thread(void *data) +{ + int i,j; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + for(i=0;i<16;i++){ + + data_test_ptr[i] = kmalloc(TEST_BUF_LEN,GFP_KERNEL); + if (NULL == data_test_ptr[i]) + { + SDIOTRAN_ERR("kmalloc buf%d err!!!",i); + return -1; + } + + SDIOTRAN_ERR("kmalloc buf%d ok!!!",i); + + + + } + + while(1) + { + msleep(10); + + for(i=0,j=0;i<TEST_BUF_LEN;i++,j++) + *(data_test_ptr[0]+i) = (j<=255?j:(j=0,j)); + + test_sdio_send_func(); + + break; + } + + return 0; +} + +void gaole_creat_test(void) +{ + struct task_struct * task; + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} +#endif//SDIO_TEST_CASE5 + +#if defined(SDIO_TEST_CASE6) + +#define BUF_LEN 1024//SDIO_TEST_CASE6 + +char *data_ptr[10] = {0}; + +bool continue_send = 0; + +static int test_send_chn = 0; + +static void test_sdio_send_func(int chn,void* data_buf) +{ + + uint32 datalen; +uint32 ret; + char *tmp = (char*)data_buf; + + //SDIOTRAN_ERR("\nrun to test_sdio_send_func!!!\n"); + + set_marlin_wakeup(chn,1); + + while(!sdio_dev_chn_idle(chn)); + + while(1) + { + datalen = sdio_dev_get_chn_datalen(chn); + if(datalen) + { + SDIOTRAN_ERR("channel %d len is =%d!!",chn,datalen); + break; + } + else + SDIOTRAN_ERR("channel %d len is =%d!!",chn,datalen); + + } + + SDIOTRAN_ERR("ap %d send data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",chn,\ + tmp[0],\ + tmp[1],\ + tmp[2],\ + tmp[3], \ + tmp[101], \ + tmp[102], \ + tmp[103], \ + tmp[104], \ + tmp[230], \ + tmp[231], \ + tmp[232], \ + tmp[233] \ + ); + + sdio_dev_write(chn,data_buf,datalen); + set_marlin_sleep(chn,1); + + +} + +void case6_workq_handler(void) +{ + int i; + + int read_chn = 0; + int datalen = 0; + + read_chn = sdio_dev_get_read_chn(); + + if(-1 == read_chn) + return; + + + SDIOTRAN_ERR("ap recv: active_chn is %d!!!",read_chn); + + + for(i=0;i<BUF_LEN;i++) + *(data_ptr[read_chn-8]+i) = 0; + + + sdio_dev_read(read_chn,data_ptr[read_chn-8],&datalen); + + SDIOTRAN_ERR("ap recv chn %d data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",read_chn,\ + *(data_ptr[read_chn-8]+0),\ + *(data_ptr[read_chn-8]+1),\ + *(data_ptr[read_chn-8]+2),\ + *(data_ptr[read_chn-8]+3), \ + *(data_ptr[read_chn-8]+100), \ + *(data_ptr[read_chn-8]+101), \ + *(data_ptr[read_chn-8]+102), \ + *(data_ptr[read_chn-8]+103), \ + *(data_ptr[read_chn-8]+230), \ + *(data_ptr[read_chn-8]+231), \ + *(data_ptr[read_chn-8]+232), \ + *(data_ptr[read_chn-8]+233) \ + ); + + continue_send = 1; +} + + + + +static int gaole_test_thread(void *data) +{ + int i,j,k; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + for(i=0;i<10;i++){ + + data_ptr[i] = kmalloc(BUF_LEN,GFP_KERNEL); + if (NULL == data_ptr[i]) + { + SDIOTRAN_ERR("kmalloc send buf%d err!!!",i); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc send buf%d ok!!!",i); + + for(j=0;j<BUF_LEN;j++) + *(data_ptr[i]+j) = 0; + + } + + for(j=0,k=0;j<BUF_LEN;j++,k++) + *(data_ptr[0]+j) = (k<=255?k:(k=0,k)); + + while(1) + { + if(1 == continue_send) + { + continue_send = 0; + msleep(1000); + test_sdio_send_func(test_send_chn,data_ptr[test_send_chn]); + + + test_send_chn++; + if(8 == test_send_chn) + { + test_send_chn = 0; + } + } + else + msleep(1); + } + return 0; +} + + +void gaole_creat_test(void) +{ + struct task_struct * task; + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} + +#endif//SDIO_TEST_CASE6 + +#if defined(SDIO_TEST_CASE7)//test speed + +#define SEND_BUF_LEN 1024 //SDIO_TEST_CASE7 + +char *data_send_ptr[17] = {0}; + + +static void test_sdio_send_func(int chn,void* data_buf) +{ + + uint32 datalen; + + char *tmp = (char*)data_buf; + + //SDIOTRAN_ERR("\nrun to test_sdio_send_func!!!\n"); + + while(!sdio_dev_chn_idle(chn)); + + while(1) + { + datalen = sdio_dev_get_chn_datalen(chn); + if(datalen) + { + //SDIOTRAN_ERR("channel %d len is =%d!!\r\n",chn,datalen); + break; + } + else + ;//SDIOTRAN_ERR("channel %d len is =%d!!\r\n",chn,datalen); + + } + /* + SDIOTRAN_ERR("\nap send data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!\n",\ + tmp[0],\ + tmp[1],\ + tmp[2],\ + tmp[3], \ + tmp[101], \ + tmp[102], \ + tmp[103], \ + tmp[104], \ + tmp[230], \ + tmp[231], \ + tmp[232], \ + tmp[233] \ + );*/ + + sdio_dev_write(chn,data_buf,datalen); + +} + + + +static int gaole_test_thread(void *data) +{ + int i,j,k; + + static struct timeval start_time; + static struct timeval stop_time; + static signed long long elapsed_time; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + for(i=0;i<16;i++){ + + data_send_ptr[i] = kmalloc(SEND_BUF_LEN,GFP_KERNEL); + if (NULL == data_send_ptr[i]) + { + SDIOTRAN_ERR("kmalloc send buf%d err!!!",i); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc send buf%d ok!!!",i); + + for(j=0,k=0;j<SEND_BUF_LEN;j++,k++) + *(data_send_ptr[i]+j) = ((k+i)<=255?(k+i):(k=0,k+i)); + + } + //set_blklen(1); + + + while(1) + { + for(i=0;i<16;i++) + { + do_gettimeofday(&start_time); + + for(j=0;j<100;j++) + test_sdio_send_func(i,data_send_ptr[i]); + + do_gettimeofday(&stop_time); + elapsed_time = timeval_to_ns(&stop_time) - timeval_to_ns(&start_time); + SDIOTRAN_ERR("Chn %d test elapsed_time is %lld!!!",i,elapsed_time); + elapsed_time = 0; + } + break; + + SDIOTRAN_ERR("sdio test write finish!!!"); + } + + return 0; +} + +void gaole_creat_test(void) +{ + struct task_struct * task; + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} + + +#endif//SDIO_TEST_CASE7 + +#if defined(SDIO_TEST_CASE8) + +#define TEST_BUF_LEN 8192 //SDIO_TEST_CASE8 + +char *data_test_ptr = NULL; + +static int gaole_test_count = 0; + +static struct timeval start_time; +static struct timeval stop_time; +static signed long long elapsed_time; + +static int last_chn = 0; +bool stop_test = 0; + +void test_sdio_recv_func(void) +{ + int i; + int read_chn = 0; + int datalen = 0; + + + + //SDIOTRAN_ERR("\nap recv: active_chn is 0x%x!!!\n",active_chn); + + + if(last_chn != read_chn) + { + last_chn = read_chn; + gaole_test_count = 0; + + } + gaole_test_count ++; + + + + //SDIOTRAN_ERR("\nap recv: read_datalen is 0x%x!!!\n",read_datalen); + + //for(i=0;i<TEST_BUF_LEN;i++) + // data_test_ptr[i] = 0; + + sdio_dev_read(read_chn,data_test_ptr,&datalen); + + if(1 == gaole_test_count) + do_gettimeofday(&start_time); + + + if(100 == gaole_test_count) + { + do_gettimeofday(&stop_time); + elapsed_time = timeval_to_ns(&stop_time) - timeval_to_ns(&start_time); + SDIOTRAN_ERR("Chn %d test elapsed_time is %lld!!!",read_chn,elapsed_time); + + elapsed_time = 0; + if(15 == read_chn) + stop_test = 1; + } + /* + SDIOTRAN_ERR("\ncase7:ap recv data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!\n",\ + data_test_ptr[0],\ + data_test_ptr[1],\ + data_test_ptr[2],\ + data_test_ptr[3], \ + data_test_ptr[101], \ + data_test_ptr[102], \ + data_test_ptr[103], \ + data_test_ptr[104], \ + data_test_ptr[251], \ + data_test_ptr[252], \ + data_test_ptr[253], \ + data_test_ptr[254] \ + );*/ +} + + +static void test_sdio_send_func(void) +{ + + uint32 datalen; + + SDIOTRAN_ERR("entry"); + + while(!sdio_dev_chn_idle(0)); + + while(1) + { + datalen = sdio_dev_get_chn_datalen(0); + if(datalen) + { + SDIOTRAN_ERR("channel %d len is =%d!!",0,datalen); + break; + } + else + SDIOTRAN_ERR("channel %d len is =%d!!",0,datalen); + + } + + SDIOTRAN_ERR("ap send data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",\ + data_test_ptr[0],\ + data_test_ptr[1],\ + data_test_ptr[2],\ + data_test_ptr[3], \ + data_test_ptr[101], \ + data_test_ptr[102], \ + data_test_ptr[103], \ + data_test_ptr[104], \ + data_test_ptr[251], \ + data_test_ptr[252], \ + data_test_ptr[253], \ + data_test_ptr[254] \ + ); + + sdio_dev_write(0,data_test_ptr,datalen); + +} + + +static int gaole_test_thread(void *data) +{ + int i,j; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + data_test_ptr = kmalloc(TEST_BUF_LEN,GFP_KERNEL); + if (NULL == data_test_ptr) + { + SDIOTRAN_ERR("kmalloc send buf err!!!"); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc send buf ok!!!"); + + for(i=0,j=0;i<TEST_BUF_LEN;i++,j++) + data_test_ptr[i] = (j<=255?j:(j=0,j)); + + test_sdio_send_func(); + + + while(1) + { + test_sdio_recv_func(); + + if(1 == stop_test) + break; + } + + return 0; +} + +void gaole_creat_test(void) +{ + struct task_struct * task; + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} + + +#endif//SDIO_TEST_CASE8 + + +#if defined(SDIO_TEST_CASE9) + +#define TEST_BUF_LEN 8192 //SDIO_TEST_CASE9 + +#define TEST_SEND_CHN 0 + + +char *data_test_ptr = NULL; + + +int active_chn = 0; +int read_datalen = 0; +static int gaole_test_count = 0; + +static struct timeval start_time; +static struct timeval stop_time; +static signed long long elapsed_time; + +static int last_chn = 0; + +void case9_workq_handler(void) +{ + int i; + + active_chn = 0; + read_datalen = 0; + + active_chn = sdio_dev_get_read_chn(); + //SDIOTRAN_ERR("\nap recv: active_chn is 0x%x!!!\n",active_chn); + + if(-1 == active_chn) + return; + + if(last_chn != active_chn) + { + last_chn = active_chn; + gaole_test_count = 0; + + } + gaole_test_count ++; + + + + //SDIOTRAN_ERR("\nap recv: read_datalen is 0x%x!!!\n",read_datalen); + + //for(i=0;i<TEST_BUF_LEN;i++) + // data_test_ptr[i] = 0; + + sdio_dev_read(active_chn,data_test_ptr,&read_datalen); + + if(2 == gaole_test_count) + do_gettimeofday(&start_time); + + + if(101 == gaole_test_count) + { + do_gettimeofday(&stop_time); + elapsed_time = timeval_to_ns(&stop_time) - timeval_to_ns(&start_time); + SDIOTRAN_ERR("Chn %d test elapsed_time is %lld!!!",active_chn,elapsed_time); + elapsed_time = 0; + } + /* + SDIOTRAN_ERR("\ncase7:ap recv data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!\n",\ + data_test_ptr[0],\ + data_test_ptr[1],\ + data_test_ptr[2],\ + data_test_ptr[3], \ + data_test_ptr[101], \ + data_test_ptr[102], \ + data_test_ptr[103], \ + data_test_ptr[104], \ + data_test_ptr[251], \ + data_test_ptr[252], \ + data_test_ptr[253], \ + data_test_ptr[254] \ + );*/ +} + + +static void test_sdio_send_func(void) +{ + + uint32 datalen; + + SDIOTRAN_ERR("entry"); + + while(!sdio_dev_chn_idle(TEST_SEND_CHN)); + + while(1) + { + datalen = sdio_dev_get_chn_datalen(TEST_SEND_CHN); + if(datalen) + { + SDIOTRAN_ERR("channel %d len is =%d!!",TEST_SEND_CHN,datalen); + break; + } + else + SDIOTRAN_ERR("channel %d len is =%d!!",TEST_SEND_CHN,datalen); + + } + + SDIOTRAN_ERR("ap send data: %d,%d,%d,%d %d,%d,%d,%d %d,%d,%d,%d!!!",\ + data_test_ptr[0],\ + data_test_ptr[1],\ + data_test_ptr[2],\ + data_test_ptr[3], \ + data_test_ptr[101], \ + data_test_ptr[102], \ + data_test_ptr[103], \ + data_test_ptr[104], \ + data_test_ptr[251], \ + data_test_ptr[252], \ + data_test_ptr[253], \ + data_test_ptr[254] \ + ); + + sdio_dev_write(TEST_SEND_CHN,data_test_ptr,datalen); + +} + + +static int gaole_test_thread(void *data) +{ + int i,j; + + struct sched_param param = {.sched_priority = 90}; + + /*set the thread as a real time thread, and its priority is 90*/ + sched_setscheduler(current, SCHED_RR, ¶m); + + data_test_ptr = kmalloc(TEST_BUF_LEN,GFP_KERNEL); + if (NULL == data_test_ptr) + { + SDIOTRAN_ERR("kmalloc send buf err!!!"); + return -1; + } + + SDIOTRAN_DEBUG("kmalloc send buf ok!!!"); + + for(i=0,j=0;i<TEST_BUF_LEN;i++,j++) + data_test_ptr[i] = (j<=255?j:(j=0,j)); + + + while(1) + { + msleep(10); + test_sdio_send_func(); + break; + } + + return 0; +} + +void gaole_creat_test(void) +{ + struct task_struct * task; + + task = kthread_create(gaole_test_thread, NULL, "GaoleTest"); + if(0 != task) + wake_up_process(task); +} +#endif//SDIO_TEST_CASE9 + + diff --git a/drivers/misc/sdiodev/sdio_dev_test.h b/drivers/misc/sdiodev/sdio_dev_test.h new file mode 100644 index 00000000..1259e9ec --- /dev/null +++ b/drivers/misc/sdiodev/sdio_dev_test.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2013 Spreadtrum Communications Inc. + * + * Filename : sdio_dev.h + * Abstract : This file is a implementation for itm sipc command/event function + * + * Authors : gaole.zhang + * + * + * 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 __SDIO_DEV_TEST_H__ +#define __SDIO_DEV_TEST_H__ + +void gaole_creat_test(void); + + +#if defined(SDIO_TEST_CASE4) +void case4_workq_handler(void); + +#endif + + +#if defined(SDIO_TEST_CASE5) +void case5_workq_handler(void); +#endif + +#if defined(SDIO_TEST_CASE6) +void case6_workq_handler(void); + +#endif + + + +#if defined(SDIO_TEST_CASE9) +void case9_workq_handler(void); +#endif + + +#endif//__SDIO_DEV_TEST_H__ |
