1565 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1565 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
#include <FreeRTOS.h>
 | 
						|
#include <task.h>
 | 
						|
#include <timers.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include "kwrap/semaphore.h"
 | 
						|
#include "semphr.h"
 | 
						|
#include "sys.h"
 | 
						|
#include <kwrap/flag.h>
 | 
						|
#include <kwrap/task.h>
 | 
						|
#include <sdio.h>
 | 
						|
 | 
						|
#define u32 unsigned int
 | 
						|
#define u16 unsigned short
 | 
						|
#define u8  unsigned char
 | 
						|
 | 
						|
#define min(a,b) (a > b ? b : a)
 | 
						|
 | 
						|
#define SDIO_HOST_ID_2                      (1)     //< SDIO2 host
 | 
						|
 | 
						|
#define SDIO_IO_R                           0x0         ///< IO Read flag
 | 
						|
#define SDIO_IO_W                           0x1         ///< IO Write flag
 | 
						|
 | 
						|
#define SDIO_IO_BYTEMODE                    0x0         ///< IO byte access mode
 | 
						|
#define SDIO_IO_BLOCKMODE                   0x1         ///< IO block access mode
 | 
						|
 | 
						|
#define SDIO_IO_DIS_RAW                     0x0         ///< Disable IO RAW function
 | 
						|
 | 
						|
#define SDIO_CCCR_IENx                      0x04     /* Function/Master Interrupt Enable */
 | 
						|
 | 
						|
#define SDIO_FBR_BASE(f)    ((f) * 0x100) /* base of function f's FBRs */
 | 
						|
#define SDIO_FBR_CIS            0x09    /* CIS pointer (3 bytes) */
 | 
						|
#define SDIO_FBR_BLKSIZE    0x10    /* block size (2 bytes) */
 | 
						|
#define __must_be_array(x) 0
 | 
						|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 | 
						|
 | 
						|
struct mmc_ios {
 | 
						|
        unsigned int    clock;                  /* clock rate */
 | 
						|
        unsigned short  vdd;
 | 
						|
 | 
						|
/* vdd stores the bit number of the selected voltage range from below. */
 | 
						|
 | 
						|
        unsigned char   bus_mode;               /* command output mode */
 | 
						|
 | 
						|
#define MMC_BUSMODE_OPENDRAIN   1
 | 
						|
#define MMC_BUSMODE_PUSHPULL    2
 | 
						|
 | 
						|
        unsigned char   chip_select;            /* SPI chip select */
 | 
						|
 | 
						|
#define MMC_CS_DONTCARE         0
 | 
						|
#define MMC_CS_HIGH             1
 | 
						|
#define MMC_CS_LOW              2
 | 
						|
 | 
						|
        unsigned char   power_mode;             /* power supply mode */
 | 
						|
 | 
						|
#define MMC_POWER_OFF           0
 | 
						|
#define MMC_POWER_UP            1
 | 
						|
#define MMC_POWER_ON            2
 | 
						|
 | 
						|
        unsigned char   bus_width;              /* data bus width */
 | 
						|
 | 
						|
#define MMC_BUS_WIDTH_1         0
 | 
						|
#define MMC_BUS_WIDTH_4         2
 | 
						|
#define MMC_BUS_WIDTH_8         3
 | 
						|
 | 
						|
        unsigned char   timing;                 /* timing specification used */
 | 
						|
 | 
						|
#define MMC_TIMING_LEGACY       0
 | 
						|
#define MMC_TIMING_MMC_HS       1
 | 
						|
#define MMC_TIMING_SD_HS        2
 | 
						|
};
 | 
						|
 | 
						|
struct mmc_host_ops {
 | 
						|
#if 0
 | 
						|
        void    (*request)(struct mmc_host *host, struct mmc_request *req);
 | 
						|
        /*
 | 
						|
         * Avoid calling these three functions too often or in a "fast path",
 | 
						|
         * since underlaying controller might implement them in an expensive
 | 
						|
         * and/or slow way.
 | 
						|
         *
 | 
						|
         * Also note that these functions might sleep, so don't call them
 | 
						|
         * in the atomic contexts!
 | 
						|
         *
 | 
						|
         * Return values for the get_ro callback should be:
 | 
						|
         *   0 for a read/write card
 | 
						|
         *   1 for a read-only card
 | 
						|
         *   -ENOSYS when not supported (equal to NULL callback)
 | 
						|
         *   or a negative errno value when something bad happened
 | 
						|
         *
 | 
						|
         * Return values for the get_cd callback should be:
 | 
						|
         *   0 for a absent card
 | 
						|
         *   1 for a present card
 | 
						|
         *   -ENOSYS when not supported (equal to NULL callback)
 | 
						|
         *   or a negative errno value when something bad happened
 | 
						|
         */
 | 
						|
        void    (*set_ios)(struct mmc_host *host, struct mmc_ios *ios);
 | 
						|
        int     (*get_ro)(struct mmc_host *host);
 | 
						|
        int     (*get_cd)(struct mmc_host *host);
 | 
						|
 | 
						|
        void    (*enable_sdio_irq)(struct mmc_host *host, int enable);
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
struct mmc_host {
 | 
						|
        //struct device         *parent;
 | 
						|
        //struct device         class_dev;
 | 
						|
        int                     index;
 | 
						|
        const struct mmc_host_ops *ops;
 | 
						|
        unsigned int            f_min;
 | 
						|
        unsigned int            f_max;
 | 
						|
        u32                     ocr_avail;
 | 
						|
 | 
						|
#define MMC_VDD_165_195         0x00000080      /* VDD voltage 1.65 - 1.95 */
 | 
						|
#define MMC_VDD_20_21           0x00000100      /* VDD voltage 2.0 ~ 2.1 */
 | 
						|
#define MMC_VDD_21_22           0x00000200      /* VDD voltage 2.1 ~ 2.2 */
 | 
						|
#define MMC_VDD_22_23           0x00000400      /* VDD voltage 2.2 ~ 2.3 */
 | 
						|
#define MMC_VDD_23_24           0x00000800      /* VDD voltage 2.3 ~ 2.4 */
 | 
						|
#define MMC_VDD_24_25           0x00001000      /* VDD voltage 2.4 ~ 2.5 */
 | 
						|
#define MMC_VDD_25_26           0x00002000      /* VDD voltage 2.5 ~ 2.6 */
 | 
						|
#define MMC_VDD_26_27           0x00004000      /* VDD voltage 2.6 ~ 2.7 */
 | 
						|
#define MMC_VDD_27_28           0x00008000      /* VDD voltage 2.7 ~ 2.8 */
 | 
						|
#define MMC_VDD_28_29           0x00010000      /* VDD voltage 2.8 ~ 2.9 */
 | 
						|
#define MMC_VDD_29_30           0x00020000      /* VDD voltage 2.9 ~ 3.0 */
 | 
						|
#define MMC_VDD_30_31           0x00040000      /* VDD voltage 3.0 ~ 3.1 */
 | 
						|
#define MMC_VDD_31_32           0x00080000      /* VDD voltage 3.1 ~ 3.2 */
 | 
						|
#define MMC_VDD_32_33           0x00100000      /* VDD voltage 3.2 ~ 3.3 */
 | 
						|
#define MMC_VDD_33_34           0x00200000      /* VDD voltage 3.3 ~ 3.4 */
 | 
						|
#define MMC_VDD_34_35           0x00400000      /* VDD voltage 3.4 ~ 3.5 */
 | 
						|
#define MMC_VDD_35_36           0x00800000      /* VDD voltage 3.5 ~ 3.6 */
 | 
						|
 | 
						|
        unsigned long           caps;           /* Host capabilities */
 | 
						|
 | 
						|
#define MMC_CAP_4_BIT_DATA      (1 << 0)        /* Can the host do 4 bit transfers */
 | 
						|
#define MMC_CAP_MMC_HIGHSPEED   (1 << 1)        /* Can do MMC high-speed timing */
 | 
						|
#define MMC_CAP_SD_HIGHSPEED    (1 << 2)        /* Can do SD high-speed timing */
 | 
						|
#define MMC_CAP_SDIO_IRQ        (1 << 3)        /* Can signal pending SDIO IRQs */
 | 
						|
#define MMC_CAP_SPI             (1 << 4)        /* Talks only SPI protocols */
 | 
						|
#define MMC_CAP_NEEDS_POLL      (1 << 5)        /* Needs polling for card-detection */
 | 
						|
#define MMC_CAP_8_BIT_DATA      (1 << 6)        /* Can the host do 8 bit transfers */
 | 
						|
 | 
						|
        /* host specific block data */
 | 
						|
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
 | 
						|
        unsigned short          max_hw_segs;    /* see blk_queue_max_hw_segments */
 | 
						|
        unsigned short          max_phys_segs;  /* see blk_queue_max_phys_segments */
 | 
						|
        unsigned short          unused;
 | 
						|
        unsigned int            max_req_size;   /* maximum number of bytes in one req */
 | 
						|
        unsigned int            max_blk_size;   /* maximum size of one mmc block */
 | 
						|
        unsigned int            max_blk_count;  /* maximum number of blocks in one req */
 | 
						|
 | 
						|
        /* private data */
 | 
						|
        //spinlock_t            lock;           /* lock for claim and bus ops */
 | 
						|
 | 
						|
        struct mmc_ios          ios;            /* current io bus settings */
 | 
						|
        u32                     ocr;            /* the current OCR setting */
 | 
						|
 | 
						|
        /* group bitfields together to minimize padding */
 | 
						|
        unsigned int            use_spi_crc:1;
 | 
						|
        unsigned int            claimed:1;      /* host exclusively claimed */
 | 
						|
        unsigned int            bus_dead:1;     /* bus has been released */
 | 
						|
#ifdef CONFIG_MMC_DEBUG
 | 
						|
        unsigned int            removed:1;      /* host is being removed */
 | 
						|
#endif
 | 
						|
 | 
						|
        struct mmc_card         *card;          /* device attached to this host */
 | 
						|
 | 
						|
        //wait_queue_head_t     wq;
 | 
						|
 | 
						|
        //struct delayed_work   detect;
 | 
						|
 | 
						|
        //const struct mmc_bus_ops *bus_ops;    /* current bus driver */
 | 
						|
        unsigned int            bus_refs;       /* reference counter */
 | 
						|
 | 
						|
        //unsigned int          sdio_irqs;
 | 
						|
        //struct task_struct    *sdio_irq_thread;
 | 
						|
        //atomic_t              sdio_irq_thread_abort;
 | 
						|
 | 
						|
#ifdef CONFIG_LEDS_TRIGGERS
 | 
						|
        struct led_trigger      *led;           /* activity led */
 | 
						|
#endif
 | 
						|
 | 
						|
        //struct dentry         *debugfs_root;
 | 
						|
 | 
						|
        //unsigned long         private[0] ____cacheline_aligned;
 | 
						|
};
 | 
						|
 | 
						|
struct sdio_func_tuple {
 | 
						|
    struct sdio_func_tuple *next;
 | 
						|
    unsigned char code;
 | 
						|
    unsigned char size;
 | 
						|
    unsigned char data[0];
 | 
						|
};
 | 
						|
 | 
						|
struct sdio_func {
 | 
						|
	struct mmc_card *card;
 | 
						|
	void            (*irq_handler)(struct sdio_func *);
 | 
						|
	unsigned int    max_blksize;
 | 
						|
	unsigned int    cur_blksize;
 | 
						|
	unsigned int    enable_timeout;
 | 
						|
	unsigned int    num;
 | 
						|
	unsigned short  vendor;
 | 
						|
	unsigned short  device;
 | 
						|
	unsigned        num_info;
 | 
						|
	const char      **info;
 | 
						|
	unsigned char   class;
 | 
						|
	unsigned int    tmpbuf_reserved;
 | 
						|
	unsigned char   tmpbuf[4];
 | 
						|
	void *drv_priv;
 | 
						|
};
 | 
						|
 | 
						|
struct sdio_cccr {
 | 
						|
	unsigned int sdio_vsn;
 | 
						|
	unsigned int sd_vsn;
 | 
						|
	unsigned int multi_block:1;
 | 
						|
	unsigned int low_speed:1;
 | 
						|
	unsigned int wide_bus:1;
 | 
						|
	unsigned int high_power:1;
 | 
						|
	unsigned int high_speed:1;
 | 
						|
	unsigned int disable_cd:1;
 | 
						|
};
 | 
						|
 | 
						|
struct sdio_cis {
 | 
						|
	unsigned short vendor;
 | 
						|
	unsigned short device;
 | 
						|
	unsigned short blksize;
 | 
						|
	unsigned int   max_dtr;
 | 
						|
};
 | 
						|
 | 
						|
struct mmc_card {
 | 
						|
	struct mmc_host        *host;
 | 
						|
	struct sdio_cccr       cccr;
 | 
						|
	struct sdio_cis        cis;
 | 
						|
	struct sdio_func       *sdio_func[7];
 | 
						|
	unsigned int           sdio_funcs;
 | 
						|
	unsigned int           rca;
 | 
						|
	unsigned int           type;
 | 
						|
	unsigned               num_info;
 | 
						|
	const char             **info;
 | 
						|
	struct sdio_func_tuple *tuples;
 | 
						|
};
 | 
						|
 | 
						|
typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
 | 
						|
                           const unsigned char *, unsigned);
 | 
						|
 | 
						|
