1/* ////////////////////////////////////////////////////////////////////////// */ 2/* */ 3/* Copyright (c) Atmel Corporation. All rights reserved. */ 4/* */ 5/* Module Name: wilc_sdio.c */ 6/* */ 7/* */ 8/* //////////////////////////////////////////////////////////////////////////// */ 9 10#include <linux/string.h> 11#include "wilc_wlan_if.h" 12#include "wilc_wlan.h" 13 14#define WILC_SDIO_BLOCK_SIZE 512 15 16typedef struct { 17 void *os_context; 18 u32 block_size; 19 int (*sdio_cmd52)(sdio_cmd52_t *); 20 int (*sdio_cmd53)(sdio_cmd53_t *); 21 int (*sdio_set_max_speed)(void); 22 int (*sdio_set_default_speed)(void); 23 wilc_debug_func dPrint; 24 int nint; 25#define MAX_NUN_INT_THRPT_ENH2 (5) /* Max num interrupts allowed in registers 0xf7, 0xf8 */ 26 int has_thrpt_enh3; 27} wilc_sdio_t; 28 29static wilc_sdio_t g_sdio; 30 31#ifdef WILC_SDIO_IRQ_GPIO 32static int sdio_write_reg(u32 addr, u32 data); 33static int sdio_read_reg(u32 addr, u32 *data); 34#endif 35 36/******************************************** 37 * 38 * Function 0 39 * 40 ********************************************/ 41 42static int sdio_set_func0_csa_address(u32 adr) 43{ 44 sdio_cmd52_t cmd; 45 46 /** 47 * Review: BIG ENDIAN 48 **/ 49 cmd.read_write = 1; 50 cmd.function = 0; 51 cmd.raw = 0; 52 cmd.address = 0x10c; 53 cmd.data = (u8)adr; 54 if (!g_sdio.sdio_cmd52(&cmd)) { 55 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10c data...\n"); 56 goto _fail_; 57 } 58 59 cmd.address = 0x10d; 60 cmd.data = (u8)(adr >> 8); 61 if (!g_sdio.sdio_cmd52(&cmd)) { 62 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10d data...\n"); 63 goto _fail_; 64 } 65 66 cmd.address = 0x10e; 67 cmd.data = (u8)(adr >> 16); 68 if (!g_sdio.sdio_cmd52(&cmd)) { 69 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10e data...\n"); 70 goto _fail_; 71 } 72 73 return 1; 74_fail_: 75 return 0; 76} 77 78static int sdio_set_func0_block_size(u32 block_size) 79{ 80 sdio_cmd52_t cmd; 81 82 cmd.read_write = 1; 83 cmd.function = 0; 84 cmd.raw = 0; 85 cmd.address = 0x10; 86 cmd.data = (u8)block_size; 87 if (!g_sdio.sdio_cmd52(&cmd)) { 88 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x10 data...\n"); 89 goto _fail_; 90 } 91 92 cmd.address = 0x11; 93 cmd.data = (u8)(block_size >> 8); 94 if (!g_sdio.sdio_cmd52(&cmd)) { 95 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x11 data...\n"); 96 goto _fail_; 97 } 98 99 return 1; 100_fail_: 101 return 0; 102} 103 104/******************************************** 105 * 106 * Function 1 107 * 108 ********************************************/ 109 110static int sdio_set_func1_block_size(u32 block_size) 111{ 112 sdio_cmd52_t cmd; 113 114 cmd.read_write = 1; 115 cmd.function = 0; 116 cmd.raw = 0; 117 cmd.address = 0x110; 118 cmd.data = (u8)block_size; 119 if (!g_sdio.sdio_cmd52(&cmd)) { 120 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x110 data...\n"); 121 goto _fail_; 122 } 123 cmd.address = 0x111; 124 cmd.data = (u8)(block_size >> 8); 125 if (!g_sdio.sdio_cmd52(&cmd)) { 126 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0x111 data...\n"); 127 goto _fail_; 128 } 129 130 return 1; 131_fail_: 132 return 0; 133} 134 135static int sdio_clear_int(void) 136{ 137#ifndef WILC_SDIO_IRQ_GPIO 138 /* u32 sts; */ 139 sdio_cmd52_t cmd; 140 141 cmd.read_write = 0; 142 cmd.function = 1; 143 cmd.raw = 0; 144 cmd.address = 0x4; 145 cmd.data = 0; 146 g_sdio.sdio_cmd52(&cmd); 147 148 return cmd.data; 149#else 150 u32 reg; 151 152 if (!sdio_read_reg(WILC_HOST_RX_CTRL_0, ®)) { 153 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0); 154 return 0; 155 } 156 reg &= ~0x1; 157 sdio_write_reg(WILC_HOST_RX_CTRL_0, reg); 158 return 1; 159#endif 160 161} 162 163u32 sdio_xfer_cnt(void) 164{ 165 u32 cnt = 0; 166 sdio_cmd52_t cmd; 167 168 cmd.read_write = 0; 169 cmd.function = 1; 170 cmd.raw = 0; 171 cmd.address = 0x1C; 172 cmd.data = 0; 173 g_sdio.sdio_cmd52(&cmd); 174 cnt = cmd.data; 175 176 cmd.read_write = 0; 177 cmd.function = 1; 178 cmd.raw = 0; 179 cmd.address = 0x1D; 180 cmd.data = 0; 181 g_sdio.sdio_cmd52(&cmd); 182 cnt |= (cmd.data << 8); 183 184 cmd.read_write = 0; 185 cmd.function = 1; 186 cmd.raw = 0; 187 cmd.address = 0x1E; 188 cmd.data = 0; 189 g_sdio.sdio_cmd52(&cmd); 190 cnt |= (cmd.data << 16); 191 192 return cnt; 193} 194 195/******************************************** 196 * 197 * Sdio interfaces 198 * 199 ********************************************/ 200int sdio_check_bs(void) 201{ 202 sdio_cmd52_t cmd; 203 204 /** 205 * poll until BS is 0 206 **/ 207 cmd.read_write = 0; 208 cmd.function = 0; 209 cmd.raw = 0; 210 cmd.address = 0xc; 211 cmd.data = 0; 212 if (!g_sdio.sdio_cmd52(&cmd)) { 213 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get BS register...\n"); 214 goto _fail_; 215 } 216 217 return 1; 218 219_fail_: 220 221 return 0; 222} 223 224static int sdio_write_reg(u32 addr, u32 data) 225{ 226#ifdef BIG_ENDIAN 227 data = BYTE_SWAP(data); 228#endif 229 230 if ((addr >= 0xf0) && (addr <= 0xff)) { 231 sdio_cmd52_t cmd; 232 233 cmd.read_write = 1; 234 cmd.function = 0; 235 cmd.raw = 0; 236 cmd.address = addr; 237 cmd.data = data; 238 if (!g_sdio.sdio_cmd52(&cmd)) { 239 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr); 240 goto _fail_; 241 } 242 } else { 243 sdio_cmd53_t cmd; 244 245 /** 246 * set the AHB address 247 **/ 248 if (!sdio_set_func0_csa_address(addr)) 249 goto _fail_; 250 251 cmd.read_write = 1; 252 cmd.function = 0; 253 cmd.address = 0x10f; 254 cmd.block_mode = 0; 255 cmd.increment = 1; 256 cmd.count = 4; 257 cmd.buffer = (u8 *)&data; 258 cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */ 259 260 if (!g_sdio.sdio_cmd53(&cmd)) { 261 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, write reg (%08x)...\n", addr); 262 goto _fail_; 263 } 264 } 265 266 return 1; 267 268_fail_: 269 270 return 0; 271} 272 273static int sdio_write(u32 addr, u8 *buf, u32 size) 274{ 275 u32 block_size = g_sdio.block_size; 276 sdio_cmd53_t cmd; 277 int nblk, nleft; 278 279 cmd.read_write = 1; 280 if (addr > 0) { 281 /** 282 * has to be word aligned... 283 **/ 284 if (size & 0x3) { 285 size += 4; 286 size &= ~0x3; 287 } 288 289 /** 290 * func 0 access 291 **/ 292 cmd.function = 0; 293 cmd.address = 0x10f; 294 } else { 295 /** 296 * has to be word aligned... 297 **/ 298 if (size & 0x3) { 299 size += 4; 300 size &= ~0x3; 301 } 302 303 /** 304 * func 1 access 305 **/ 306 cmd.function = 1; 307 cmd.address = 0; 308 } 309 310 nblk = size / block_size; 311 nleft = size % block_size; 312 313 if (nblk > 0) { 314 cmd.block_mode = 1; 315 cmd.increment = 1; 316 cmd.count = nblk; 317 cmd.buffer = buf; 318 cmd.block_size = block_size; 319 if (addr > 0) { 320 if (!sdio_set_func0_csa_address(addr)) 321 goto _fail_; 322 } 323 if (!g_sdio.sdio_cmd53(&cmd)) { 324 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr); 325 goto _fail_; 326 } 327 if (addr > 0) 328 addr += nblk * block_size; 329 buf += nblk * block_size; 330 } 331 332 if (nleft > 0) { 333 cmd.block_mode = 0; 334 cmd.increment = 1; 335 cmd.count = nleft; 336 cmd.buffer = buf; 337 338 cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ 339 340 if (addr > 0) { 341 if (!sdio_set_func0_csa_address(addr)) 342 goto _fail_; 343 } 344 if (!g_sdio.sdio_cmd53(&cmd)) { 345 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr); 346 goto _fail_; 347 } 348 } 349 350 return 1; 351 352_fail_: 353 354 return 0; 355} 356 357static int sdio_read_reg(u32 addr, u32 *data) 358{ 359 if ((addr >= 0xf0) && (addr <= 0xff)) { 360 sdio_cmd52_t cmd; 361 362 cmd.read_write = 0; 363 cmd.function = 0; 364 cmd.raw = 0; 365 cmd.address = addr; 366 if (!g_sdio.sdio_cmd52(&cmd)) { 367 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd 52, read reg (%08x) ...\n", addr); 368 goto _fail_; 369 } 370 *data = cmd.data; 371 } else { 372 sdio_cmd53_t cmd; 373 374 if (!sdio_set_func0_csa_address(addr)) 375 goto _fail_; 376 377 cmd.read_write = 0; 378 cmd.function = 0; 379 cmd.address = 0x10f; 380 cmd.block_mode = 0; 381 cmd.increment = 1; 382 cmd.count = 4; 383 cmd.buffer = (u8 *)data; 384 385 cmd.block_size = g_sdio.block_size; /* johnny : prevent it from setting unexpected value */ 386 387 if (!g_sdio.sdio_cmd53(&cmd)) { 388 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53, read reg (%08x)...\n", addr); 389 goto _fail_; 390 } 391 } 392 393#ifdef BIG_ENDIAN 394 *data = BYTE_SWAP(*data); 395#endif 396 397 return 1; 398 399_fail_: 400 401 return 0; 402} 403 404static int sdio_read(u32 addr, u8 *buf, u32 size) 405{ 406 u32 block_size = g_sdio.block_size; 407 sdio_cmd53_t cmd; 408 int nblk, nleft; 409 410 cmd.read_write = 0; 411 if (addr > 0) { 412 /** 413 * has to be word aligned... 414 **/ 415 if (size & 0x3) { 416 size += 4; 417 size &= ~0x3; 418 } 419 420 /** 421 * func 0 access 422 **/ 423 cmd.function = 0; 424 cmd.address = 0x10f; 425 } else { 426 /** 427 * has to be word aligned... 428 **/ 429 if (size & 0x3) { 430 size += 4; 431 size &= ~0x3; 432 } 433 434 /** 435 * func 1 access 436 **/ 437 cmd.function = 1; 438 cmd.address = 0; 439 } 440 441 nblk = size / block_size; 442 nleft = size % block_size; 443 444 if (nblk > 0) { 445 cmd.block_mode = 1; 446 cmd.increment = 1; 447 cmd.count = nblk; 448 cmd.buffer = buf; 449 cmd.block_size = block_size; 450 if (addr > 0) { 451 if (!sdio_set_func0_csa_address(addr)) 452 goto _fail_; 453 } 454 if (!g_sdio.sdio_cmd53(&cmd)) { 455 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr); 456 goto _fail_; 457 } 458 if (addr > 0) 459 addr += nblk * block_size; 460 buf += nblk * block_size; 461 } /* if (nblk > 0) */ 462 463 if (nleft > 0) { 464 cmd.block_mode = 0; 465 cmd.increment = 1; 466 cmd.count = nleft; 467 cmd.buffer = buf; 468 469 cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */ 470 471 if (addr > 0) { 472 if (!sdio_set_func0_csa_address(addr)) 473 goto _fail_; 474 } 475 if (!g_sdio.sdio_cmd53(&cmd)) { 476 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes read...\n", addr); 477 goto _fail_; 478 } 479 } 480 481 return 1; 482 483_fail_: 484 485 return 0; 486} 487 488/******************************************** 489 * 490 * Bus interfaces 491 * 492 ********************************************/ 493 494static int sdio_deinit(void *pv) 495{ 496 return 1; 497} 498 499static int sdio_sync(void) 500{ 501 u32 reg; 502 503 /** 504 * Disable power sequencer 505 **/ 506 if (!sdio_read_reg(WILC_MISC, ®)) { 507 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read misc reg...\n"); 508 return 0; 509 } 510 511 reg &= ~BIT(8); 512 if (!sdio_write_reg(WILC_MISC, reg)) { 513 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n"); 514 return 0; 515 } 516 517#ifdef WILC_SDIO_IRQ_GPIO 518 { 519 u32 reg; 520 int ret; 521 522 /** 523 * interrupt pin mux select 524 **/ 525 ret = sdio_read_reg(WILC_PIN_MUX_0, ®); 526 if (!ret) { 527 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0); 528 return 0; 529 } 530 reg |= BIT(8); 531 ret = sdio_write_reg(WILC_PIN_MUX_0, reg); 532 if (!ret) { 533 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0); 534 return 0; 535 } 536 537 /** 538 * interrupt enable 539 **/ 540 ret = sdio_read_reg(WILC_INTR_ENABLE, ®); 541 if (!ret) { 542 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE); 543 return 0; 544 } 545 reg |= BIT(16); 546 ret = sdio_write_reg(WILC_INTR_ENABLE, reg); 547 if (!ret) { 548 g_sdio.dPrint(N_ERR, "[wilc spi]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE); 549 return 0; 550 } 551 } 552#endif 553 554 return 1; 555} 556 557static int sdio_init(wilc_wlan_inp_t *inp, wilc_debug_func func) 558{ 559 sdio_cmd52_t cmd; 560 int loop; 561 u32 chipid; 562 563 memset(&g_sdio, 0, sizeof(wilc_sdio_t)); 564 565 g_sdio.dPrint = func; 566 g_sdio.os_context = inp->os_context.os_private; 567 568 if (inp->io_func.io_init) { 569 if (!inp->io_func.io_init(g_sdio.os_context)) { 570 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed io init bus...\n"); 571 return 0; 572 } 573 } else { 574 return 0; 575 } 576 577 g_sdio.sdio_cmd52 = inp->io_func.u.sdio.sdio_cmd52; 578 g_sdio.sdio_cmd53 = inp->io_func.u.sdio.sdio_cmd53; 579 g_sdio.sdio_set_max_speed = inp->io_func.u.sdio.sdio_set_max_speed; 580 g_sdio.sdio_set_default_speed = inp->io_func.u.sdio.sdio_set_default_speed; 581 582 /** 583 * function 0 csa enable 584 **/ 585 cmd.read_write = 1; 586 cmd.function = 0; 587 cmd.raw = 1; 588 cmd.address = 0x100; 589 cmd.data = 0x80; 590 if (!g_sdio.sdio_cmd52(&cmd)) { 591 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, enable csa...\n"); 592 goto _fail_; 593 } 594 595 /** 596 * function 0 block size 597 **/ 598 if (!sdio_set_func0_block_size(WILC_SDIO_BLOCK_SIZE)) { 599 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, set func 0 block size...\n"); 600 goto _fail_; 601 } 602 g_sdio.block_size = WILC_SDIO_BLOCK_SIZE; 603 604 /** 605 * enable func1 IO 606 **/ 607 cmd.read_write = 1; 608 cmd.function = 0; 609 cmd.raw = 1; 610 cmd.address = 0x2; 611 cmd.data = 0x2; 612 if (!g_sdio.sdio_cmd52(&cmd)) { 613 g_sdio.dPrint(N_ERR, "[wilc sdio] Fail cmd 52, set IOE register...\n"); 614 goto _fail_; 615 } 616 617 /** 618 * make sure func 1 is up 619 **/ 620 cmd.read_write = 0; 621 cmd.function = 0; 622 cmd.raw = 0; 623 cmd.address = 0x3; 624 loop = 3; 625 do { 626 cmd.data = 0; 627 if (!g_sdio.sdio_cmd52(&cmd)) { 628 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, get IOR register...\n"); 629 goto _fail_; 630 } 631 if (cmd.data == 0x2) 632 break; 633 } while (loop--); 634 635 if (loop <= 0) { 636 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail func 1 is not ready...\n"); 637 goto _fail_; 638 } 639 640 /** 641 * func 1 is ready, set func 1 block size 642 **/ 643 if (!sdio_set_func1_block_size(WILC_SDIO_BLOCK_SIZE)) { 644 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail set func 1 block size...\n"); 645 goto _fail_; 646 } 647 648 /** 649 * func 1 interrupt enable 650 **/ 651 cmd.read_write = 1; 652 cmd.function = 0; 653 cmd.raw = 1; 654 cmd.address = 0x4; 655 cmd.data = 0x3; 656 if (!g_sdio.sdio_cmd52(&cmd)) { 657 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd 52, set IEN register...\n"); 658 goto _fail_; 659 } 660 661 /** 662 * make sure can read back chip id correctly 663 **/ 664 if (!sdio_read_reg(0x1000, &chipid)) { 665 g_sdio.dPrint(N_ERR, "[wilc sdio]: Fail cmd read chip id...\n"); 666 goto _fail_; 667 } 668 g_sdio.dPrint(N_ERR, "[wilc sdio]: chipid (%08x)\n", chipid); 669 if ((chipid & 0xfff) > 0x2a0) 670 g_sdio.has_thrpt_enh3 = 1; 671 else 672 g_sdio.has_thrpt_enh3 = 0; 673 g_sdio.dPrint(N_ERR, "[wilc sdio]: has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3); 674 675 return 1; 676 677_fail_: 678 679 return 0; 680} 681 682static void sdio_set_max_speed(void) 683{ 684 g_sdio.sdio_set_max_speed(); 685} 686 687static void sdio_set_default_speed(void) 688{ 689 g_sdio.sdio_set_default_speed(); 690} 691 692static int sdio_read_size(u32 *size) 693{ 694 695 u32 tmp; 696 sdio_cmd52_t cmd; 697 698 /** 699 * Read DMA count in words 700 **/ 701 cmd.read_write = 0; 702 cmd.function = 0; 703 cmd.raw = 0; 704 cmd.address = 0xf2; 705 cmd.data = 0; 706 g_sdio.sdio_cmd52(&cmd); 707 tmp = cmd.data; 708 709 /* cmd.read_write = 0; */ 710 /* cmd.function = 0; */ 711 /* cmd.raw = 0; */ 712 cmd.address = 0xf3; 713 cmd.data = 0; 714 g_sdio.sdio_cmd52(&cmd); 715 tmp |= (cmd.data << 8); 716 717 *size = tmp; 718 return 1; 719} 720 721static int sdio_read_int(u32 *int_status) 722{ 723 724 u32 tmp; 725 sdio_cmd52_t cmd; 726 727 sdio_read_size(&tmp); 728 729 /** 730 * Read IRQ flags 731 **/ 732#ifndef WILC_SDIO_IRQ_GPIO 733 cmd.function = 1; 734 cmd.address = 0x04; 735 cmd.data = 0; 736 g_sdio.sdio_cmd52(&cmd); 737 738 if (cmd.data & BIT(0)) 739 tmp |= INT_0; 740 if (cmd.data & BIT(2)) 741 tmp |= INT_1; 742 if (cmd.data & BIT(3)) 743 tmp |= INT_2; 744 if (cmd.data & BIT(4)) 745 tmp |= INT_3; 746 if (cmd.data & BIT(5)) 747 tmp |= INT_4; 748 if (cmd.data & BIT(6)) 749 tmp |= INT_5; 750 { 751 int i; 752 753 for (i = g_sdio.nint; i < MAX_NUM_INT; i++) { 754 if ((tmp >> (IRG_FLAGS_OFFSET + i)) & 0x1) { 755 g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt (1) : tmp=%x, data=%x\n", tmp, cmd.data); 756 break; 757 } 758 } 759 } 760#else 761 { 762 u32 irq_flags; 763 764 cmd.read_write = 0; 765 cmd.function = 0; 766 cmd.raw = 0; 767 cmd.address = 0xf7; 768 cmd.data = 0; 769 g_sdio.sdio_cmd52(&cmd); 770 irq_flags = cmd.data & 0x1f; 771 tmp |= ((irq_flags >> 0) << IRG_FLAGS_OFFSET); 772 } 773 774#endif 775 776 *int_status = tmp; 777 778 return 1; 779} 780 781static int sdio_clear_int_ext(u32 val) 782{ 783 int ret; 784 785 if (g_sdio.has_thrpt_enh3) { 786 u32 reg; 787 788#ifdef WILC_SDIO_IRQ_GPIO 789 { 790 u32 flags; 791 792 flags = val & (BIT(MAX_NUN_INT_THRPT_ENH2) - 1); 793 reg = flags; 794 } 795#else 796 reg = 0; 797#endif 798 /* select VMM table 0 */ 799 if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0) 800 reg |= BIT(5); 801 /* select VMM table 1 */ 802 if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1) 803 reg |= BIT(6); 804 /* enable VMM */ 805 if ((val & EN_VMM) == EN_VMM) 806 reg |= BIT(7); 807 if (reg) { 808 sdio_cmd52_t cmd; 809 810 cmd.read_write = 1; 811 cmd.function = 0; 812 cmd.raw = 0; 813 cmd.address = 0xf8; 814 cmd.data = reg; 815 816 ret = g_sdio.sdio_cmd52(&cmd); 817 if (!ret) { 818 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__); 819 goto _fail_; 820 } 821 822 } 823 } else { 824#ifdef WILC_SDIO_IRQ_GPIO 825 { 826 /* see below. has_thrpt_enh2 uses register 0xf8 to clear interrupts. */ 827 /* Cannot clear multiple interrupts. Must clear each interrupt individually */ 828 u32 flags; 829 830 flags = val & (BIT(MAX_NUM_INT) - 1); 831 if (flags) { 832 int i; 833 834 ret = 1; 835 for (i = 0; i < g_sdio.nint; i++) { 836 if (flags & 1) { 837 sdio_cmd52_t cmd; 838 839 cmd.read_write = 1; 840 cmd.function = 0; 841 cmd.raw = 0; 842 cmd.address = 0xf8; 843 cmd.data = BIT(i); 844 845 ret = g_sdio.sdio_cmd52(&cmd); 846 if (!ret) { 847 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf8 data (%d) ...\n", __LINE__); 848 goto _fail_; 849 } 850 851 } 852 if (!ret) 853 break; 854 flags >>= 1; 855 } 856 if (!ret) 857 goto _fail_; 858 for (i = g_sdio.nint; i < MAX_NUM_INT; i++) { 859 if (flags & 1) 860 g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt cleared %d...\n", i); 861 flags >>= 1; 862 } 863 } 864 } 865#endif /* WILC_SDIO_IRQ_GPIO */ 866 867 { 868 u32 vmm_ctl; 869 870 vmm_ctl = 0; 871 /* select VMM table 0 */ 872 if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0) 873 vmm_ctl |= BIT(0); 874 /* select VMM table 1 */ 875 if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1) 876 vmm_ctl |= BIT(1); 877 /* enable VMM */ 878 if ((val & EN_VMM) == EN_VMM) 879 vmm_ctl |= BIT(2); 880 881 if (vmm_ctl) { 882 sdio_cmd52_t cmd; 883 884 cmd.read_write = 1; 885 cmd.function = 0; 886 cmd.raw = 0; 887 cmd.address = 0xf6; 888 cmd.data = vmm_ctl; 889 ret = g_sdio.sdio_cmd52(&cmd); 890 if (!ret) { 891 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd52, set 0xf6 data (%d) ...\n", __LINE__); 892 goto _fail_; 893 } 894 } 895 } 896 } 897 898 return 1; 899_fail_: 900 return 0; 901} 902 903static int sdio_sync_ext(int nint /* how mant interrupts to enable. */) 904{ 905 u32 reg; 906 907 if (nint > MAX_NUM_INT) { 908 g_sdio.dPrint(N_ERR, "[wilc sdio]: Too many interupts (%d)...\n", nint); 909 return 0; 910 } 911 if (nint > MAX_NUN_INT_THRPT_ENH2) { 912 g_sdio.dPrint(N_ERR, "[wilc sdio]: Error: Cannot support more than 5 interrupts when has_thrpt_enh2=1.\n"); 913 return 0; 914 } 915 916 g_sdio.nint = nint; 917 918 /** 919 * Disable power sequencer 920 **/ 921 if (!sdio_read_reg(WILC_MISC, ®)) { 922 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read misc reg...\n"); 923 return 0; 924 } 925 926 reg &= ~BIT(8); 927 if (!sdio_write_reg(WILC_MISC, reg)) { 928 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write misc reg...\n"); 929 return 0; 930 } 931 932#ifdef WILC_SDIO_IRQ_GPIO 933 { 934 u32 reg; 935 int ret, i; 936 937 /** 938 * interrupt pin mux select 939 **/ 940 ret = sdio_read_reg(WILC_PIN_MUX_0, ®); 941 if (!ret) { 942 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_PIN_MUX_0); 943 return 0; 944 } 945 reg |= BIT(8); 946 ret = sdio_write_reg(WILC_PIN_MUX_0, reg); 947 if (!ret) { 948 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_PIN_MUX_0); 949 return 0; 950 } 951 952 /** 953 * interrupt enable 954 **/ 955 ret = sdio_read_reg(WILC_INTR_ENABLE, ®); 956 if (!ret) { 957 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_INTR_ENABLE); 958 return 0; 959 } 960 961 for (i = 0; (i < 5) && (nint > 0); i++, nint--) 962 reg |= BIT((27 + i)); 963 ret = sdio_write_reg(WILC_INTR_ENABLE, reg); 964 if (!ret) { 965 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE); 966 return 0; 967 } 968 if (nint) { 969 ret = sdio_read_reg(WILC_INTR2_ENABLE, ®); 970 if (!ret) { 971 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed read reg (%08x)...\n", WILC_INTR2_ENABLE); 972 return 0; 973 } 974 975 for (i = 0; (i < 3) && (nint > 0); i++, nint--) 976 reg |= BIT(i); 977 978 ret = sdio_read_reg(WILC_INTR2_ENABLE, ®); 979 if (!ret) { 980 g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR2_ENABLE); 981 return 0; 982 } 983 } 984 } 985#endif /* WILC_SDIO_IRQ_GPIO */ 986 return 1; 987} 988 989/******************************************** 990 * 991 * Global sdio HIF function table 992 * 993 ********************************************/ 994 995wilc_hif_func_t hif_sdio = { 996 sdio_init, 997 sdio_deinit, 998 sdio_read_reg, 999 sdio_write_reg, 1000 sdio_read, 1001 sdio_write, 1002 sdio_sync, 1003 sdio_clear_int, 1004 sdio_read_int, 1005 sdio_clear_int_ext, 1006 sdio_read_size, 1007 sdio_write, 1008 sdio_read, 1009 sdio_sync_ext, 1010 1011 sdio_set_max_speed, 1012 sdio_set_default_speed, 1013}; 1014 1015