Home | History | Annotate | Download | only in src
      1 /* mmc_tnetw1150_api.c
      2  *
      3  * This program is free software; you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License version 2 as
      5  * published by the Free Software Foundation.
      6  *
      7  * Copyright  Texas Instruments Incorporated (Oct 2005)
      8  * THIS CODE/PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
      9  * EITHER EXPRESS OR IMPLIED, INCLUDED BUT NOT LIMITED TO , THE IMPLIED
     10  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     11  * This program has been modified from its original operation by Texas
     12  * Instruments Incorporated. These changes are covered under version 2
     13  * of the GNU General Public License, dated June 1991.
     14  *
     15  * Copyright  Google Inc (Feb 2008)
     16  */
     17 /*-------------------------------------------------------------------*/
     18 #ifdef TIWLAN_MSM7000
     19 
     20 #include <linux/module.h>
     21 #include <linux/kernel.h>
     22 #include <linux/version.h>
     23 #include "mmc_tnetw1150_api.h"
     24 #include <linux/mmc/core.h>
     25 
     26 #include <linux/mmc/card.h>
     27 #include <linux/mmc/sdio_func.h>
     28 
     29 #define SDIO_INVALID_PERIPHERAL_ADDRESS             0x1FFFF
     30 
     31 /* CCCR                                                 0x000000 - 0x0000ff          */
     32 /* Function Basic Register (Function 1)                 0x000100 - 0x0001ff          */
     33 	/* 0x101          - Function 1 Extended standard I/O device type code        */
     34 	/* 0x102          - RFU[4-0] EnableHighPower Supports High-Power[1-0] SHP[0] */
     35 	/* 0x103 - 0x108  - RFU                                                      */
     36 	/* 0x109 - 0x10b  - Pointer to Function 1 Card Information Structure         */
     37 	/* 0x10c - 0x10e  - Pointer to Function 1 Code Storage Area                  */
     38 	/* 0x10f          - Data access window to Function 1 Code Storage Area       */
     39 	/* 0x110 - 0x111  - I/O block size for Function 1                            */
     40 	/* 0x112 - 0x1ff  - RFU                                                      */
     41 /* Function Basic Register (Function 2)                 0x000200 - 0x0002ff          */
     42 /* Function Basic Register (Function 3)                 0x000300 - 0x0003ff          */
     43 /* Function Basic Register (Function 4)                 0x000400 - 0x0004ff          */
     44 /* Function Basic Register (Function 5)                 0x000500 - 0x0005ff          */
     45 /* Function Basic Register (Function 6)                 0x000600 - 0x0006ff          */
     46 /* Function Basic Register (Function 7)                 0x000700 - 0x0007ff          */
     47 /* RFU                                			0x000800 - 0x000fff          */
     48 /* CIS common and per-function area                     0x001000 - 0x017fff          */
     49 /* RFU                                                  0x018000 - 0x01ffff          */
     50 #define SDIO_FUNC1_OFFSET    0x1FFC0
     51 
     52 typedef struct
     53 {
     54 	Peripheral_Address mem_start_addr;
     55 	Peripheral_Address mem_part_size;
     56 	Peripheral_Address mem_end_addr;
     57 	Peripheral_Address reg_start_addr;
     58 	Peripheral_Address reg_part_size;
     59 	Peripheral_Address reg_end_addr;
     60 } SDIO_TNETW_partitions;
     61 static SDIO_TNETW_partitions TNETW_table;
     62 
     63 static SDIO_TNETWConfigParams TNETW_params;
     64 
     65 #ifdef CONFIG_MMC_TNET_INFO
     66 typedef struct {
     67 	u8  scr_space[SDIO_FUNC1_OFFSET];	/* 0x000000 - 0x01ffbf;
     68 				   		   131072B(128kB)-64B=131008B(0x01ffc0) */
     69 	u32 amap_size1;         		/* 0x01ffc0 */
     70 	u32 amap_offset1;       		/* 0x01ffc4 */
     71 	u32 amap_size2;         		/* 0x01ffc8 */
     72 	u32 amap_offset2;       		/* 0x01ffcc */
     73 	u32 amap_size3;         		/* 0x01ffd0 */
     74 	u32 amap_offset3;       		/* 0x01ffd4 */
     75 	u32 amap_offset4;       		/* 0x01ffd8 */
     76 	u32 cis_offset;         		/* 0x01ffdc - Card Information Structure */
     77 	u32 csa_offset;         		/* 0x01ffe0 - Code Storage Area */
     78 	u8  filler[16];         		/* 0x01ffe4 - 0x01fff3 */
     79 	u32 wr_err_len;         		/* 0x01fff4 */
     80 	u32 wr_err_addr;        		/* 0x01fff8 */
     81 	u32 status;             		/* 0x01fffc */
     82 } SDIO_FUNC1AddressMap;
     83 SDIO_FUNC1AddressMap mapping;
     84 
     85 int sdio_tnetw1150_dump(int count)
     86 {
     87 	unsigned long from;
     88 	unsigned long br_offset;
     89 	unsigned long offset=0;
     90 	unsigned long p1_offset=0;
     91 	unsigned long p2_offset=0;
     92 	struct mmc_request request;
     93 	int lines;
     94 	int i=0;
     95 	int second_part=0;
     96 
     97 	printk("%s:\n", __FUNCTION__);
     98 #define TNETW1150_OFFSET 1024
     99 	from=TNETW1150_OFFSET*count;
    100 	if((from+TNETW1150_OFFSET)>(SDIO_FUNC1_OFFSET+64))
    101 		return -1;
    102 	br_offset=TNETW1150_OFFSET*count;
    103 	if(br_offset>=TNETW_params.map_reg[0].reg_size) {
    104 		second_part=1;
    105 		p2_offset = SDIO_DRIVER_REG_PARTITION_START;
    106 		offset = TNETW_params.map_reg[1].scr_offset - TNETW_params.map_reg[0].reg_size;
    107 	}
    108 	else {
    109 		p1_offset += SDIO_DOWNLOAD_PARTITION_START;
    110 		offset = TNETW_params.map_reg[0].scr_offset;
    111 	}
    112 
    113 	request.cmd=SD_IO_RW_DIRECT;
    114  	request.buffer_len=1;
    115 	request.nob=0;
    116 	request.block_len=0;
    117 	request.buffer=&mapping.scr_space[from];
    118     printk(" TNETW1150 try br_offset:0x%08lx offset:0x%08lx):\n", br_offset, offset);
    119 	do {
    120 		request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,br_offset);
    121 		if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
    122 			return SDIO_FAILURE;
    123 		udelay(1);
    124 		*request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
    125 		i++;
    126 		request.buffer++;
    127 		br_offset++;
    128 	} while(i<TNETW1150_OFFSET);
    129 
    130     printk(" TNETW1150 SCR Address Space (start:0x%08lx  end:0x%08lx part:%d offset:0x%08lx):\n", from, from+TNETW1150_OFFSET-1, second_part+1, (!second_part)?p1_offset:p2_offset);
    131 
    132 	lines=TNETW1150_OFFSET/16;
    133 	for(i=0; i<lines;i++, from+=16)
    134         printk("SDIO:0x%04lx(SCR:0x%04lx): %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", from, (!second_part)?(from+p1_offset):(from-p2_offset+SDIO_REG_PARTITION_START), mapping.scr_space[from], mapping.scr_space[from+1], mapping.scr_space[from+2], mapping.scr_space[from+3], mapping.scr_space[from+4], mapping.scr_space[from+5], mapping.scr_space[from+6], mapping.scr_space[from+7], mapping.scr_space[from+8], mapping.scr_space[from+9], mapping.scr_space[from+10], mapping.scr_space[from+11], mapping.scr_space[from+12], mapping.scr_space[from+13], mapping.scr_space[from+14], mapping.scr_space[from+15]);
    135 
    136     return 0;
    137 }
    138 EXPORT_SYMBOL(sdio_tnetw1150_dump);
    139 
    140 int sdio_tnetw1150_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
    141 {
    142     int len=0;
    143 	int br_offset = SDIO_FUNC1_OFFSET;
    144 	struct mmc_request request;
    145 	u8 buf[64];
    146 	u8 buf3[3];
    147 	int bytes_to_read=64;
    148 	int i;
    149 #define CCCR_SIZE 17
    150 	u8 buf_ccr[CCCR_SIZE];
    151 	u8 buf_ccr_offset[CCCR_SIZE] = {
    152 		CCCR_SDIO_REVISION, CCCR_SD_SPECIFICATION_REVISION, CCCR_IO_ENABLE,
    153 		CCCR_IO_READY, CCCR_INT_ENABLE, CCCR_INT_PENDING,
    154 		CCCR_IO_ABORT, CCCR_BUS_INTERFACE_CONTOROL, CCCR_CARD_CAPABILITY,
    155 		CCCR_COMMON_CIS_POINTER, CCCR_COMMON_CIS_POINTER+1, CCCR_COMMON_CIS_POINTER+2,
    156 		CCCR_BUS_SUSPEND, CCCR_FUNCTION_SELECT, CCCR_EXEC_FLAGS,
    157 		CCCR_READY_FLAGS, CCCR_FNO_BLOCK_SIZE,
    158 	};
    159 #define FBR_SIZE 9
    160 	u8 buf_fbr[FBR_SIZE];
    161 	u16 buf_fbr_offset[FBR_SIZE] = {
    162 		FBR_PTR_F1_CIS, FBR_PTR_F1_CIS+1, FBR_PTR_F1_CIS+2,
    163 		FBR_PTR_F1_CSA, FBR_PTR_F1_CSA+1, FBR_PTR_F1_CSA+2,
    164 		FBR_WIN_F1_CSA, FBR_F1_IO_BLK_SIZE, FBR_F1_IO_BLK_SIZE+1,
    165 	};
    166 
    167 	request.cmd=SD_IO_RW_DIRECT;
    168  	request.buffer_len=1;
    169 	request.nob=0;
    170 	request.block_len=0;
    171 	request.buffer=&buf[0];
    172 	for (i=0; i<bytes_to_read;i++,request.buffer++,br_offset++) {
    173 		request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,br_offset);
    174 		if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
    175 			return SDIO_FAILURE;
    176 		*request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
    177 	}
    178 	memcpy(&mapping.amap_size1, &buf, 64);
    179 
    180     count -= 80; /* some reserve */
    181     len += (len<count)?sprintf(page+len, " TNETW1150 partitions:\n"):0;
    182     len += (len<count)?sprintf(page+len, " Memory:      "):0;
    183 	len += (len<count)?sprintf(page+len, " start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size):0;
    184     len += (len<count)?sprintf(page+len, " Registers:   "):0;
    185 	len += (len<count)?sprintf(page+len, " start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size):0;
    186 
    187     len += (len<count)?sprintf(page+len, " SDIO Function 1 Address Map:\n"):0;
    188 	len += (len<count)?sprintf(page+len, " amap_size1:0x%08x  amap_offset1:0x%08x\n", mapping.amap_size1, mapping.amap_offset1):0;
    189 	len += (len<count)?sprintf(page+len, " amap_size2:0x%08x  amap_offset2:0x%08x\n", mapping.amap_size2, mapping.amap_offset2):0;
    190 	len += (len<count)?sprintf(page+len, " amap_size3:0x%08x  amap_offset3:0x%08x\n", mapping.amap_size3, mapping.amap_offset3):0;
    191 	len += (len<count)?sprintf(page+len, "                        amap_offset4:0x%08x\n", mapping.amap_offset4):0;
    192 	len += (len<count)?sprintf(page+len, " cis_offset:0x%08x  csa_offset  :0x%08x\n", mapping.cis_offset, mapping.csa_offset):0;
    193 	len += (len<count)?sprintf(page+len, " wr_err_len:0x%08x  wr_err_addr :0x%08x\n", mapping.wr_err_len, mapping.wr_err_addr):0;
    194 	len += (len<count)?sprintf(page+len, " status    :0x%08x\n", mapping.status):0;
    195 
    196 	request.cmd=SD_IO_RW_DIRECT;
    197  	request.buffer_len=1;
    198 	request.nob=0;
    199 	request.block_len=0;
    200 	request.buffer=&buf_ccr[0];
    201 	for (i=0; i<CCCR_SIZE;i++,request.buffer++) {
    202 		request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_0,0,buf_ccr_offset[i]);
    203 		if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
    204 			return SDIO_FAILURE;
    205 		*request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
    206 	}
    207 
    208     len += (len<count)?sprintf(page+len, "\n Card Common Control Registers:\n"):0;
    209 	len += (len<count)?sprintf(page+len, " \
    210  REVISION             :0x%02x  SD_SPEC_REVISION       :0x%02x   IO_ENABLE            :0x%02x\n \
    211  IO_READY             :0x%02x  INT_ENABLE             :0x%02x   INT_PENDING          :0x%02x\n \
    212  IO_ABORT             :0x%02x  BUS_INTERFACE_CONTOROL :0x%02x   CARD_CAPABILITY      :0x%02x\n \
    213  COMMON_CIS_POINTER[2]:0x%02x  COMMON_CIS_POINTER[1]  :0x%02x   COMMON_CIS_POINTER[0]:0x%02x\n \
    214  BUS_SUSPEND          :0x%02x  FUNCTION_SELECT        :0x%02x   EXEC_FLAGS           :0x%02x\n \
    215  READY_FLAGS          :0x%02x  FNO_BLOCK_SIZE         :0x%02x\n" , buf_ccr[0], buf_ccr[1], buf_ccr[2], buf_ccr[3], buf_ccr[4], buf_ccr[5], buf_ccr[6], buf_ccr[7], buf_ccr[8], buf_ccr[11], buf_ccr[10], buf_ccr[9], buf_ccr[12], buf_ccr[13], buf_ccr[14], buf_ccr[15], buf_ccr[16]):0;
    216 
    217 	request.cmd=SD_IO_RW_DIRECT;
    218  	request.buffer_len=1;
    219 	request.nob=0;
    220 	request.block_len=0;
    221 
    222 	request.buffer=&buf3[0];
    223 	for (i=0; i<3;i++,request.buffer++) {
    224 		request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,FBR_PTR_F1_IO_DEV);
    225 		if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
    226 			return SDIO_FAILURE;
    227 		*request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
    228 	}
    229 
    230 	request.buffer=&buf_fbr[0];
    231 	for (i=0; i<FBR_SIZE;i++,request.buffer++) {
    232 		request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,buf_fbr_offset[i]);
    233 		if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS)
    234 			return SDIO_FAILURE;
    235 		*request.buffer = (char)omap_readw(OMAP_MMC_RSP6);
    236 	}
    237 
    238     len += (len<count)?sprintf(page+len, "\n Function Basic Registers(Func 1):\n"):0;
    239 	len += (len<count)?sprintf(page+len, " \
    240  Func 1 CSA enable and CSA support              :     0x%02x 0x%02x\n \
    241  Func 1 Ext stand. I/O device i/f and type code :     0x%02x 0x%02x\n \
    242  EHP|SHP[1]|SHP[0]                              :          0x%02x\n \
    243  Pointer to Func 1 Card Information Structure   :0x%02x 0x%02x 0x%02x\n \
    244  Pointer to Func 1 Code Storage Area            :0x%02x 0x%02x 0x%02x\n \
    245  Data access window to Func 1 Code Storage Area :          0x%02x\n \
    246  I/O block size for Func 1                      :     0x%02x 0x%02x\n", ((buf3[0]&0x80)>>7), ((buf3[0]&0x40)>>6), (buf3[1]&0x0f), buf3[1], (buf3[2]&0x07), buf_fbr[2], buf_fbr[1], buf_fbr[0], buf_fbr[5], buf_fbr[4], buf_fbr[3], buf_fbr[6], buf_fbr[8], buf_fbr[7]):0;
    247 
    248     *eof = 1;
    249     return len;
    250 }
    251 #endif /*CONFIG_MMC_TNET_STATISTICS*/
    252 
    253 
    254 /*
    255   Initialization of TNETW memory configuration.
    256 */
    257 extern int debug_level;
    258 SDIO_Status SDIO_TNETWInit(SDIO_TNETWConfigParams *params)
    259 {
    260     /*	debug_level=3;    */
    261 	/* printk("%s\n", __FUNCTION__); */
    262 
    263 	memset(&TNETW_params, 0, sizeof(SDIO_TNETWConfigParams));
    264 
    265     if(!params) {
    266 		/* printk("%s set to default\n", __FUNCTION__); */
    267 		/* set to default value in case params is not presented */
    268 		TNETW_params.num_of_parts = 2;
    269 		/* First time initialization */
    270 		TNETW_params.map_reg[0].reg_size = SDIO_DOWNLOAD_PARTITION_SIZE;
    271 		TNETW_params.map_reg[0].scr_offset = SDIO_DOWNLOAD_PARTITION_START;
    272 		/* After firmware has been downloaded, data memory region
    273 		   has to be re-initialized as following:
    274 		TNETW_params.map_reg[0].reg_size = SDIO_MEM_PARTITION_START;
    275 		TNETW_params.map_reg[0].scr_offset = SDIO_MEM_PARTITION_SIZE;
    276 		*/
    277 		TNETW_params.map_reg[1].reg_size = SDIO_REG_PARTITION_SIZE;
    278 		TNETW_params.map_reg[1].scr_offset = SDIO_REG_PARTITION_START;
    279 	}
    280 	else {
    281 		/* printk("%s: params->num_of_parts=%d\n", __FUNCTION__, params->num_of_parts); */
    282 		/* validate input parameters */
    283 		switch(params->num_of_parts) {
    284 		case 1:
    285 			if(params->map_reg[0].reg_size > AMAP_ONE_REGION)
    286 				return SDIO_FAILURE;
    287 			break;
    288 		case 2:
    289 			if((params->map_reg[0].reg_size + params->map_reg[1].reg_size) > AMAP_ONE_REGION)
    290 				return SDIO_FAILURE;
    291 			break;
    292 		case 3:
    293 			if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size) > AMAP_ONE_REGION)
    294 				return SDIO_FAILURE;
    295 			break;
    296 		case 4:
    297 			if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size + params->map_reg[3].reg_size) > AMAP_ONE_REGION)
    298 				return SDIO_FAILURE;
    299 			break;
    300 		default:
    301 			return SDIO_FAILURE;
    302 		}
    303 		memcpy(&TNETW_params, params, sizeof(SDIO_TNETWConfigParams));
    304 	}
    305 
    306 #ifdef CONFIG_PROC_FS
    307 #ifdef CONFIG_MMC_TNET_INFO
    308 	create_proc_read_entry("sdio_tnetw1150", 0, NULL, sdio_tnetw1150_read_proc, NULL);
    309 #endif
    310 #endif
    311 
    312 	/* printk("%s completed\n", __FUNCTION__); */
    313 
    314 	return SDIO_SUCCESS;
    315 }
    316 
    317 SDIO_Status SDIO_TNETWReset(SDIO_TNETWConfigParams *params)
    318 {
    319 	/* printk("%s\n", __FUNCTION__); */
    320 
    321 	memset(&TNETW_params, 0, sizeof(SDIO_TNETWConfigParams));
    322 
    323 	if(!params) {
    324 		/* printk("%s set to default\n", __FUNCTION__); */
    325 		/* set to default value in case params is not presented */
    326 		TNETW_params.num_of_parts = 2;
    327 
    328 		/* After firmware has been downloaded, data memory region
    329 		   has to be re-initialized as following */
    330 		TNETW_params.map_reg[0].reg_size = SDIO_MEM_PARTITION_START;
    331 		TNETW_params.map_reg[0].scr_offset = SDIO_MEM_PARTITION_SIZE;
    332 		TNETW_params.map_reg[1].reg_size = SDIO_REG_PARTITION_SIZE;
    333 		TNETW_params.map_reg[1].scr_offset = SDIO_REG_PARTITION_START;
    334 	}
    335 	else {
    336 		/* printk("%s: params->num_of_parts=%d\n", __FUNCTION__, params->num_of_parts); */
    337 		/* validate input parameters */
    338 		switch(params->num_of_parts) {
    339 		case 1:
    340 			if(params->map_reg[0].reg_size > AMAP_ONE_REGION)
    341 				return SDIO_FAILURE;
    342 			break;
    343 		case 2:
    344 			if((params->map_reg[0].reg_size + params->map_reg[1].reg_size) > AMAP_ONE_REGION)
    345 				return SDIO_FAILURE;
    346 			break;
    347 		case 3:
    348 			if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size) > AMAP_ONE_REGION)
    349 				return SDIO_FAILURE;
    350 			break;
    351 		case 4:
    352 			if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size + params->map_reg[3].reg_size) > AMAP_ONE_REGION)
    353 				return SDIO_FAILURE;
    354 			break;
    355 		default:
    356 			return SDIO_FAILURE;
    357 		}
    358 		memcpy(&TNETW_params, params, sizeof(SDIO_TNETWConfigParams));
    359 	}
    360 
    361 	/* printk("%s completed\n", __FUNCTION__); */
    362 
    363 	return SDIO_SUCCESS;
    364 }
    365 
    366 
    367 static SDIO_Status config_partition(SDIO_Handle sdioHandle, int partition_no, Peripheral_Address start_addr, SDIO_BufferLength part_size)
    368 {
    369 	struct sdio_func *func = (struct sdio_func *) sdioHandle;
    370 	u8 data;
    371 	int br_offset = SDIO_FUNC1_OFFSET + (partition_no-1)*8;
    372 	int i, rc;
    373 
    374 	/* printk("%s: partition_no=%d\n", __FUNCTION__, partition_no); */
    375 
    376 	/* Set size - write out 4 bytes by 4 requests */
    377 	if (partition_no < AMAP_MAX_REGIONS)
    378 	{
    379 		for(i=0;i<4;i++,br_offset++) {
    380 			data = (part_size>>(8*i))&0xFF;
    381 
    382 			/* put R/W Flag (1 for write); Function Number(1), RAW Flag(0),
    383 	   	   	   Register Address - the address of the byte of data inside
    384 	   	   	   of the selected function that will be written
    385  			   (br_offset for func1),
    386 	   	   	   Write Data - for a direct write command, this is the byte=data,
    387 	   		   that will be written to the selected address=br_offset).
    388 			*/
    389 			sdio_writeb(func, data, br_offset, &rc);
    390 			if (rc < 0) {
    391 				printk(KERN_ERR "%s: Error writing size\n", __FUNCTION__);
    392 				return SDIO_FAILURE;
    393 			}
    394             /* printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset); */
    395 		}
    396 
    397         /* Set offset - write out 4 bytes by 4 requests */
    398         for(i=0;i<4;i++,br_offset++) {
    399             data = (start_addr>>(8*i))&0xFF;
    400             sdio_writeb(func, data, br_offset, &rc);
    401             if (rc < 0) {
    402                 printk(KERN_ERR "%s: Error writing offset\n", __FUNCTION__);
    403                 return SDIO_FAILURE;
    404             }
    405             /* printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset); */
    406         }
    407     }
    408 #if 0
    409     if( partition_no == 2 ) {
    410         unsigned long id1;
    411         for(i=0,br_offset=0x1ce34;i<4;i++,br_offset++) {
    412             data = sdio_readb(func, br_offset, &rc);
    413             if (rc < 0) {
    414                 printk(KERN_ERR "%s: Error reading offset\n", __FUNCTION__);
    415                 return SDIO_FAILURE;
    416             }
    417             printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset);
    418         }
    419         rc = sdio_memcpy_fromio(func, &id1, 0x1ce34, 4); /* Dm: Important - DO NOT REMOVE !!! */
    420         if (rc < 0) {
    421             printk(KERN_ERR "%s: Error reading offset\n", __FUNCTION__);
    422             return SDIO_FAILURE;
    423         }
    424         printk("%s: data=0x%08x at=0x%08x\n", __FUNCTION__, id1, br_offset);
    425     }
    426 #endif
    427     return SDIO_SUCCESS;
    428 }
    429 
    430 /*
    431   This function configures the slave SDIO device for the required
    432   operation mode.
    433 */
    434 SDIO_Status SDIO_TNETWConfig(SDIO_Handle sdioHandle, Peripheral_ConfigParams **peripheral_info)
    435 {
    436 	SDIO_Status rc;
    437 
    438 	/* printk("%s\n", __FUNCTION__); */
    439 
    440 	TNETW_table.mem_start_addr = TNETW_params.map_reg[0].scr_offset;
    441 	TNETW_table.mem_part_size = TNETW_params.map_reg[0].reg_size;
    442 	TNETW_table.mem_end_addr = TNETW_table.mem_start_addr + TNETW_table.mem_part_size - 1;
    443 
    444 	TNETW_table.reg_start_addr = TNETW_params.map_reg[1].scr_offset;
    445 	TNETW_table.reg_part_size = TNETW_params.map_reg[1].reg_size;
    446 	TNETW_table.reg_end_addr = TNETW_table.reg_start_addr + TNETW_table.reg_part_size - 1;
    447 #if 0
    448 	printk("%s: memory area: start_addr=0x%08lx end_addr=0x%08lx part_size=0x%08lx\n", __FUNCTION__, TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size);
    449 	printk("%s: register area: start_addr=0x%08lx end_addr=0x%08lx part_size=0x%08lx\n", __FUNCTION__, TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size);
    450 #endif
    451 	/* Configure 17-bits address range in peripheral */
    452 	rc=config_partition(sdioHandle, 1, TNETW_table.mem_start_addr, TNETW_table.mem_part_size);
    453 	rc = (rc==SDIO_SUCCESS)?config_partition(sdioHandle, 2, TNETW_table.reg_start_addr, TNETW_table.reg_part_size):rc;
    454 
    455 	if(*peripheral_info)
    456 		*peripheral_info = (void *)&TNETW_table;
    457 
    458     /* printk("%s: TNETW1150 partitions:\n", __FUNCTION__);
    459 	printk("Memory   : start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size);
    460 	printk("Registers: start:0x%08lx  end:0x%08lx  size:0x%08lx bytes\n", TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size);
    461     */
    462 
    463 	return rc;
    464 }
    465 
    466 /*
    467   This function performs convertion of peripheral adddress into 17 bits
    468   SDIO address. If found that the memory partition configuration must be
    469   changed, the memory is re-mapped in accordance to requested address.
    470 */
    471 SDIO_Address SDIO_ConvertTNETWToSDIOMaster(Peripheral_Address in_tnetw_address, SDIO_BufferLength packet_size)
    472 {
    473  	SDIO_Address out_sdio_address;
    474 
    475 #ifdef CONFIG_SDIO_ADDRESS_MAPPING_BY_APPLICATION
    476 	out_sdio_address = in_tnetw_address;
    477 #else
    478 	Peripheral_Address tnetw_last_address = in_tnetw_address + packet_size - 1;
    479 
    480 	/* printk("%s:\n", __FUNCTION__); */
    481 
    482 	if ((in_tnetw_address >= TNETW_table.mem_start_addr) && (tnetw_last_address <= TNETW_table.mem_end_addr)) {
    483 		/* printk("%s part1 from=0x%08lx to 0x%08lx\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */
    484 		/* address in the 1-st partition range (data memory space) */
    485 		out_sdio_address = in_tnetw_address - TNETW_table.mem_start_addr;
    486 	}
    487 	else if ((in_tnetw_address >= TNETW_table.reg_start_addr) && (tnetw_last_address <= TNETW_table.reg_end_addr)) {
    488 		/* printk("%s part2 from=0x%08lx to 0x%08lx\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */
    489 		/* address in the 2-nd partition range (register memory space) */
    490 		out_sdio_address = in_tnetw_address - TNETW_table.reg_start_addr + TNETW_table.mem_part_size;
    491 	}
    492 	else {
    493 		/* printk("%s peripheral addresses from=0x%08lx to 0x%08lx is out of range\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */
    494 		/* invalid address */
    495 		return SDIO_INVALID_PERIPHERAL_ADDRESS;
    496 	}
    497 	/* printk("%s: in_tnetw_addr=0x%08lx out_sdio_addr=0x%08lx\n", __FUNCTION__, in_tnetw_address, out_sdio_address); */
    498 
    499 #endif /* CONFIG_SDIO_ADDRESS_MAPPING_BY_APPLICATION */
    500 
    501 	return out_sdio_address;
    502 }
    503 
    504 SDIO_Status SDIO_TNETW_Set_ELP_Reg(SDIO_Handle sdioHandle, Peripheral_Address start_addr, unsigned int data)
    505 {
    506 	struct sdio_func *func = (struct sdio_func *) sdioHandle;
    507 	u8 data1 = 0;
    508 	int br_offset = start_addr;
    509 	int i, rc;
    510 
    511 	/* Set size - write out 4 bytes by 4 requests */
    512 	for(i=0;i<1;i++,br_offset++) {
    513 		data1 = (data>>(8*i))&0xFF;
    514 
    515 		/* put R/W Flag (1 for write); Function Number(1), RAW Flag(0),
    516 	   	   	   Register Address - the address of the byte of data inside
    517 	   	   	   of the selected function that will be written
    518  			   (br_offset for func1),
    519 	   	   	   Write Data - for a direct write command, this is the byte=data,
    520 	   		   that will be written to the selected address=br_offset).
    521 		*/
    522 		sdio_writeb(func, data1, br_offset, &rc);
    523 		if (rc < 0) {
    524 			printk(KERN_ERR "%s: Error writing size\n", __FUNCTION__);
    525 			return SDIO_FAILURE;
    526 		}
    527 	}
    528 	return SDIO_SUCCESS;
    529 }
    530 
    531 SDIO_Status SDIO_TNETW_Get_ELP_Reg(SDIO_Handle sdioHandle, Peripheral_Address start_addr, unsigned int *data)
    532 {
    533 	struct sdio_func *func = (struct sdio_func *) sdioHandle;
    534 	int br_offset = start_addr;
    535 	int rc;
    536 
    537 	*(u8*)data = sdio_readb_ext(func, br_offset, &rc, 0x01);
    538 	if (rc) {
    539 		printk(KERN_ERR "%s: Error reading sdio register (%d)\n", __FUNCTION__, rc);
    540 		return SDIO_FAILURE;
    541 	}
    542 	return SDIO_SUCCESS;
    543 }
    544 
    545 #endif /* TIWLAN_MSM7000 */
    546