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