struct cis_tpl {
 | 
						|
        unsigned char code;
 | 
						|
        unsigned char min_size;
 | 
						|
        tpl_parse_t *parse;
 | 
						|
};
 | 
						|
 | 
						|
typedef enum
 | 
						|
{
 | 
						|
    SDIO_HOST_IOINT_DIS = 0,      ///< sdio host io interrupt enable
 | 
						|
    SDIO_HOST_IOINT_EN  = 1       ///< sdio host io interrupt disable
 | 
						|
}SDIO_HOST_IOINT_ENDIS;	
 | 
						|
 | 
						|
static struct mmc_card sdiocard;
 | 
						|
static struct mmc_host sdiohost;
 | 
						|
static struct sdio_func func_sdio = { 0 };
 | 
						|
struct sdio_func *wifi_sdio_func = &func_sdio;
 | 
						|
static struct sdio_func_tuple *func_tuples = NULL;
 | 
						|
static struct sdio_func_tuple *card_tuples = NULL;
 | 
						|
static struct sdio_func *save_sdio_func;
 | 
						|
static void(*vpSdioLinuxIoHdl)(struct sdio_func *) = NULL;
 | 
						|
 | 
						|
static SEM_HANDLE wifi_sdio_mutex;
 | 
						|
static TaskHandle_t sdio_irq_task_handler;
 | 
						|
static ID FLG_ID_WIFI_SDIO;
 | 
						|
#define FLGPTN_WIFI_SDIO  0x4
 | 
						|
 | 
						|
#define uimempoolsize 512
 | 
						|
static unsigned char uimempool[uimempoolsize];
 | 
						|
 | 
						|
static unsigned int func_max_byte_size = 512u;
 | 
						|
 | 
						|
static unsigned int sdio_max_byte_size(struct sdio_func *func)
 | 
						|
{
 | 
						|
    //?? todo
 | 
						|
    #if 0
 | 
						|
    unsigned mval = min(func->card->host->max_seg_size,
 | 
						|
                func->card->host->max_blk_size);
 | 
						|
    mval = min(mval, func->max_blksize);
 | 
						|
    return min(mval, 512u); /* maximum size for byte mode */
 | 
						|
    #else
 | 
						|
    return func_max_byte_size;
 | 
						|
    #endif
 | 
						|
    //?? todo end
 | 
						|
}
 | 
						|
 | 
						|
void sdio_set_max_byte_size(struct sdio_func *func, unsigned int size)
 | 
						|
{
 | 
						|
    func_max_byte_size = size;
 | 
						|
    //?? todo end
 | 
						|
}
 | 
						|
 | 
						|
