1/* 2 * Copyright (C) 2012 ROCKCHIP, Inc. 3 * 4 * This software is licensed under the terms of the GNU General Public 5 * License version 2, as published by the Free Software Foundation, and 6 * may be copied, distributed, and modified under those terms. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14/* Rock-chips rfkill driver for wifi 15 */ 16 17#include <linux/kernel.h> 18#include <linux/platform_device.h> 19#include <linux/module.h> 20#include <linux/rfkill.h> 21#include <linux/init.h> 22#include <linux/slab.h> 23#include <linux/regulator/consumer.h> 24#include <linux/delay.h> 25#include <linux/rfkill-wlan.h> 26#include <linux/rfkill-bt.h> 27#include <linux/wakelock.h> 28#include <linux/interrupt.h> 29#include <asm/irq.h> 30#include <linux/suspend.h> 31#include <linux/proc_fs.h> 32#include <linux/uaccess.h> 33#include <linux/gpio.h> 34#include <dt-bindings/gpio/gpio.h> 35#include <linux/skbuff.h> 36#include <linux/fb.h> 37#include <linux/rockchip/grf.h> 38#include <linux/regmap.h> 39#include <linux/mfd/syscon.h> 40#include <linux/mmc/host.h> 41#ifdef CONFIG_OF 42#include <linux/of.h> 43#include <linux/of_device.h> 44#include <linux/of_gpio.h> 45#endif 46#include <linux/soc/rockchip/rk_vendor_storage.h> 47#include <linux/device.h> 48 49#include "../../drivers/mmc/core/pwrseq.h" 50 51#define DBG(x...) 52 53#define LOG(x...) pr_info("[WLAN_RFKILL]: " x) 54 55struct rfkill_wlan_data { 56 struct rksdmmc_gpio_wifi_moudle *pdata; 57 struct wake_lock wlan_irq_wl; 58}; 59 60static struct rfkill_wlan_data *g_rfkill = NULL; 61static int power_set_time = 0; 62static int wifi_bt_vbat_state; 63static int wifi_power_state; 64 65static const char wlan_name[] = "rkwifi"; 66 67static char wifi_chip_type_string[64]; 68/*********************************************************** 69 * 70 * Broadcom Wifi Static Memory 71 * 72 **********************************************************/ 73#ifdef CONFIG_RKWIFI 74#define BCM_STATIC_MEMORY_SUPPORT 0 75#else 76#define BCM_STATIC_MEMORY_SUPPORT 0 77#endif 78// =========================== 79#if BCM_STATIC_MEMORY_SUPPORT 80#define PREALLOC_WLAN_SEC_NUM 4 81#define PREALLOC_WLAN_BUF_NUM 160 82#define PREALLOC_WLAN_SECTION_HEADER 0 83#define WLAN_SKB_BUF_NUM 16 84 85#define WLAN_SECTION_SIZE_0 (12 * 1024) 86#define WLAN_SECTION_SIZE_1 (12 * 1024) 87#define WLAN_SECTION_SIZE_2 (32 * 1024) 88#define WLAN_SECTION_SIZE_3 (136 * 1024) 89#define WLAN_SECTION_SIZE_4 (4 * 1024) 90#define WLAN_SECTION_SIZE_5 (64 * 1024) 91#define WLAN_SECTION_SIZE_6 (4 * 1024) 92#define WLAN_SECTION_SIZE_7 (4 * 1024) 93 94static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM + 1]; 95 96struct wifi_mem_prealloc { 97 void *mem_ptr; 98 unsigned long size; 99}; 100 101static struct wifi_mem_prealloc wifi_mem_array[8] = {{NULL, (WLAN_SECTION_SIZE_0)}, {NULL, (WLAN_SECTION_SIZE_1)}, 102 {NULL, (WLAN_SECTION_SIZE_2)}, {NULL, (WLAN_SECTION_SIZE_3)}, 103 {NULL, (WLAN_SECTION_SIZE_4)}, {NULL, (WLAN_SECTION_SIZE_5)}, 104 {NULL, (WLAN_SECTION_SIZE_6)}, {NULL, (WLAN_SECTION_SIZE_7)}}; 105 106static int rockchip_init_wifi_mem(void) 107{ 108 int i; 109 int j; 110 111 for (i = 0; i < WLAN_SKB_BUF_NUM; i++) { 112 wlan_static_skb[i] = dev_alloc_skb(((i < (WLAN_SKB_BUF_NUM / 0x02)) ? (PAGE_SIZE * 1) : (PAGE_SIZE * 0x02))); 113 114 if (!wlan_static_skb[i]) { 115 goto err_skb_alloc; 116 } 117 } 118 119 wlan_static_skb[i] = dev_alloc_skb((PAGE_SIZE * 0x04)); 120 if (!wlan_static_skb[i]) { 121 goto err_skb_alloc; 122 } 123 124 for (i = 0; i <= 0x07; i++) { 125 wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size, GFP_KERNEL); 126 127 if (!wifi_mem_array[i].mem_ptr) { 128 goto err_mem_alloc; 129 } 130 } 131 return 0; 132 133err_mem_alloc: 134 pr_err("Failed to mem_alloc for WLAN\n"); 135 for (j = 0; j < i; j++) { 136 kfree(wifi_mem_array[j].mem_ptr); 137 } 138 i = WLAN_SKB_BUF_NUM; 139err_skb_alloc: 140 pr_err("Failed to skb_alloc for WLAN\n"); 141 for (j = 0; j < i; j++) { 142 dev_kfree_skb(wlan_static_skb[j]); 143 } 144 dev_kfree_skb(wlan_static_skb[j]); 145 146 return -ENOMEM; 147} 148 149void *rockchip_mem_prealloc(int section, unsigned long size) 150{ 151 if (section == PREALLOC_WLAN_SEC_NUM) { 152 return wlan_static_skb; 153 } 154 155 if (section < 0 || section > 0x07) { 156 return NULL; 157 } 158 159 if (wifi_mem_array[section].size < size) { 160 return NULL; 161 } 162 163 return wifi_mem_array[section].mem_ptr; 164} 165#else 166void *rockchip_mem_prealloc(int section, unsigned long size) 167{ 168 return NULL; 169} 170#endif 171EXPORT_SYMBOL(rockchip_mem_prealloc); 172 173int rfkill_set_wifi_bt_power(int on) 174{ 175 struct rfkill_wlan_data *mrfkill = g_rfkill; 176 struct rksdmmc_gpio *vbat; 177 178 LOG("%s: %d\n", __func__, on); 179 180 if (!mrfkill) { 181 LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__); 182 return -1; 183 } 184 185 vbat = &mrfkill->pdata->vbat_n; 186 if (on) { 187 if (gpio_is_valid(vbat->io)) { 188 gpio_direction_output(vbat->io, vbat->enable); 189 } 190 } else { 191 if (gpio_is_valid(vbat->io)) { 192 gpio_direction_output(vbat->io, !(vbat->enable)); 193 } 194 } 195 wifi_bt_vbat_state = on; 196 return 0; 197} 198 199/************************************************************************** 200 * 201 * get wifi power state Func 202 * 203 *************************************************************************/ 204int rfkill_get_wifi_power_state(int *power) 205{ 206 struct rfkill_wlan_data *mrfkill = g_rfkill; 207 208 if (!mrfkill) { 209 LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__); 210 return -1; 211 } 212 213 *power = wifi_power_state; 214 215 return 0; 216} 217 218/************************************************************************** 219 * 220 * Wifi Power Control Func 221 * 0 -> power off 222 * 1 -> power on 223 * 224 *************************************************************************/ 225int rockchip_wifi_power(int on) 226{ 227 struct rfkill_wlan_data *mrfkill = g_rfkill; 228 struct rksdmmc_gpio *poweron, *reset; 229 struct regulator *ldo = NULL; 230 int bt_power = 0; 231 bool toggle = false; 232 233 LOG("%s: %d\n", __func__, on); 234 235 if (!on && primary_sdio_host) { 236 mmc_pwrseq_power_off(primary_sdio_host); 237 } 238 239 if (!mrfkill) { 240 LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__); 241 return -1; 242 } 243 244 if (mrfkill->pdata->wifi_power_remain && power_set_time) { 245 LOG("%s: wifi power is setted to be remain on.", __func__); 246 return 0; 247 } 248 power_set_time++; 249 250 if (!rfkill_get_bt_power_state(&bt_power, &toggle)) { 251 LOG("%s: toggle = %s\n", __func__, toggle ? "true" : "false"); 252 } 253 254 if (mrfkill->pdata->mregulator.power_ctrl_by_pmu) { 255 int ret = -1; 256 char *ldostr; 257 int level = mrfkill->pdata->mregulator.enable; 258 259 ldostr = mrfkill->pdata->mregulator.pmu_regulator; 260 if (!ldostr) { 261 return -1; 262 } 263 ldo = regulator_get(NULL, ldostr); 264 if (!ldo || IS_ERR(ldo)) { 265 LOG("\n\n\n%s get ldo error,please mod this\n\n\n", __func__); 266 return -1; 267 } 268 if (on == level) { 269 regulator_set_voltage(ldo, 0x2DC6C0, 0x2DC6C0); 270 LOG("%s: %s enabled\n", __func__, ldostr); 271 ret = regulator_enable(ldo); 272 wifi_power_state = 1; 273 LOG("wifi turn on power.\n"); 274 } else { 275 LOG("%s: %s disabled\n", __func__, ldostr); 276 while (regulator_is_enabled(ldo) > 0) { 277 ret = regulator_disable(ldo); 278 } 279 wifi_power_state = 0; 280 LOG("wifi shut off power.\n"); 281 } 282 regulator_put(ldo); 283 msleep(0x64); 284 } else { 285 poweron = &mrfkill->pdata->power_n; 286 reset = &mrfkill->pdata->reset_n; 287 288 if (on) { 289 if (toggle) { 290 rfkill_set_wifi_bt_power(1); 291 msleep(0x64); 292 } 293 294 if (gpio_is_valid(poweron->io)) { 295 gpio_direction_output(poweron->io, poweron->enable); 296 msleep(0x64); 297 } 298 299 if (gpio_is_valid(reset->io)) { 300 gpio_direction_output(reset->io, reset->enable); 301 msleep(0x64); 302 } 303 304 wifi_power_state = 1; 305 LOG("wifi turn on power [GPIO%d-%d]\n", poweron->io, poweron->enable); 306 } else { 307 if (gpio_is_valid(poweron->io)) { 308 printk("wifi power off\n"); 309 gpio_direction_output(poweron->io, !(poweron->enable)); 310 msleep(0x64); 311 } 312 313 if (gpio_is_valid(reset->io)) { 314 gpio_direction_output(reset->io, !(reset->enable)); 315 } 316 317 wifi_power_state = 0; 318 if (toggle) { 319 if (!bt_power) { 320 LOG("%s: wifi will set vbat to low\n", __func__); 321 rfkill_set_wifi_bt_power(0); 322 } else { 323 LOG("%s: wifi shouldn't control the vbat\n", __func__); 324 } 325 } 326 LOG("wifi shut off power [GPIO%d-%d]\n", poweron->io, !poweron->enable); 327 } 328 } 329 330 return 0; 331} 332EXPORT_SYMBOL(rockchip_wifi_power); 333 334/************************************************************************** 335 * 336 * Wifi Sdio Detect Func 337 * 338 *************************************************************************/ 339 340int rockchip_wifi_set_carddetect(int val) 341{ 342 return mmc_host_rescan(NULL, val, 1); 343} 344EXPORT_SYMBOL(rockchip_wifi_set_carddetect); 345 346/************************************************************************** 347 * 348 * Wifi Get Interrupt irq Func 349 * 350 *************************************************************************/ 351int rockchip_wifi_get_oob_irq(void) 352{ 353 struct rfkill_wlan_data *mrfkill = g_rfkill; 354 struct rksdmmc_gpio *wifi_int_irq; 355 356 LOG("%s: Enter\n", __func__); 357 358 if (!mrfkill) { 359 LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__); 360 return -1; 361 } 362 363 wifi_int_irq = &mrfkill->pdata->wifi_int_b; 364 if (gpio_is_valid(wifi_int_irq->io)) { 365 return gpio_to_irq(wifi_int_irq->io); 366 } else { 367 LOG("%s: wifi OOB pin isn't defined.\n", __func__); 368 } 369 370 return -1; 371} 372EXPORT_SYMBOL(rockchip_wifi_get_oob_irq); 373 374int rockchip_wifi_get_oob_irq_flag(void) 375{ 376 struct rfkill_wlan_data *mrfkill = g_rfkill; 377 struct rksdmmc_gpio *wifi_int_irq; 378 int gpio_flags = -1; 379 380 if (mrfkill) { 381 wifi_int_irq = &mrfkill->pdata->wifi_int_b; 382 if (gpio_is_valid(wifi_int_irq->io)) { 383 gpio_flags = wifi_int_irq->enable; 384 } 385 } 386 387 return gpio_flags; 388} 389EXPORT_SYMBOL(rockchip_wifi_get_oob_irq_flag); 390 391/************************************************************************** 392 * 393 * Wifi Reset Func 394 * 395 *************************************************************************/ 396int rockchip_wifi_reset(int on) 397{ 398 return 0; 399} 400EXPORT_SYMBOL(rockchip_wifi_reset); 401 402/************************************************************************** 403 * 404 * Wifi MAC custom Func 405 * 406 *************************************************************************/ 407#include <linux/etherdevice.h> 408#include <linux/errno.h> 409u8 wifi_custom_mac_addr[6] = {0, 0, 0, 0, 0, 0}; 410 411static int get_wifi_addr_vendor(unsigned char *addr) 412{ 413 int ret; 414 int count = 5; 415 416 while (count-- > 0) { 417 if (is_rk_vendor_ready()) { 418 break; 419 } 420 /* sleep 500ms wait rk vendor driver ready */ 421 msleep(500); 422 } 423 ret = rk_vendor_read(WIFI_MAC_ID, addr, 0x06); 424 if (ret != 0x06 || is_zero_ether_addr(addr)) { 425 LOG("%s: rk_vendor_read wifi mac address failed (%d)\n", __func__, ret); 426#ifdef CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR 427 random_ether_addr(addr); 428 LOG("%s: generate random wifi mac address: " 429 "%02x:%02x:%02x:%02x:%02x:%02x\n", 430 __func__, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 431 ret = rk_vendor_write(WIFI_MAC_ID, addr, 0x06); 432 if (ret != 0) { 433 LOG("%s: rk_vendor_write failed %d\n" __func__, ret); 434 memset(addr, 0, 0x06); 435 return -1; 436 } 437#else 438 return -1; 439#endif 440 } else { 441 LOG("%s: rk_vendor_read wifi mac address: " 442 "%02x:%02x:%02x:%02x:%02x:%02x\n", 443 __func__, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); 444 } 445 return 0; 446} 447 448int rockchip_wifi_mac_addr(unsigned char *buf) 449{ 450 char mac_buf[20] = {0}; 451 452 LOG("%s: enter.\n", __func__); 453 454 // from vendor storage 455 if (is_zero_ether_addr(wifi_custom_mac_addr)) { 456 if (get_wifi_addr_vendor(wifi_custom_mac_addr) != 0) { 457 return -1; 458 } 459 } 460 461 sprintf(mac_buf, "%02x:%02x:%02x:%02x:%02x:%02x", wifi_custom_mac_addr[0], wifi_custom_mac_addr[1], 462 wifi_custom_mac_addr[0x02], wifi_custom_mac_addr[0x03], 463 wifi_custom_mac_addr[0x04], wifi_custom_mac_addr[0x05]); 464 LOG("falsh wifi_custom_mac_addr=[%s]\n", mac_buf); 465 466 if (is_valid_ether_addr(wifi_custom_mac_addr)) { 467 if (!strncmp(wifi_chip_type_string, "rtl", 0x03)) { 468 wifi_custom_mac_addr[0] &= ~0x2; // for p2p 469 } 470 } else { 471 LOG("This mac address is not valid, ignored...\n"); 472 return -1; 473 } 474 475 memcpy(buf, wifi_custom_mac_addr, 0x06); 476 477 return 0; 478} 479EXPORT_SYMBOL(rockchip_wifi_mac_addr); 480 481/************************************************************************** 482 * 483 * wifi get country code func 484 * 485 *************************************************************************/ 486struct cntry_locales_custom { 487 char iso_abbrev[4]; /* ISO 3166-1 country abbreviation */ 488 char custom_locale[4]; /* Custom firmware locale */ 489 int custom_locale_rev; /* Custom local revisin default -1 */ 490}; 491 492static struct cntry_locales_custom country_cloc; 493 494void *rockchip_wifi_country_code(char *ccode) 495{ 496 struct cntry_locales_custom *mcloc; 497 498 LOG("%s: set country code [%s]\n", __func__, ccode); 499 mcloc = &country_cloc; 500 memcpy(mcloc->custom_locale, ccode, 0x04); 501 mcloc->custom_locale_rev = 0; 502 503 return mcloc; 504} 505EXPORT_SYMBOL(rockchip_wifi_country_code); 506 507static int rfkill_rk_setup_gpio(struct rksdmmc_gpio *gpio, const char *prefix, const char *name) 508{ 509 if (gpio_is_valid(gpio->io)) { 510 int ret = 0; 511 512 sprintf(gpio->name, "%s_%s", prefix, name); 513 ret = gpio_request(gpio->io, gpio->name); 514 if (ret) { 515 LOG("Failed to get %s gpio.\n", gpio->name); 516 return -1; 517 } 518 } 519 520 return 0; 521} 522 523#ifdef CONFIG_OF 524static int wlan_platdata_parse_dt(struct device *dev, struct rksdmmc_gpio_wifi_moudle *data) 525{ 526 struct device_node *node = dev->of_node; 527 const char *strings; 528 u32 value; 529 int gpio, ret; 530 enum of_gpio_flags flags; 531 u32 ext_clk_value = 0; 532 533 if (!node) { 534 return -ENODEV; 535 } 536 537 memset(data, 0, sizeof(*data)); 538 539#ifdef CONFIG_MFD_SYSCON 540 data->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); 541 if (IS_ERR(data->grf)) { 542 LOG("can't find rockchip,grf property\n"); 543 } 544#endif 545 546 ret = of_property_read_string(node, "wifi_chip_type", &strings); 547 if (ret) { 548 LOG("%s: Can not read wifi_chip_type, set default to rkwifi.\n", __func__); 549 strcpy(wifi_chip_type_string, "rkwifi"); 550 } else { 551 strcpy(wifi_chip_type_string, strings); 552 } 553 LOG("%s: wifi_chip_type = %s\n", __func__, wifi_chip_type_string); 554 555 if (of_find_property(node, "keep_wifi_power_on", NULL)) { 556 data->wifi_power_remain = true; 557 LOG("%s: wifi power remain\n", __func__); 558 } else { 559 data->wifi_power_remain = false; 560 LOG("%s: enable wifi power control.\n", __func__); 561 } 562 563 if (of_find_property(node, "power_ctrl_by_pmu", NULL)) { 564 data->mregulator.power_ctrl_by_pmu = true; 565 ret = of_property_read_string(node, "power_pmu_regulator", &strings); 566 if (ret) { 567 LOG("%s: Can not read property: power_pmu_regulator.\n", __func__); 568 data->mregulator.power_ctrl_by_pmu = false; 569 } else { 570 LOG("%s: wifi power controlled by pmu(%s).\n", __func__, strings); 571 sprintf(data->mregulator.pmu_regulator, "%s", strings); 572 } 573 ret = of_property_read_u32(node, "power_pmu_enable_level", &value); 574 if (ret) { 575 LOG("%s: Can not read: power_pmu_enable_level.\n", __func__); 576 data->mregulator.power_ctrl_by_pmu = false; 577 } else { 578 LOG("%s: wifi power controlled by pmu(level = %s).\n", __func__, (value == 1) ? "HIGH" : "LOW"); 579 data->mregulator.enable = value; 580 } 581 } else { 582 data->mregulator.power_ctrl_by_pmu = false; 583 LOG("%s: wifi power controled by gpio.\n", __func__); 584 gpio = of_get_named_gpio_flags(node, "WIFI,poweren_gpio", 0, &flags); 585 if (gpio_is_valid(gpio)) { 586 data->power_n.io = gpio; 587 data->power_n.enable = (flags == GPIO_ACTIVE_HIGH) ? 1 : 0; 588 LOG("%s: WIFI,poweren_gpio = %d flags = %d.\n", __func__, gpio, flags); 589 } else { 590 data->power_n.io = -1; 591 } 592 gpio = of_get_named_gpio_flags(node, "WIFI,vbat_gpio", 0, &flags); 593 if (gpio_is_valid(gpio)) { 594 data->vbat_n.io = gpio; 595 data->vbat_n.enable = (flags == GPIO_ACTIVE_HIGH) ? 1 : 0; 596 LOG("%s: WIFI,vbat_gpio = %d, flags = %d.\n", __func__, gpio, flags); 597 } else { 598 data->vbat_n.io = -1; 599 } 600 gpio = of_get_named_gpio_flags(node, "WIFI,reset_gpio", 0, &flags); 601 if (gpio_is_valid(gpio)) { 602 data->reset_n.io = gpio; 603 data->reset_n.enable = (flags == GPIO_ACTIVE_HIGH) ? 1 : 0; 604 LOG("%s: WIFI,reset_gpio = %d, flags = %d.\n", __func__, gpio, flags); 605 } else { 606 data->reset_n.io = -1; 607 } 608 gpio = of_get_named_gpio_flags(node, "WIFI,host_wake_irq", 0, &flags); 609 if (gpio_is_valid(gpio)) { 610 data->wifi_int_b.io = gpio; 611 data->wifi_int_b.enable = !flags; 612 LOG("%s: WIFI,host_wake_irq = %d, flags = %d.\n", __func__, gpio, flags); 613 } else { 614 data->wifi_int_b.io = -1; 615 } 616 } 617 618 data->ext_clk = devm_clk_get(dev, "clk_wifi"); 619 if (IS_ERR(data->ext_clk)) { 620 LOG("%s: The ref_wifi_clk not found !\n", __func__); 621 } else { 622 of_property_read_u32(node, "ref-clock-frequency", &ext_clk_value); 623 if (ext_clk_value > 0) { 624 ret = clk_set_rate(data->ext_clk, ext_clk_value); 625 if (ret) { 626 LOG("%s: set ref clk error!\n", __func__); 627 } 628 } 629 630 ret = clk_prepare_enable(data->ext_clk); 631 if (ret) { 632 LOG("%s: enable ref clk error!\n", __func__); 633 } 634 635 /* WIFI clock (REF_CLKOUT) output enable. 636 * 1'b0: drive disable 637 * 1'b1: output enable 638 */ 639 if (of_machine_is_compatible("rockchip,rk3308")) { 640 regmap_write(data->grf, 0x0314, 0x00020002); 641 } 642 } 643 644 return 0; 645} 646#endif // CONFIG_OF 647 648#if defined(CONFIG_HAS_EARLYSUSPEND) 649#include <linux/earlysuspend.h> 650 651static void wlan_early_suspend(struct early_suspend *h) 652{ 653 LOG("%s :enter\n", __func__); 654 655 return; 656} 657 658static void wlan_late_resume(struct early_suspend *h) 659{ 660 LOG("%s :enter\n", __func__); 661 662 return; 663} 664 665struct early_suspend wlan_early_suspend { 666 .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20; 667 .suspend = wlan_early_suspend; 668 .resume = wlan_late_resume; 669} 670#endif 671 672static void 673rfkill_wlan_early_suspend(void) 674{ 675 return; 676} 677 678static void rfkill_wlan_later_resume(void) 679{ 680 return; 681} 682 683static int rfkill_wlan_fb_event_notify(struct notifier_block *self, unsigned long action, void *data) 684{ 685 struct fb_event *event = data; 686 int blank_mode = *((int *)event->data); 687 688 switch (blank_mode) { 689 case FB_BLANK_UNBLANK: 690 rfkill_wlan_later_resume(); 691 break; 692 case FB_BLANK_NORMAL: 693 rfkill_wlan_early_suspend(); 694 break; 695 default: 696 rfkill_wlan_early_suspend(); 697 break; 698 } 699 700 return 0; 701} 702 703static struct notifier_block rfkill_wlan_fb_notifier = { 704 .notifier_call = rfkill_wlan_fb_event_notify, 705}; 706 707static ssize_t wifi_power_show(struct class *cls, struct class_attribute *attr, char *_buf) 708{ 709 return sprintf(_buf, "%d\n", wifi_power_state); 710} 711 712static ssize_t wifi_power_store(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count) 713{ 714 long poweren = 0; 715 716 if (kstrtol(_buf, 0x0A, &poweren) < 0) { 717 return -EINVAL; 718 } 719 720 LOG("%s: poweren = %ld\n", __func__, poweren); 721 722 if (poweren > 0) { 723 rockchip_wifi_power(1); 724 } else { 725 rockchip_wifi_power(0); 726 } 727 728 return _count; 729} 730 731static CLASS_ATTR_RW(wifi_power); 732 733static ssize_t wifi_bt_vbat_show(struct class *cls, struct class_attribute *attr, char *_buf) 734{ 735 return sprintf(_buf, "%d\n", wifi_bt_vbat_state); 736} 737 738static ssize_t wifi_bt_vbat_store(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count) 739{ 740 long vbat = 0; 741 742 if (kstrtol(_buf, 0x0A, &vbat) < 0) { 743 return -EINVAL; 744 } 745 746 LOG("%s: vbat = %ld\n", __func__, vbat); 747 748 if (vbat > 0) { 749 rfkill_set_wifi_bt_power(1); 750 } else { 751 rfkill_set_wifi_bt_power(0); 752 } 753 754 return _count; 755} 756 757static CLASS_ATTR_RW(wifi_bt_vbat); 758 759static ssize_t wifi_set_carddetect_store(struct class *cls, struct class_attribute *attr, const char *_buf, 760 size_t _count) 761{ 762 long val = 0; 763 764 if (kstrtol(_buf, 0x0A, &val) < 0) { 765 return -EINVAL; 766 } 767 768 LOG("%s: val = %ld\n", __func__, val); 769 770 if (val > 0) { 771 rockchip_wifi_set_carddetect(1); 772 } else { 773 rockchip_wifi_set_carddetect(0); 774 } 775 776 return _count; 777} 778 779static CLASS_ATTR_WO(wifi_set_carddetect); 780 781static struct attribute *rkwifi_power_attrs[] = { 782 &class_attr_wifi_power.attr, 783 &class_attr_wifi_bt_vbat.attr, 784 &class_attr_wifi_set_carddetect.attr, 785 NULL, 786}; 787ATTRIBUTE_GROUPS(rkwifi_power); 788 789/** Device model classes */ 790static struct class rkwifi_power = { 791 .name = "rkwifi", 792 .class_groups = rkwifi_power_groups, 793}; 794 795static int rfkill_wlan_probe(struct platform_device *pdev) 796{ 797 struct rfkill_wlan_data *rfkill; 798 struct rksdmmc_gpio_wifi_moudle *pdata = pdev->dev.platform_data; 799 int ret = -1; 800 801 LOG("Enter %s\n", __func__); 802 803 class_register(&rkwifi_power); 804 805 if (!pdata) { 806#ifdef CONFIG_OF 807 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 808 if (!pdata) { 809 return -ENOMEM; 810 } 811 812 ret = wlan_platdata_parse_dt(&pdev->dev, pdata); 813 if (ret < 0) { 814#endif 815 LOG("%s: No platform data specified\n", __func__); 816 return ret; 817#ifdef CONFIG_OF 818 } 819#endif 820 } 821 822 rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); 823 if (!rfkill) { 824 goto rfkill_alloc_fail; 825 } 826 827 rfkill->pdata = pdata; 828 g_rfkill = rfkill; 829 830 LOG("%s: init gpio\n", __func__); 831 832 if (!pdata->mregulator.power_ctrl_by_pmu) { 833 ret = rfkill_rk_setup_gpio(&pdata->vbat_n, wlan_name, "wlan_vbat"); 834 if (ret) { 835 goto fail_alloc; 836 } 837 838 ret = rfkill_rk_setup_gpio(&pdata->power_n, wlan_name, "wlan_poweren"); 839 if (ret) { 840 goto fail_alloc; 841 } 842 843 ret = rfkill_rk_setup_gpio(&pdata->reset_n, wlan_name, "wlan_reset"); 844 if (ret) { 845 goto fail_alloc; 846 } 847 } 848 849 wake_lock_init(&rfkill->wlan_irq_wl, WAKE_LOCK_SUSPEND, "rfkill_wlan_wake"); 850 851 rfkill_set_wifi_bt_power(1); 852 853#ifdef CONFIG_SDIO_KEEPALIVE 854 if (gpio_is_valid(pdata->power_n.io) && primary_sdio_host && primary_sdio_host->support_chip_alive) { 855 gpio_direction_output(pdata->power_n.io, pdata->power_n.enable); 856 } 857#else 858 if (gpio_is_valid(pdata->power_n.io)) { 859 gpio_direction_output(pdata->power_n.io, !pdata->power_n.enable); 860 } 861#endif 862 863 if (pdata->wifi_power_remain) { 864 rockchip_wifi_power(1); 865 } 866 867#if BCM_STATIC_MEMORY_SUPPORT 868 rockchip_init_wifi_mem(); 869#endif 870 871#if defined(CONFIG_HAS_EARLYSUSPEND) 872 register_early_suspend(wlan_early_suspend); 873#endif 874 875 fb_register_client(&rfkill_wlan_fb_notifier); 876 877 LOG("Exit %s\n", __func__); 878 879 return 0; 880 881fail_alloc: 882 kfree(rfkill); 883rfkill_alloc_fail: 884 kfree(pdata); 885 886 g_rfkill = NULL; 887 888 return ret; 889} 890 891static int rfkill_wlan_remove(struct platform_device *pdev) 892{ 893 struct rfkill_wlan_data *rfkill = platform_get_drvdata(pdev); 894 895 LOG("Enter %s\n", __func__); 896 897 wake_lock_destroy(&rfkill->wlan_irq_wl); 898 899 fb_unregister_client(&rfkill_wlan_fb_notifier); 900 901 if (gpio_is_valid(rfkill->pdata->power_n.io)) { 902 gpio_free(rfkill->pdata->power_n.io); 903 } 904 905 if (gpio_is_valid(rfkill->pdata->reset_n.io)) { 906 gpio_free(rfkill->pdata->reset_n.io); 907 } 908 909 kfree(rfkill); 910 g_rfkill = NULL; 911 912 return 0; 913} 914 915static int rfkill_wlan_suspend(struct platform_device *pdev, pm_message_t state) 916{ 917 LOG("Enter %s\n", __func__); 918 return 0; 919} 920 921static int rfkill_wlan_resume(struct platform_device *pdev) 922{ 923 LOG("Enter %s\n", __func__); 924 return 0; 925} 926 927#ifdef CONFIG_OF 928static struct of_device_id wlan_platdata_of_match[] = {{.compatible = "wlan-platdata"}, {}}; 929MODULE_DEVICE_TABLE(of, wlan_platdata_of_match); 930#endif // CONFIG_OF 931 932static struct platform_driver rfkill_wlan_driver = { 933 .probe = rfkill_wlan_probe, 934 .remove = rfkill_wlan_remove, 935 .suspend = rfkill_wlan_suspend, 936 .resume = rfkill_wlan_resume, 937 .driver = 938 { 939 .name = "wlan-platdata", 940 .owner = THIS_MODULE, 941 .of_match_table = of_match_ptr(wlan_platdata_of_match), 942 }, 943}; 944 945int __init rfkill_wlan_init(void) 946{ 947 LOG("Enter %s\n", __func__); 948 return platform_driver_register(&rfkill_wlan_driver); 949} 950 951void __exit rfkill_wlan_exit(void) 952{ 953 LOG("Enter %s\n", __func__); 954 platform_driver_unregister(&rfkill_wlan_driver); 955} 956 957MODULE_DESCRIPTION("rock-chips rfkill for wifi v0.1"); 958MODULE_AUTHOR("gwl@rock-chips.com"); 959MODULE_LICENSE("GPL"); 960