static int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, unsigned addr, u8 in, u8* out)
 | 
						|
{
 | 
						|
    SDIO_CMD52_STRUCT cmd52;
 | 
						|
 | 
						|
    unsigned char rw;
 | 
						|
    //cyg_io_handle_t handle;
 | 
						|
    //unsigned char data;
 | 
						|
 | 
						|
    if (write)
 | 
						|
        rw = SDIO_IO_W;
 | 
						|
    else
 | 
						|
        rw = SDIO_IO_R;
 | 
						|
 | 
						|
    cmd52.Function_Num = (unsigned char)fn;
 | 
						|
    cmd52.Reg_Addr = (unsigned long)addr;
 | 
						|
    if (write)
 | 
						|
        cmd52.pData = (unsigned char *)∈
 | 
						|
    else
 | 
						|
        cmd52.pData = (unsigned char *)out;
 | 
						|
    cmd52.ByteCount = 1;
 | 
						|
    cmd52.RW_flag = rw;
 | 
						|
    cmd52.RAW = SDIO_IO_DIS_RAW;
 | 
						|
    cmd52.Stuff = 0;
 | 
						|
 | 
						|
	extern int sdio2_sendIOCMD52(PSDIO_CMD52_STRUCT pSDIO_CMD52);
 | 
						|
    if(sdio2_sendIOCMD52(&cmd52))
 | 
						|
    {
 | 
						|
        printf("mmc_io_rw_direct error\r\n");
 | 
						|
 | 
						|
        //if (vpSdioCmdErrHdl)
 | 
						|
        //    vpSdioCmdErrHdl(SDIO_HOST_ERR_CMD52);
 | 
						|
        //return -EIO;
 | 
						|
		return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
 | 
						|
    unsigned addr, int incr_addr, u8 *buf, unsigned blocks, unsigned blksz)
 | 
						|
{
 | 
						|
 | 
						|
    SDIO_CMD53_STRUCT cmd53;
 | 
						|
 | 
						|
    unsigned char rw;
 | 
						|
    //cyg_io_handle_t handle;
 | 
						|
    unsigned char uiblock;
 | 
						|
    unsigned int  uibytecnt;
 | 
						|
 | 
						|
    if (write)
 | 
						|
        rw = SDIO_IO_W;
 | 
						|
    else
 | 
						|
        rw = SDIO_IO_R;
 | 
						|
 | 
						|
    cmd53.Function_Num = (unsigned char)fn;
 | 
						|
    cmd53.Reg_Addr = (unsigned int)addr;
 | 
						|
    cmd53.pData = (unsigned char *)buf;
 | 
						|
    cmd53.OpCode = incr_addr;
 | 
						|
    cmd53.RW_flag = rw;
 | 
						|
    cmd53.Stuff = 0;
 | 
						|
 | 
						|
    if (blocks == 1 && blksz <= 512)
 | 
						|
    {
 | 
						|
        //uibytecnt = (blksz == 512) ? 0 : blksz; /* byte mode */
 | 
						|
        uibytecnt = blksz;
 | 
						|
        uiblock = SDIO_IO_BYTEMODE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        uiblock = SDIO_IO_BLOCKMODE;
 | 
						|
        uibytecnt =  blocks;        /* block mode */
 | 
						|
    }
 | 
						|
 | 
						|
    cmd53.Block = uiblock;
 | 
						|
    cmd53.ByteCount = uibytecnt;
 | 
						|
 | 
						|
	extern int sdio2_sendIOCMD53(PSDIO_CMD53_STRUCT pSDIO_CMD53);
 | 
						|
    if(sdio2_sendIOCMD53((void *)&cmd53))
 | 
						|
    {
 | 
						|
        printf("mmc_io_rw_extended error\r\n");
 | 
						|
 | 
						|
        //if (vpSdioCmdErrHdl)
 | 
						|
        //    vpSdioCmdErrHdl(SDIO_HOST_ERR_CMD53);
 | 
						|
 | 
						|
        //return -EIO;
 | 
						|
		return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static int mmc_io_rw_ext_helper(struct sdio_func *func, int write,
 | 
						|
    unsigned addr, int incr_addr, u8 *buf, unsigned size)
 | 
						|
{
 | 
						|
    unsigned remainder = size;
 | 
						|
    unsigned max_blocks;
 | 
						|
    int ret;
 | 
						|
 | 
						|
    /* Do the bulk of the transfer using block mode (if supported). */
 | 
						|
    if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
 | 
						|
        /* Blocks per command is limited by host count, host transfer
 | 
						|
         * size (we only use a single sg entry) and the maximum for
 | 
						|
         * IO_RW_EXTENDED of 511 blocks. */
 | 
						|
        //??
 | 
						|
        //?? todo
 | 
						|
        /*max_blocks = min(func->card->host->max_blk_count,
 | 
						|
            func->card->host->max_seg_size / func->cur_blksize);
 | 
						|
        max_blocks = min(max_blocks, 511u);*/
 | 
						|
        max_blocks = 511u;
 | 
						|
        //?? todo end
 | 
						|
 | 
						|
        while (remainder > func->cur_blksize) {
 | 
						|
            unsigned blocks;
 | 
						|
 | 
						|
            blocks = remainder / func->cur_blksize;
 | 
						|
            if (blocks > max_blocks)
 | 
						|
                blocks = max_blocks;
 | 
						|
            size = blocks * func->cur_blksize;
 | 
						|
 | 
						|
            ret = mmc_io_rw_extended(func->card, write,
 | 
						|
                func->num, addr, incr_addr, buf,
 | 
						|
                blocks, func->cur_blksize);
 | 
						|
            if (ret)
 | 
						|
                return ret;
 | 
						|
 | 
						|
            remainder -= size;
 | 
						|
            buf += size;
 | 
						|
            if (incr_addr)
 | 
						|
                addr += size;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Write the remainder using byte mode. */
 | 
						|
    while (remainder > 0) {
 | 
						|
        size = min(remainder, sdio_max_byte_size(func));
 | 
						|
 | 
						|
        ret = mmc_io_rw_extended(func->card, write, func->num, addr,
 | 
						|
             incr_addr, buf, 1, size);
 | 
						|
        if (ret)
 | 
						|
            return ret;
 | 
						|
 | 
						|
        remainder -= size;
 | 
						|
        buf += size;
 | 
						|
        if (incr_addr)
 | 
						|
            addr += size;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int sdio_cardDetectCB(void)
 | 
						|
{
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
static int sdio_writeProtCB(void)
 | 
						|
{
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int sdio_read_cccr(struct mmc_card *card)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    int cccr_vsn;
 | 
						|
    unsigned char data;
 | 
						|
 | 
						|
    memset(&card->cccr, 0, sizeof(struct sdio_cccr));
 | 
						|
 | 
						|
#define SDIO_CCCR_CCCR          0x00
 | 
						|
    ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data);
 | 
						|
    if (ret)
 | 
						|
        goto out;
 | 
						|
 | 
						|
    cccr_vsn = data & 0x0f;
 | 
						|
 | 
						|
#define  SDIO_CCCR_REV_3_00 3   /* CCCR/FBR Version 3.00 */
 | 
						|
    if (cccr_vsn > SDIO_CCCR_REV_3_00) {
 | 
						|
        //??printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n",
 | 
						|
        //??    mmc_hostname(card->host), cccr_vsn);
 | 
						|
		printf("unrecognised CCCR structure version %d\n", cccr_vsn);
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    card->cccr.sdio_vsn = (data & 0xf0) >> 4;
 | 
						|
 | 
						|
#define SDIO_CCCR_CAPS          0x08
 | 
						|
    ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CAPS, 0, &data);
 | 
						|
    if (ret)
 | 
						|
        goto out;
 | 
						|
 | 
						|
#define  SDIO_CCCR_CAP_SMB      0x02    /* can do multi-block xfers (CMD53) */
 | 
						|
    if (data & SDIO_CCCR_CAP_SMB)
 | 
						|
        card->cccr.multi_block = 1;
 | 
						|
#define  SDIO_CCCR_CAP_LSC      0x40    /* low speed card */
 | 
						|
    if (data & SDIO_CCCR_CAP_LSC)
 | 
						|
        card->cccr.low_speed = 1;
 | 
						|
#define  SDIO_CCCR_CAP_4BLS     0x80    /* 4 bit low speed card */
 | 
						|
    if (data & SDIO_CCCR_CAP_4BLS)
 | 
						|
        card->cccr.wide_bus = 1;
 | 
						|
 | 
						|
#define  SDIO_CCCR_REV_1_10     1       /* CCCR/FBR Version 1.10 */
 | 
						|
    if (cccr_vsn >= SDIO_CCCR_REV_1_10) {
 | 
						|
#define SDIO_CCCR_POWER         0x12
 | 
						|
        ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_POWER, 0, &data);
 | 
						|
        if (ret)
 | 
						|
            goto out;
 | 
						|
 | 
						|
#define  SDIO_POWER_SMPC        0x01    /* Supports Master Power Control */
 | 
						|
        if (data & SDIO_POWER_SMPC)
 | 
						|
            card->cccr.high_power = 1;
 | 
						|
    }
 | 
						|
 | 
						|
#define  SDIO_CCCR_REV_1_20     2       /* CCCR/FBR Version 1.20 */
 | 
						|
    if (cccr_vsn >= SDIO_CCCR_REV_1_20) {
 | 
						|
#define SDIO_CCCR_SPEED         0x13
 | 
						|
        ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data);
 | 
						|
        if (ret)
 | 
						|
            goto out;
 | 
						|
 | 
						|
#define  SDIO_SPEED_SHS         0x01    /* Supports High-Speed mode */
 | 
						|
        if (data & SDIO_SPEED_SHS)
 | 
						|
            card->cccr.high_speed = 1;
 | 
						|
    }
 | 
						|
 | 
						|
out:
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
 | 
						|
                         const unsigned char *buf, unsigned size)
 | 
						|
{
 | 
						|
        unsigned i, nr_strings;
 | 
						|
        char **buffer, *string;
 | 
						|
 | 
						|
        buf += 2;
 | 
						|
        size -= 2;
 | 
						|
 | 
						|
        nr_strings = 0;
 | 
						|
        for (i = 0; i < size; i++) {
 | 
						|
                if (buf[i] == 0xff)
 | 
						|
                        break;
 | 
						|
                if (buf[i] == 0)
 | 
						|
                        nr_strings++;
 | 
						|
        }
 | 
						|
 | 
						|
        if (buf[i-1] != '\0') {
 | 
						|
                printf("SDIO: ignoring broken CISTPL_VERS_1\n");
 | 
						|
                return 0;
 | 
						|
        }
 | 
						|
        size = i;
 | 
						|
 | 
						|
        //buffer = kzalloc(sizeof(char*) * nr_strings + size, GFP_KERNEL);
 | 
						|
        buffer = pvPortMalloc(sizeof(char*) * nr_strings + size);
 | 
						|
 | 
						|
        if (!buffer)
 | 
						|
                return -1;
 | 
						|
 | 
						|
        string = (char*)(buffer + nr_strings);
 | 
						|
 | 
						|
        for (i = 0; i < nr_strings; i++) {
 | 
						|
                buffer[i] = string;
 | 
						|
                strcpy(string, (char*)buf);
 | 
						|
                string += strlen(string) + 1;
 | 
						|
                buf += strlen((char*)buf) + 1;
 | 
						|
        }
 | 
						|
 | 
						|
        if (func) {
 | 
						|
                func->num_info = nr_strings;
 | 
						|
                func->info = (const char**)buffer;
 | 
						|
        } else {
 | 
						|
                card->num_info = nr_strings;
 | 
						|
                card->info = (const char**)buffer;
 | 
						|
        }
 | 
						|
 | 
						|
        return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int cistpl_manfid(struct mmc_card *card, struct sdio_func *func,
 | 
						|
                         const unsigned char *buf, unsigned size)
 | 
						|
{
 | 
						|
        unsigned int vendor, device;
 | 
						|
 | 
						|
        /* TPLMID_MANF */
 | 
						|
        vendor = buf[0] | (buf[1] << 8);
 | 
						|
 | 
						|
        /* TPLMID_CARD */
 | 
						|
        device = buf[2] | (buf[3] << 8);
 | 
						|
 | 
						|
        if (func) {
 | 
						|
                func->vendor = vendor;
 | 
						|
                func->device = device;
 | 
						|
        } else {
 | 
						|
                card->cis.vendor = vendor;
 | 
						|
                card->cis.device = device;
 | 
						|
        }
 | 
						|
 | 
						|
        return 0;
 | 
						|
}
 | 
						|
 | 
						|
static const unsigned char speed_val[16] =
 | 
						|
        { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
 | 
						|
static const unsigned int speed_unit[8] =
 | 
						|
        { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
 | 
						|
 | 
						|
static int cistpl_funce_common(struct mmc_card *card,
 | 
						|
                               const unsigned char *buf, unsigned size)
 | 
						|
{
 | 
						|
        if (size < 0x04 || buf[0] != 0)
 | 
						|
                return -1;
 | 
						|
 | 
						|
        /* TPLFE_FN0_BLK_SIZE */
 | 
						|
        card->cis.blksize = buf[1] | (buf[2] << 8);
 | 
						|
 | 
						|
        /* TPLFE_MAX_TRAN_SPEED */
 | 
						|
        card->cis.max_dtr = speed_val[(buf[3] >> 3) & 15] *
 | 
						|
                            speed_unit[buf[3] & 7];
 | 
						|
 | 
						|
        return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int cistpl_funce_func(struct sdio_func *func,
 | 
						|
                             const unsigned char *buf, unsigned size)
 | 
						|
{
 | 
						|
        unsigned vsn;
 | 
						|
        unsigned min_size;
 | 
						|
 | 
						|
        vsn = func->card->cccr.sdio_vsn;
 | 
						|
#define  SDIO_SDIO_REV_1_00     0       /* SDIO Spec Version 1.00 */
 | 
						|
        min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
 | 
						|
 | 
						|
        if (size < min_size || buf[0] != 1)
 | 
						|
                return -1;
 | 
						|
 | 
						|
        /* TPLFE_MAX_BLK_SIZE */
 | 
						|
        func->max_blksize = buf[12] | (buf[13] << 8);
 | 
						|
 | 
						|
        /* TPLFE_ENABLE_TIMEOUT_VAL, present in ver 1.1 and above */
 | 
						|
        if (vsn > SDIO_SDIO_REV_1_00)
 | 
						|
                func->enable_timeout = (buf[28] | (buf[29] << 8)) * 10;
 | 
						|
        else
 | 
						|
                func->enable_timeout = 0;//??jiffies_to_msecs(HZ);
 | 
						|
 | 
						|
        return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int cistpl_funce(struct mmc_card *card, struct sdio_func *func,
 | 
						|
                        const unsigned char *buf, unsigned size)
 | 
						|
{
 | 
						|
        int ret;
 | 
						|
 | 
						|
        /*
 | 
						|
         * There should be two versions of the CISTPL_FUNCE tuple,
 | 
						|
         * one for the common CIS (function 0) and a version used by
 | 
						|
         * the individual function's CIS (1-7). Yet, the later has a
 | 
						|
         * different length depending on the SDIO spec version.
 | 
						|
         */
 | 
						|
        if (func)
 | 
						|
                ret = cistpl_funce_func(func, buf, size);
 | 
						|
        else
 | 
						|
                ret = cistpl_funce_common(card, buf, size);
 | 
						|
 | 
						|
        if (ret) {
 | 
						|
                printf("bad CISTPL_FUNCE size %u,type %u\n", size, buf[0]);
 | 
						|
                return ret;
 | 
						|
        }
 | 
						|
 | 
						|
        return 0;
 | 
						|
}
 | 
						|
 | 
						|
static const struct cis_tpl cis_tpl_list[] = {
 | 
						|
        {       0x15,   3,      cistpl_vers_1           },
 | 
						|
        {       0x20,   4,      cistpl_manfid           },
 | 
						|
        {       0x21,   2,      /* cistpl_funcid */     },
 | 
						|
        {       0x22,   0,      cistpl_funce            },
 | 
						|
};
 | 
						|
 | 
						|
static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
 | 
						|
{
 | 
						|
        int ret;
 | 
						|
        struct sdio_func_tuple *this, **prev;
 | 
						|
        unsigned i, ptr = 0;
 | 
						|
 | 
						|
        /*
 | 
						|
         * Note that this works for the common CIS (function number 0) as
 | 
						|
         * well as a function's CIS * since SDIO_CCCR_CIS and SDIO_FBR_CIS
 | 
						|
         * have the same offset.
 | 
						|
         */
 | 
						|
         for (i = 0; i < 3; i++) {
 | 
						|
                unsigned char x, fn;
 | 
						|
 | 
						|
                if (func)
 | 
						|
                        fn = func->num;
 | 
						|
                else
 | 
						|
                        fn = 0;
 | 
						|
 | 
						|
                ret = mmc_io_rw_direct(card, 0, 0,
 | 
						|
                        SDIO_FBR_BASE(fn) + SDIO_FBR_CIS + i, 0, &x);
 | 
						|
 | 
						|
                if (ret)
 | 
						|
                        return ret;
 | 
						|
                ptr |= x << (i * 8);
 | 
						|
				printf("tpl_ptr = 0x%x\r\n", ptr);
 | 
						|
        }
 | 
						|
        if (func)
 | 
						|
                //prev = &func->tuples;
 | 
						|
				prev = &func_tuples;
 | 
						|
        else
 | 
						|
                //prev = &card->tuples;
 | 
						|
				prev = &card_tuples;
 | 
						|
 | 
						|
        //BUG_ON(*prev);
 | 
						|
 | 
						|
        do {
 | 
						|
                unsigned char tpl_code, tpl_link;
 | 
						|
 | 
						|
                ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code);
 | 
						|
				printf("tpl_code = 0x%02x\r\n", tpl_code);
 | 
						|
                if (ret)
 | 
						|
                        break;
 | 
						|
 | 
						|
                /* 0xff means we're done */
 | 
						|
                if (tpl_code == 0xff)
 | 
						|
                        break;
 | 
						|
 | 
						|
                /* null entries have no link field or data */
 | 
						|
                if (tpl_code == 0x00)
 | 
						|
                        continue;
 | 
						|
 | 
						|
                ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
 | 
						|
				printf("tpl_link = 0x%02x\r\n", tpl_link);
 | 
						|
                if (ret)
 | 
						|
                        break;
 | 
						|
 | 
						|
                /* a size of 0xff also means we're done */
 | 
						|
                if (tpl_link == 0xff)
 | 
						|
                {
 | 
						|
						printf("tpl_link done, because equals to 0xff\r\n");
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
 | 
						|
                this = pvPortMalloc(sizeof(*this) + tpl_link);
 | 
						|
                if (!this)
 | 
						|
                        return -1;
 | 
						|
 | 
						|
				printf("tpl_data =\r\n");
 | 
						|
                for (i = 0; i < tpl_link; i++) {
 | 
						|
                        ret = mmc_io_rw_direct(card, 0, 0,
 | 
						|
                                               ptr + i, 0, &this->data[i]);
 | 
						|
 | 
						|
					printf("0x%02x  ", this->data[i]);
 | 
						|
					if ((i % 8) == 7)
 | 
						|
					{
 | 
						|
						printf("\r\n");
 | 
						|
					}
 | 
						|
					if (ret)
 | 
						|
						break;
 | 
						|
                }
 | 
						|
                if (ret) {
 | 
						|
                        vPortFree(this);
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
 | 
						|
				printf("\r\ni = %d, ARRAY_SIZE = %d\r\n", i, ARRAY_SIZE(cis_tpl_list));
 | 
						|
				for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
 | 
						|
					if (cis_tpl_list[i].code == tpl_code)
 | 
						|
						break;
 | 
						|
 | 
						|
				if (i >= ARRAY_SIZE(cis_tpl_list))
 | 
						|
				{
 | 
						|
                        /* this tuple is unknown to the core */
 | 
						|
                        this->next = NULL;
 | 
						|
                        this->code = tpl_code;
 | 
						|
                        this->size = tpl_link;
 | 
						|
                        *prev = this;
 | 
						|
                        prev = &this->next;
 | 
						|
						printf("queuing CIS tuple 0x%02x length %u\n", tpl_code, tpl_link);
 | 
						|
                } else {
 | 
						|
                        const struct cis_tpl *tpl = cis_tpl_list + i;
 | 
						|
                        if (tpl_link < tpl->min_size)
 | 
						|
						{
 | 
						|
								printf("bad CIS tuple 0x%02x (length = %u, expected >= %u)\n",tpl_code, tpl_link, tpl->min_size);
 | 
						|
                                ret = -1;
 | 
						|
                        } else if (tpl->parse) {
 | 
						|
                                ret = tpl->parse(card, func,
 | 
						|
                                                 this->data, tpl_link);
 | 
						|
                        }
 | 
						|
                        vPortFree(this);
 | 
						|
                }
 | 
						|
 | 
						|
                ptr += tpl_link;
 | 
						|
        } while (!ret);
 | 
						|
 | 
						|
        /*
 | 
						|
         * Link in all unknown tuples found in the common CIS so that
 | 
						|
         * drivers don't have to go digging in two places.
 | 
						|
         */
 | 
						|
        if (func)
 | 
						|
                //*prev = card->tuples;
 | 
						|
				*prev = card_tuples;
 | 
						|
 | 
						|
        return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int sdio_read_common_cis(struct mmc_card *card)
 | 
						|
{
 | 
						|
        return sdio_read_cis(card, NULL);
 | 
						|
}
 | 
						|
 | 
						|
static struct sdio_func *sdio_alloc_func(struct mmc_card *card)
 | 
						|
{
 | 
						|
        struct sdio_func *func;
 | 
						|
 | 
						|
        func = pvPortMalloc(sizeof(struct sdio_func));
 | 
						|
		if (!func)
 | 
						|
			return NULL;
 | 
						|
 | 
						|
		memset(func, 0, sizeof(struct sdio_func));
 | 
						|
        func->card = card;
 | 
						|
 | 
						|
        //device_initialize(&func->dev);
 | 
						|
 | 
						|
        //??func->dev.parent = &card->dev;
 | 
						|
        //??func->dev.bus = &sdio_bus_type;
 | 
						|
        //??func->dev.release = sdio_release_func;
 | 
						|
 | 
						|
        return func;
 | 
						|
}
 | 
						|
 | 
						|
static int sdio_read_fbr(struct sdio_func *func)
 | 
						|
{
 | 
						|
        int ret;
 | 
						|
        unsigned char data;
 | 
						|
 | 
						|
#define SDIO_FBR_STD_IF  0x00
 | 
						|
        ret = mmc_io_rw_direct(func->card, 0, 0,
 | 
						|
                SDIO_FBR_BASE(func->num) + SDIO_FBR_STD_IF, 0, &data);
 | 
						|
        if (ret)
 | 
						|
                goto out;
 | 
						|
 | 
						|
        data &= 0x0f;
 | 
						|
 | 
						|
        if (data == 0x0f) {
 | 
						|
#define SDIO_FBR_STD_IF_EXT       0x01
 | 
						|
                ret = mmc_io_rw_direct(func->card, 0, 0,
 | 
						|
                        SDIO_FBR_BASE(func->num) + SDIO_FBR_STD_IF_EXT, 0, &data);
 | 
						|
                if (ret)
 | 
						|
                        goto out;
 | 
						|
        }
 | 
						|
 | 
						|
        func->class = data;
 | 
						|
 | 
						|
out:
 | 
						|
        return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int sdio_read_func_cis(struct sdio_func *func)
 | 
						|
{
 | 
						|
        int ret;
 | 
						|
 | 
						|
        ret = sdio_read_cis(func->card, func);
 | 
						|
        if (ret)
 | 
						|
                return ret;
 | 
						|
 | 
						|
        /*
 | 
						|
         * Since we've linked to tuples in the card structure,
 | 
						|
         * we must make sure we have a reference to it.
 | 
						|
         */
 | 
						|
        //get_device(&func->card->dev);
 | 
						|
 | 
						|
        /*
 | 
						|
         * Vendor/device id is optional for function CIS, so
 | 
						|
         * copy it from the card structure as needed.
 | 
						|
         */
 | 
						|
        if (func->vendor == 0) {
 | 
						|
                func->vendor = func->card->cis.vendor;
 | 
						|
                func->device = func->card->cis.device;
 | 
						|
        }
 | 
						|
 | 
						|
        return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void sdio_remove_func(struct sdio_func *func)
 | 
						|
{
 | 
						|
    //??
 | 
						|
        /*if (sdio_func_present(func))
 | 
						|
                device_del(&func->dev);
 | 
						|
 | 
						|
        put_device(&func->dev);*/
 | 
						|
}
 | 
						|
 | 
						|
static int sdio_init_func(struct mmc_card *card, unsigned int fn)
 | 
						|
{
 | 
						|
        int ret;
 | 
						|
        struct sdio_func *func;
 | 
						|
 | 
						|
        //BUG_ON(fn > SDIO_MAX_FUNCS);
 | 
						|
 | 
						|
        func = sdio_alloc_func(card);
 | 
						|
        if (func == NULL)
 | 
						|
                return -1;
 | 
						|
 | 
						|
        func->num = fn;
 | 
						|
 | 
						|
        ret = sdio_read_fbr(func);
 | 
						|
        if (ret)
 | 
						|
                goto fail;
 | 
						|
 | 
						|
        ret = sdio_read_func_cis(func);
 | 
						|
        if (ret)
 | 
						|
                goto fail;
 | 
						|
 | 
						|
        card->sdio_func[fn - 1] = func;
 | 
						|
 | 
						|
        return 0;
 | 
						|
 | 
						|
fail:
 | 
						|
        /*
 | 
						|
         * It is okay to remove the function here even though we hold
 | 
						|
         * the host lock as we haven't registered the device yet.
 | 
						|
         */
 | 
						|
        sdio_remove_func(func);
 | 
						|
        return ret;
 | 
						|
}
 | 
						|
 | 
						|
int sdio_set_block_size(struct sdio_func *func, unsigned blksz)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
    if (blksz > func->card->host->max_blk_size){
 | 
						|
		printf("sdio_set_block_size:blksz(%d) > max(%d)\n", blksz, func->card->host->max_blk_size);
 | 
						|
        return -1;
 | 
						|
	}
 | 
						|
 | 
						|
    if (blksz == 0) {
 | 
						|
        blksz = min(func->max_blksize, func->card->host->max_blk_size);
 | 
						|
        blksz = min(blksz, 512u);
 | 
						|
    }
 | 
						|
 | 
						|
    ret = mmc_io_rw_direct(func->card, 1, 0,
 | 
						|
        SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
 | 
						|
        blksz & 0xff, NULL);
 | 
						|
    if (ret){
 | 
						|
		printf("sdio_set_block_size:set SDIO_FBR_BLKSIZE fail\n");
 | 
						|
        return ret;
 | 
						|
	}
 | 
						|
    ret = mmc_io_rw_direct(func->card, 1, 0,
 | 
						|
        SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
 | 
						|
        (blksz >> 8) & 0xff, NULL);
 | 
						|
    if (ret){
 | 
						|
		printf("sdio_set_block_size:set SDIO_FBR_BLKSIZE+1 fail\n");
 | 
						|
        return ret;
 | 
						|
	}
 | 
						|
    func->cur_blksize = blksz;
 | 
						|
 | 
						|
    // set sdio host block size
 | 
						|
	extern void sdioHost_setBlkSize(UINT32 id, UINT32 size);
 | 
						|
	sdioHost_setBlkSize(SDIO_HOST_ID_2, blksz);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void sdio_claim_host(struct sdio_func*func)
 | 
						|
{
 | 
						|
        SEM_WAIT(wifi_sdio_mutex);
 | 
						|
}
 | 
						|
 | 
						|
void sdio_release_host(struct sdio_func *func)
 | 
						|
{
 | 
						|
        SEM_SIGNAL(wifi_sdio_mutex);
 | 
						|
}
 | 
						|
 | 
						|
static void sdio_irq_task(void *pvParameters)
 | 
						|
{
 | 
						|
	FLGPTN uiFlag;
 | 
						|
	
 | 
						|
	if(!wifi_sdio_func){
 | 
						|
		printf("sdio_irq_task : wifi_sdio_func is NULL\n");
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	
 | 
						|
	//coverity[no_escape]
 | 
						|
	while(1)
 | 
						|
	{
 | 
						|
		 wai_flg(&uiFlag, FLG_ID_WIFI_SDIO, FLGPTN_WIFI_SDIO, TWF_ORW | TWF_CLR);
 | 
						|
//extern volatile int sdio_io_int_count;
 | 
						|
//printf("task in(%d)\n", sdio_io_int_count);sdio_io_int_count++;
 | 
						|
		//if(sdio_card_intr)
 | 
						|
		{
 | 
						|
			//sdio_card_intr = 0;
 | 
						|
			sdio_claim_host(wifi_sdio_func);
 | 
						|
			if (wifi_sdio_func->irq_handler)
 | 
						|
			{
 | 
						|
				wifi_sdio_func->irq_handler(wifi_sdio_func);
 | 
						|
				//wifi_sdio_func->irq_handler(wifi_sdio_func);
 | 
						|
				//wifi_sdio_func->irq_handler(wifi_sdio_func);
 | 
						|
			}
 | 
						|
			sdio_release_host(wifi_sdio_func);
 | 
						|
		}
 | 
						|
//printf("task out(%d)\n", sdio_io_int_count);sdio_io_int_count++;
 | 
						|
		
 | 
						|
		//extern UINT32 sdioHost_setIoIntEn(unsigned int id, int bEn);
 | 
						|
		//sdioHost_setIoIntEn(SDIO_HOST_ID_2, 1);
 | 
						|
		//vTaskDelay(5);
 | 
						|
	}
 | 
						|
	vTaskDelete(NULL);
 | 
						|
}
 | 
						|
 | 
						|
int wifi_sdio_init(void)
 | 
						|
{
 | 
						|
    int funcs;
 | 
						|
    int i;
 | 
						|
	
 | 
						|
	SEM_CREATE(wifi_sdio_mutex, 1);
 | 
						|
	cre_flg(&FLG_ID_WIFI_SDIO, NULL, "wifi_sdio_flag");
 | 
						|
	
 | 
						|
	extern void sdioPrtcl_setDetectCardExistHdl(UINT32 id, void *pHdl);
 | 
						|
	sdioPrtcl_setDetectCardExistHdl(SDIO_HOST_ID_2, sdio_cardDetectCB);
 | 
						|
	extern void sdioPrtcl_setDetectCardProtectHdl(UINT32 id, void *pHdl);
 | 
						|
	sdioPrtcl_setDetectCardProtectHdl(SDIO_HOST_ID_2, sdio_writeProtCB);
 | 
						|
	//sdioHost_creatInt(SDIO_HOST);
 | 
						|
 | 
						|
    extern void sdioPrtcl_setMemPool(unsigned int id, unsigned int uiAddr, unsigned int uiSize);
 | 
						|
	sdioPrtcl_setMemPool(SDIO_HOST_ID_2, (unsigned int)uimempool, uimempoolsize);
 | 
						|
	sdio2_setIOEnable(1);
 | 
						|
	
 | 
						|
	extern ER sdioPrtcl_setConfig(UINT32 id, SDIO_CONFIG_ID configID, UINT32 configContext);
 | 
						|
	if(sdioPrtcl_setConfig(SDIO_HOST_ID_2, SDIO_CONFIG_ID_DS_MAX_CLK, 48000000)){
 | 
						|
		printf("fail to set sdio2 to 48Mhz\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	
 | 
						|
	extern int sdio2strg_open(int id);
 | 
						|
	if(sdio2strg_open(0)){
 | 
						|
		printf("sdio2strg_open(0) fail\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	extern ER sdioHost_setPadDriving(UINT32 id, UINT32 driving);
 | 
						|
	if(sdioHost_setPadDriving(SDIO_HOST_ID_2, 150)){
 | 
						|
		printf("fail to set sdio driving padding\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
    memset(&func_sdio, 0, sizeof(struct sdio_func));
 | 
						|
    memset(&sdiocard, 0, sizeof(struct mmc_card));
 | 
						|
    memset(&sdiohost, 0, sizeof(struct mmc_host));
 | 
						|
	
 | 
						|
	//get ocr value
 | 
						|
	funcs = 1;
 | 
						|
	
 | 
						|
	//function number
 | 
						|
    printf("funcs = 0x%x\r\n", funcs);
 | 
						|
 | 
						|
    //save sdio functions
 | 
						|
    //??sdiocard.sdio_funcs = funcs;
 | 
						|
    func_sdio.card = (struct mmc_card *)&sdiocard;
 | 
						|
 | 
						|
    //read cccr
 | 
						|
    if(sdio_read_cccr((struct mmc_card *)&sdiocard)){
 | 
						|
		printf("sdio_read_cccr() fail\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
    //read cis
 | 
						|
    if(sdio_read_common_cis((struct mmc_card *)&sdiocard)){
 | 
						|
		printf("sdio_read_common_cis() fail\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
    //set to 4 bit
 | 
						|
    //sdio_enable_wide((struct mmc_card *)&sdiocard);
 | 
						|
 | 
						|
        /*
 | 
						|
         * Initialize (but don't add) all present functions.
 | 
						|
         */
 | 
						|
        for (i = 0;i < funcs;i++) {
 | 
						|
                if(sdio_init_func((struct mmc_card *)&sdiocard, i + 1)){
 | 
						|
					printf("sdio_init_func(%d) fail\n", i+1);
 | 
						|
					return -1;
 | 
						|
				}
 | 
						|
                //??if (err)
 | 
						|
                //??    goto remove;
 | 
						|
        }
 | 
						|
 | 
						|
    //func_sdio.max_blksize = param.SEL.SET_BLOCK_SIZE.uiblocksize;
 | 
						|
    //func_sdio.cur_blksize = param.SEL.SET_BLOCK_SIZE.uiblocksize;
 | 
						|
    //func_sdio.num =funcs; //??temp solution
 | 
						|
    sdiocard.host = (struct mmc_host *)&sdiohost;
 | 
						|
    //func_sdio.card->host->max_blk_size = param.SEL.SET_BLOCK_SIZE.uiblocksize;
 | 
						|
    //func_sdio.card->host->max_blk_count = 511u; //?? todo
 | 
						|
 | 
						|
	for (i = 0; i < funcs; i++)
 | 
						|
		sdiocard.sdio_func[i]->card->host->max_blk_size = 512u;
 | 
						|
	
 | 
						|
	//func_sdio.num = 0;//funcs;//func.num;
 | 
						|
	func_sdio.num = sdiocard.sdio_func[funcs-1]->num;//funcs;//func.num;
 | 
						|
	func_sdio.irq_handler = NULL;
 | 
						|
	//func_sdio.max_blksize = 512u;
 | 
						|
	func_sdio.max_blksize = sdiocard.sdio_func[funcs-1]->max_blksize;
 | 
						|
	//func_sdio.cur_blksize = sdioHost_getBlksize(SDIO_HOST_ID_2);
 | 
						|
	func_sdio.enable_timeout = sdiocard.sdio_func[funcs-1]->enable_timeout;
 | 
						|
	func_sdio.vendor = sdiocard.sdio_func[funcs-1]->vendor;
 | 
						|
	func_sdio.device = sdiocard.sdio_func[funcs-1]->device;
 | 
						|
	func_sdio.num_info = sdiocard.sdio_func[funcs-1]->num_info;
 | 
						|
	func_sdio.class = sdiocard.sdio_func[funcs-1]->class;
 | 
						|
	wifi_sdio_func = &func_sdio;
 | 
						|
 | 
						|
	sdio_set_block_size(sdiocard.sdio_func[funcs-1], 0);
 | 
						|
	func_sdio.cur_blksize = sdiocard.sdio_func[funcs-1]->cur_blksize;
 | 
						|
 | 
						|
	//xTaskCreate(sdio_irq_task, "sdio_irq_thread", 8192, NULL, 6, &sdio_irq_task_handler );
 | 
						|
	//xTaskCreate(sdio_irq_task, "sdio_irq_thread", 8192, NULL, 27, &sdio_irq_task_handler );
 | 
						|
if(0)	
 | 
						|
	xTaskCreate(sdio_irq_task, "sdio_irq_thread", 8192, NULL, 30, &sdio_irq_task_handler );
 | 
						|
else{
 | 
						|
		THREAD_HANDLE    wifi_sdio_irq_task = 0;
 | 
						|
		wifi_sdio_irq_task = vos_task_create(sdio_irq_task, 0, "sdio_irq_thread", 1, 8192*4);
 | 
						|
		if (wifi_sdio_irq_task == 0) {
 | 
						|
				printf("create sdio_irq_thread fail\n");
 | 
						|
		} else {
 | 
						|
			vos_task_resume(wifi_sdio_irq_task);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int sdio_bus_probe(void)
 | 
						|
{
 | 
						|
	printf("sdio_bus_probe()\n");
 | 
						|
	
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int sdio_bus_remove(void)
 | 
						|
{
 | 
						|
	printf("%s \n",__func__);
 | 
						|
	
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
struct sdio_func  *sdio_get_func(void)
 | 
						|
{
 | 
						|
    return &func_sdio;
 | 
						|
}
 | 
						|
 | 
						|
#define SDIO_CCCR_IOEx      0x02
 | 
						|
#define SDIO_CCCR_IORx      0x03
 | 
						|
 | 
						|
int sdio_enable_func(struct sdio_func *func)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    unsigned char reg;
 | 
						|
    //unsigned long timeout;
 | 
						|
 | 
						|
    //BUG_ON(!func);
 | 
						|
    //BUG_ON(!func->card);
 | 
						|
 | 
						|
    //sdiolinux_printf("SDIO: Enabling device %s...\n", sdio_func_id(func));
 | 
						|
 | 
						|
    ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, ®);
 | 
						|
    if (ret){
 | 
						|
		printf("sdio_enable_func:set SDIO_CCCR_IOEx fail\n");
 | 
						|
        goto err;
 | 
						|
	}
 | 
						|
 | 
						|
    reg |= 1 << func->num;
 | 
						|
 | 
						|
    ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
 | 
						|
    if (ret){
 | 
						|
		printf("sdio_enable_func:set SDIO_CCCR_IOEx fail\n");
 | 
						|
        goto err;
 | 
						|
	}
 | 
						|
 | 
						|
    //?? todo
 | 
						|
    //??timeout = jiffies + msecs_to_jiffies(func->enable_timeout);
 | 
						|
 | 
						|
    while (1) {
 | 
						|
        ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IORx, 0, ®);
 | 
						|
        if (ret)
 | 
						|
            goto err;
 | 
						|
        if (reg & (1 << func->num))
 | 
						|
            break;
 | 
						|
        //??ret = -ETIME;
 | 
						|
        //??if (time_after(jiffies, timeout))
 | 
						|
        //??    goto err;
 | 
						|
    }
 | 
						|
 | 
						|
    //?? todo end
 | 
						|
 | 
						|
    //sdiolinux_printf("SDIO: Enabled device %s\n", sdio_func_id(func));
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
err:
 | 
						|
    printf("SDIO: Failed to enable device %p\n", func);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
int sdio_disable_func(struct sdio_func *func)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    unsigned char reg;
 | 
						|
 | 
						|
    //BUG_ON(!func);
 | 
						|
    //BUG_ON(!func->card);
 | 
						|
 | 
						|
    //sdiolinux_printf("SDIO: Disabling device %s...\n", sdio_func_id(func));
 | 
						|
 | 
						|
    ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, ®);
 | 
						|
    if (ret){
 | 
						|
		printf("sdio_disable_func:set SDIO_CCCR_IOEx fail\n");
 | 
						|
        goto err;
 | 
						|
	}
 | 
						|
 | 
						|
    reg &= ~(1 << func->num);
 | 
						|
 | 
						|
    ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
 | 
						|
    if (ret){
 | 
						|
		printf("sdio_disable_func:set SDIO_CCCR_IOEx fail\n");
 | 
						|
        goto err;
 | 
						|
	}
 | 
						|
 | 
						|
    //sdiolinux_printf("SDIO: Disabled device %s\n", sdio_func_id(func));
 | 
						|
 | 
						|
    return 0;
 | 
						|
 | 
						|
err:
 | 
						|
    printf("SDIO: Failed to disable device %p\n", func);
 | 
						|
    return -1;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static BOOL sdio_default_callback(BOOL b)
 | 
						|
{
 | 
						|
	iset_flg(FLG_ID_WIFI_SDIO, FLGPTN_WIFI_SDIO);
 | 
						|
	
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void sdio_host_ioint_enable(unsigned int enable)
 | 
						|
{
 | 
						|
	extern UINT32 sdioHost_setIoIntEn(unsigned int id, int bEn);
 | 
						|
	sdioHost_setIoIntEn(SDIO_HOST_ID_2, enable);
 | 
						|
}
 | 
						|
 | 
						|
int sdio_claim_irq(struct sdio_func *func, void(*handler)(struct sdio_func *))
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    unsigned char reg;
 | 
						|
 | 
						|
    func->irq_handler = NULL;
 | 
						|
 | 
						|
	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, ®);
 | 
						|
	if (ret){
 | 
						|
		printf("sdio_claim_irq:set SDIO_CCCR_IENx fail\n");
 | 
						|
		return ret;
 | 
						|
	}
 | 
						|
 | 
						|
	reg |= 1 << func->num;
 | 
						|
 | 
						|
	reg |= 1; /* Master interrupt enable */
 | 
						|
 | 
						|
	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
 | 
						|
	if (ret){
 | 
						|
		printf("sdio_claim_irq:set SDIO_CCCR_IENx fail\n");
 | 
						|
		return ret;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	//sdio_reg_iocallback((sdio_iocallback_hdl)handler);
 | 
						|
	save_sdio_func = func;
 | 
						|
    vpSdioLinuxIoHdl = handler;
 | 
						|
	//sdio_reg_iocallback((sdio_iocallback_hdl)sdio_default_callback);
 | 
						|
#define SDIO_CALLBACK_IO_INT 4
 | 
						|
	sdio2_setCallBack(SDIO_CALLBACK_IO_INT, sdio_default_callback);
 | 
						|
	extern UINT32 sdioHost_setIoIntEn(unsigned int id, int bEn);
 | 
						|
	sdioHost_setIoIntEn(SDIO_HOST_ID_2, 1);
 | 
						|
 | 
						|
    func->irq_handler = handler;
 | 
						|
 | 
						|
	return 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int sdio_release_irq(struct sdio_func *func)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
	unsigned char reg;
 | 
						|
 | 
						|
    if (func->irq_handler)
 | 
						|
    {
 | 
						|
        func->irq_handler = NULL;
 | 
						|
 | 
						|
    }
 | 
						|
    //sdio_reg_iocallback((sdio_iocallback_hdl)func->irq_handler);
 | 
						|
#define SDIO_CALLBACK_IO_INT 4
 | 
						|
	sdio2_setCallBack(SDIO_CALLBACK_IO_INT, NULL);
 | 
						|
	sdio2_setIOEnable(SDIO_HOST_IOINT_DIS);
 | 
						|
 | 
						|
	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, ®);
 | 
						|
	if (ret){
 | 
						|
		printf("sdio_release_irq:set SDIO_CCCR_IENx fail\n");
 | 
						|
		return ret;
 | 
						|
	}
 | 
						|
 | 
						|
	reg &= ~(1 << func->num);
 | 
						|
 | 
						|
	/* Disable master interrupt with the last function interrupt */
 | 
						|
	if (!(reg & 0xFE))
 | 
						|
		reg = 0;
 | 
						|
 | 
						|
	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
 | 
						|
	if (ret){
 | 
						|
		printf("sdio_release_irq:set SDIO_CCCR_IENx fail\n");
 | 
						|
		return ret;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int sdio_memcpy_fromio(struct sdio_func *func, void *dst,unsigned int addr, int count)
 | 
						|
{
 | 
						|
    return mmc_io_rw_ext_helper(func, 0, addr, 1, dst, count);
 | 
						|
}
 | 
						|
 | 
						|
int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,void *src, int count)
 | 
						|
{
 | 
						|
    return mmc_io_rw_ext_helper(func, 1, addr, 1, src, count);
 | 
						|
}
 | 
						|
 | 
						|
u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    u8 val;
 | 
						|
    //u8 in;
 | 
						|
 | 
						|
    //BUG_ON(!func);
 | 
						|
 | 
						|
    if (err_ret)
 | 
						|
        *err_ret = 0;
 | 
						|
 | 
						|
    //in = 0;
 | 
						|
 | 
						|
    ret = mmc_io_rw_direct(func->card, 0, func->num, addr, 0, &val);
 | 
						|
    if (ret) {
 | 
						|
        if (err_ret)
 | 
						|
            *err_ret = ret;
 | 
						|
        return 0xFF;
 | 
						|
    }
 | 
						|
 | 
						|
    return val;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
    if (err_ret)
 | 
						|
        *err_ret = 0;
 | 
						|
 | 
						|
    ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 2);
 | 
						|
    if (ret) {
 | 
						|
        if (err_ret)
 | 
						|
            *err_ret = ret;
 | 
						|
        return 0xFFFF;
 | 
						|
    }
 | 
						|
 | 
						|
    return *(u16 *)func->tmpbuf;
 | 
						|
}
 | 
						|
 | 
						|
static u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
    if (err_ret)
 | 
						|
        *err_ret = 0;
 | 
						|
 | 
						|
    ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 4);
 | 
						|
    if (ret) {
 | 
						|
        if (err_ret)
 | 
						|
            *err_ret = ret;
 | 
						|
        return 0xFFFFFFFF;
 | 
						|
    }
 | 
						|
 | 
						|
    return *(u32 *)(func->tmpbuf);
 | 
						|
}
 | 
						|
 | 
						|
void sdio_writeb(struct sdio_func *func, u8 b,unsigned int addr, int *err_ret)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
    //BUG_ON(!func);
 | 
						|
 | 
						|
    ret = mmc_io_rw_direct(func->card, 1, func->num, addr, b, NULL);
 | 
						|
    if (err_ret)
 | 
						|
        *err_ret = ret;
 | 
						|
}
 | 
						|
 | 
						|
static void sdio_writew(struct sdio_func *func, u16 b,unsigned int addr, int *err_ret)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
	*(u16 *)func->tmpbuf = b;
 | 
						|
 | 
						|
	ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2);
 | 
						|
	if (err_ret)
 | 
						|
		*err_ret = ret;
 | 
						|
}
 | 
						|
 | 
						|
static void sdio_writel(struct sdio_func *func, u32 b,unsigned int addr, int *err_ret)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
 | 
						|
    *(u32 *)func->tmpbuf = b;
 | 
						|
 | 
						|
    ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4);
 | 
						|
    if (err_ret)
 | 
						|
        *err_ret = ret;
 | 
						|
}
 | 
						|
 | 
						|
/* test wifi driver */
 | 
						|
#define ADDR_MASK 0x10000
 | 
						|
#define LOCAL_ADDR_MASK 0x00000
 | 
						|
 | 
						|
int wifi_read(struct sdio_func *func, u32 addr, u32 cnt, void *pdata)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
 | 
						|
	err = sdio_memcpy_fromio(func, pdata, addr, cnt);
 | 
						|
	if (err) {
 | 
						|
		printf("%s: FAIL(%d)! ADDR=%#x Size=%d\n", __func__, err, addr, cnt);
 | 
						|
	}
 | 
						|
 | 
						|
	sdio_release_host(func);
 | 
						|
 | 
						|
	return err;
 | 
						|
}
 | 
						|
 | 
						|
int wifi_write(struct sdio_func *func, u32 addr, u32 cnt, void *pdata)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
	u32 size;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
 | 
						|
	size = cnt;
 | 
						|
	err = sdio_memcpy_toio(func, addr, pdata, size);
 | 
						|
	if (err) {
 | 
						|
		printf("%s: FAIL(%d)! ADDR=%#x Size=%d(%d)\n", __func__, err, addr, cnt, size);
 | 
						|
	}
 | 
						|
 | 
						|
	sdio_release_host(func);
 | 
						|
 | 
						|
	return err;
 | 
						|
}
 | 
						|
 | 
						|
u8 wifi_readb(struct sdio_func *func, u32 addr)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
	u8 ret = 0;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
	ret = sdio_readb(func, ADDR_MASK | addr, &err);
 | 
						|
	sdio_release_host(func);
 | 
						|
 | 
						|
	if (err)
 | 
						|
		printf("%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
u16 wifi_readw(struct sdio_func *func, u32 addr)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
	u16 v;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
	v = sdio_readw(func, ADDR_MASK | addr, &err);
 | 
						|
	sdio_release_host(func);
 | 
						|
	if (err)
 | 
						|
		printf("%s: FAIL!(%d) addr=0x%05x\n", __func__, err, addr);
 | 
						|
 | 
						|
	return  v;
 | 
						|
}
 | 
						|
 | 
						|
u32 wifi_readl(struct sdio_func *func, u32 addr)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
	u32 v;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
	v = sdio_readl(func, ADDR_MASK | addr, &err);
 | 
						|
	sdio_release_host(func);
 | 
						|
 | 
						|
	return  v;
 | 
						|
}
 | 
						|
 | 
						|
void wifi_writeb(struct sdio_func *func, u32 addr, u8 val)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
	sdio_writeb(func, val, ADDR_MASK | addr, &err);
 | 
						|
	sdio_release_host(func);
 | 
						|
	if (err)
 | 
						|
		printf("%s: FAIL!(%d) addr=0x%05x val=0x%02x\n", __func__, err, addr, val);
 | 
						|
}
 | 
						|
 | 
						|
void wifi_writew(struct sdio_func *func, u32 addr, u16 v)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
	sdio_writew(func, v, ADDR_MASK | addr, &err);
 | 
						|
	sdio_release_host(func);
 | 
						|
	if (err)
 | 
						|
		printf("%s: FAIL!(%d) addr=0x%05x val=0x%04x\n", __func__, err, addr, v);
 | 
						|
}
 | 
						|
 | 
						|
void wifi_writel(struct sdio_func *func, u32 addr, u32 v)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
 | 
						|
	sdio_claim_host(func);
 | 
						|
	sdio_writel(func, v, ADDR_MASK | addr, &err);
 | 
						|
	sdio_release_host(func);
 | 
						|
}
 | 
						|
 | 
						|
u8 wifi_readb_local(struct sdio_func *func, u32 addr)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
	u8 ret = 0;
 | 
						|
 | 
						|
	ret = sdio_readb(func, LOCAL_ADDR_MASK | addr, &err);
 | 
						|
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
void wifi_writeb_local(struct sdio_func *func, u32 addr, u8 val)
 | 
						|
{
 | 
						|
	int err;
 | 
						|
 | 
						|
	sdio_writeb(func, val, LOCAL_ADDR_MASK | addr, &err);
 | 
						|
}
 | 
						|
 | 
						|
/*below functions are exported
 | 
						|
	sdio_bus_probe,
 | 
						|
	sdio_bus_remove,
 | 
						|
	sdio_enable_func,
 | 
						|
	sdio_disable_func,
 | 
						|
	sdio_reg_driver,
 | 
						|
	sdio_unreg_driver,
 | 
						|
	sdio_claim_irq,
 | 
						|
	sdio_release_irq,
 | 
						|
	sdio_claim_host,
 | 
						|
	sdio_release_host,
 | 
						|
	sdio_readb,
 | 
						|
	sdio_readw,
 | 
						|
	sdio_readl,
 | 
						|
	sdio_writeb,
 | 
						|
	sdio_writew,
 | 
						|
	sdio_writel,
 | 
						|
	sdio_memcpy_fromio,
 | 
						|
	sdio_memcpy_toio
 | 
						|
*/
 |