rfkill-wlan.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  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. #include <linux/kernel.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/module.h>
  19. #include <linux/rfkill.h>
  20. #include <linux/init.h>
  21. #include <linux/slab.h>
  22. #include <linux/regulator/consumer.h>
  23. #include <linux/delay.h>
  24. #include <linux/rfkill-wlan.h>
  25. #include <linux/rfkill-bt.h>
  26. #include <linux/interrupt.h>
  27. #include <asm/irq.h>
  28. #include <linux/suspend.h>
  29. #include <linux/proc_fs.h>
  30. #include <linux/uaccess.h>
  31. #include <linux/gpio.h>
  32. #include <dt-bindings/gpio/gpio.h>
  33. #include <linux/skbuff.h>
  34. #include <linux/fb.h>
  35. #include <linux/regmap.h>
  36. #include <linux/mfd/syscon.h>
  37. #include <linux/mmc/host.h>
  38. #ifdef CONFIG_OF
  39. #include <linux/of.h>
  40. #include <linux/of_device.h>
  41. #include <linux/of_gpio.h>
  42. #endif
  43. #if 0
  44. #define DBG(x...) printk(KERN_INFO "[WLAN_RFKILL]: "x)
  45. #else
  46. #define DBG(x...)
  47. #endif
  48. #define LOG(x...) printk(KERN_INFO "[WLAN_RFKILL]: "x)
  49. extern struct mmc_host *primary_sdio_host;
  50. extern void mmc_pwrseq_power_off(struct mmc_host *host);
  51. struct rfkill_wlan_data {
  52. struct rksdmmc_gpio_wifi_moudle *pdata;
  53. // struct wake_lock wlan_irq_wl;
  54. };
  55. static struct rfkill_wlan_data *g_rfkill = NULL;
  56. static int power_set_time = 0;
  57. static const char wlan_name[] =
  58. #if defined (CONFIG_BCM4330)
  59. #if defined (CONFIG_BT_MODULE_NH660)
  60. "nh660"
  61. #else
  62. "bcm4330"
  63. #endif
  64. #elif defined (CONFIG_RK903)
  65. #if defined(CONFIG_RKWIFI_26M)
  66. "rk903_26M"
  67. #else
  68. "rk903"
  69. #endif
  70. #elif defined(CONFIG_BCM4329)
  71. "bcm4329"
  72. #elif defined(CONFIG_MV8787)
  73. "mv8787"
  74. #elif defined(CONFIG_AP6210)
  75. #if defined(CONFIG_RKWIFI_26M)
  76. "ap6210"
  77. #else
  78. "ap6210_24M"
  79. #endif
  80. #elif defined(CONFIG_AP6330)
  81. "ap6330"
  82. #elif defined(CONFIG_AP6476)
  83. "ap6476"
  84. #elif defined(CONFIG_AP6493)
  85. "ap6493"
  86. #elif defined(CONFIG_MVL88W8977)
  87. "mvl88w8977"
  88. #else
  89. "wlan_default"
  90. #endif
  91. ;
  92. static char wifi_chip_type_string[64];
  93. int get_wifi_chip_type(void)
  94. {
  95. int type;
  96. if (strcmp(wifi_chip_type_string, "ap6210") == 0) {
  97. type = WIFI_AP6210;
  98. } else if (strcmp(wifi_chip_type_string, "ap6212") == 0) {
  99. type = WIFI_AP6212;
  100. } else if (strcmp(wifi_chip_type_string, "rk901") == 0) {
  101. type = WIFI_RK901;
  102. } else if (strcmp(wifi_chip_type_string, "rk903") == 0) {
  103. type = WIFI_RK903;
  104. } else if (strcmp(wifi_chip_type_string, "ap6181") == 0) {
  105. type = WIFI_AP6181;
  106. } else if (strcmp(wifi_chip_type_string, "ap6234") == 0) {
  107. type = WIFI_AP6234;
  108. } else if (strcmp(wifi_chip_type_string, "ap6255") == 0) {
  109. type = WIFI_AP6255;
  110. } else if (strcmp(wifi_chip_type_string, "ap6256") == 0) {
  111. type = WIFI_AP6256;
  112. } else if (strcmp(wifi_chip_type_string, "ap6330") == 0) {
  113. type = WIFI_AP6330;
  114. } else if (strcmp(wifi_chip_type_string, "ap6335") == 0) {
  115. type = WIFI_AP6335;
  116. } else if (strcmp(wifi_chip_type_string, "ap6354") == 0) {
  117. type = WIFI_AP6354;
  118. } else if (strcmp(wifi_chip_type_string, "ap6441") == 0) {
  119. type = WIFI_AP6441;
  120. } else if (strcmp(wifi_chip_type_string, "ap6476") == 0) {
  121. type = WIFI_AP6476;
  122. } else if (strcmp(wifi_chip_type_string, "ap6493") == 0) {
  123. type = WIFI_AP6493;
  124. } else if (strcmp(wifi_chip_type_string, "rtl8188eu") == 0) {
  125. type = WIFI_RTL8188EU;
  126. } else if (strcmp(wifi_chip_type_string, "rtl8192du") == 0) {
  127. type = WIFI_RTL8192DU;
  128. } else if (strcmp(wifi_chip_type_string, "rtl8723as") == 0) {
  129. type = WIFI_RTL8723AS;
  130. } else if (strcmp(wifi_chip_type_string, "rtl8723bs_vq0") == 0) {
  131. type = WIFI_RTL8723BS_VQ0;
  132. } else if (strcmp(wifi_chip_type_string, "rtl8723bs") == 0) {
  133. type = WIFI_RTL8723BS;
  134. } else if (strcmp(wifi_chip_type_string, "rtl8723cs") == 0) {
  135. type = WIFI_RTL8723CS;
  136. } else if (strcmp(wifi_chip_type_string, "rtl8723ds") == 0) {
  137. type = WIFI_RTL8723DS;
  138. } else if (strcmp(wifi_chip_type_string, "rtl8723au") == 0) {
  139. type = WIFI_RTL8723AU;
  140. } else if (strcmp(wifi_chip_type_string, "rtl8723bu") == 0) {
  141. type = WIFI_RTL8723BU;
  142. } else if (strcmp(wifi_chip_type_string, "rtl8189es") == 0) {
  143. type = WIFI_RTL8189ES;
  144. } else if (strcmp(wifi_chip_type_string, "rtl8189fs") == 0) {
  145. type = WIFI_RTL8189FS;
  146. } else if (strcmp(wifi_chip_type_string, "rtl8812au") == 0) {
  147. type = WIFI_RTL8812AU;
  148. } else if (strcmp(wifi_chip_type_string, "esp8089") == 0) {
  149. type = WIFI_ESP8089;
  150. } else if (strcmp(wifi_chip_type_string, "mvl88w8977") == 0) {
  151. type = WIFI_MVL88W8977;
  152. } else if (strcmp(wifi_chip_type_string, "ssv6051") == 0) {
  153. type = WIFI_SSV6051;
  154. } else {
  155. type = WIFI_AP6210;
  156. }
  157. return type;
  158. }
  159. EXPORT_SYMBOL(get_wifi_chip_type);
  160. /***********************************************************
  161. *
  162. * Broadcom Wifi Static Memory
  163. *
  164. **********************************************************/
  165. #ifdef CONFIG_RKWIFI
  166. #define BCM_STATIC_MEMORY_SUPPORT 0
  167. #else
  168. #define BCM_STATIC_MEMORY_SUPPORT 0
  169. #endif
  170. //===========================
  171. #if BCM_STATIC_MEMORY_SUPPORT
  172. #define PREALLOC_WLAN_SEC_NUM 4
  173. #define PREALLOC_WLAN_BUF_NUM 160
  174. #define PREALLOC_WLAN_SECTION_HEADER 0
  175. #define WLAN_SKB_BUF_NUM 16
  176. #define WLAN_SECTION_SIZE_0 (12 * 1024)
  177. #define WLAN_SECTION_SIZE_1 (12 * 1024)
  178. #define WLAN_SECTION_SIZE_2 (32 * 1024)
  179. #define WLAN_SECTION_SIZE_3 (136* 1024)
  180. #define WLAN_SECTION_SIZE_4 (4 * 1024)
  181. #define WLAN_SECTION_SIZE_5 (64 * 1024)
  182. #define WLAN_SECTION_SIZE_6 (4 * 1024)
  183. #define WLAN_SECTION_SIZE_7 (4 * 1024)
  184. static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM+1];
  185. struct wifi_mem_prealloc {
  186. void *mem_ptr;
  187. unsigned long size;
  188. };
  189. static struct wifi_mem_prealloc wifi_mem_array[8] = {
  190. {NULL, (WLAN_SECTION_SIZE_0)},
  191. {NULL, (WLAN_SECTION_SIZE_1)},
  192. {NULL, (WLAN_SECTION_SIZE_2)},
  193. {NULL, (WLAN_SECTION_SIZE_3)},
  194. {NULL, (WLAN_SECTION_SIZE_4)},
  195. {NULL, (WLAN_SECTION_SIZE_5)},
  196. {NULL, (WLAN_SECTION_SIZE_6)},
  197. {NULL, (WLAN_SECTION_SIZE_7)}
  198. };
  199. static int rockchip_init_wifi_mem(void)
  200. {
  201. int i;
  202. int j;
  203. for (i = 0 ; i < WLAN_SKB_BUF_NUM ; i++) {
  204. wlan_static_skb[i] = dev_alloc_skb(
  205. ((i < (WLAN_SKB_BUF_NUM / 2)) ? (PAGE_SIZE*1) : (PAGE_SIZE*2)));
  206. if (!wlan_static_skb[i])
  207. goto err_skb_alloc;
  208. }
  209. wlan_static_skb[i] = dev_alloc_skb((PAGE_SIZE*4));
  210. if (!wlan_static_skb[i])
  211. goto err_skb_alloc;
  212. for (i = 0 ; i <= 7; i++) {
  213. wifi_mem_array[i].mem_ptr =
  214. kmalloc(wifi_mem_array[i].size, GFP_KERNEL);
  215. if (!wifi_mem_array[i].mem_ptr)
  216. goto err_mem_alloc;
  217. }
  218. return 0;
  219. err_mem_alloc:
  220. pr_err("Failed to mem_alloc for WLAN\n");
  221. for (j = 0 ; j < i ; j++)
  222. kfree(wifi_mem_array[j].mem_ptr);
  223. i = WLAN_SKB_BUF_NUM;
  224. err_skb_alloc:
  225. pr_err("Failed to skb_alloc for WLAN\n");
  226. for (j = 0 ; j < i ; j++)
  227. dev_kfree_skb(wlan_static_skb[j]);
  228. dev_kfree_skb(wlan_static_skb[j]);
  229. return -ENOMEM;
  230. }
  231. void *rockchip_mem_prealloc(int section, unsigned long size)
  232. {
  233. //printk("rockchip_mem_prealloc: section = %d, size = %d\n", section, size);
  234. if (section == PREALLOC_WLAN_SEC_NUM)
  235. return wlan_static_skb;
  236. if ((section < 0) || (section > 7))
  237. return NULL;
  238. if (wifi_mem_array[section].size < size)
  239. return NULL;
  240. return wifi_mem_array[section].mem_ptr;
  241. }
  242. #else
  243. void *rockchip_mem_prealloc(int section, unsigned long size) { return NULL;}
  244. #endif
  245. EXPORT_SYMBOL(rockchip_mem_prealloc);
  246. /**************************************************************************
  247. *
  248. * get wifi power state Func
  249. *
  250. *************************************************************************/
  251. static int wifi_power_state = 0;
  252. int rfkill_get_wifi_power_state(int *power, int *vref_ctrl_enable)
  253. {
  254. struct rfkill_wlan_data *mrfkill = g_rfkill;
  255. if (mrfkill == NULL) {
  256. LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__);
  257. return -1;
  258. }
  259. *power = wifi_power_state;
  260. return 0;
  261. }
  262. /**************************************************************************
  263. *
  264. * Wifi Power Control Func
  265. * 0 -> power off
  266. * 1 -> power on
  267. *
  268. *************************************************************************/
  269. int rockchip_wifi_power(int on)
  270. {
  271. struct rfkill_wlan_data *mrfkill = g_rfkill;
  272. struct rksdmmc_gpio *poweron, *reset;
  273. struct regulator *ldo = NULL;
  274. int power = 0;
  275. bool toggle = false;
  276. LOG("%s: %d\n", __func__, on);
  277. // if (!on && primary_sdio_host)
  278. // mmc_pwrseq_power_off(primary_sdio_host);
  279. if (mrfkill == NULL) {
  280. LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__);
  281. return -1;
  282. }
  283. if (mrfkill->pdata->wifi_power_remain && power_set_time) {
  284. LOG("%s: wifi power is setted to be remain on. skip anything to the power control", __func__);
  285. return 0;
  286. } else power_set_time++;
  287. if (!rfkill_get_bt_power_state(&power, &toggle)) {
  288. if (toggle == true && power == 1) {
  289. LOG("%s: wifi shouldn't control the power, it was enabled by BT!\n", __func__);
  290. return 0;
  291. }
  292. }
  293. if (mrfkill->pdata->mregulator.power_ctrl_by_pmu) {
  294. int ret = -1;
  295. char *ldostr;
  296. int level = mrfkill->pdata->mregulator.enable;
  297. ldostr = mrfkill->pdata->mregulator.pmu_regulator;
  298. if (ldostr == NULL) {
  299. LOG("%s: wifi power set to be controled by pmic, but which one?\n", __func__);
  300. return -1;
  301. }
  302. ldo = regulator_get(NULL, ldostr);
  303. if (ldo == NULL || IS_ERR(ldo)) {
  304. LOG("\n\n\n%s get ldo error,please mod this\n\n\n", __func__);
  305. return -1;
  306. } else {
  307. if (on == level) {
  308. regulator_set_voltage(ldo, 3000000, 3000000);
  309. LOG("%s: %s enabled\n", __func__, ldostr);
  310. ret = regulator_enable(ldo);
  311. wifi_power_state = 1;
  312. LOG("wifi turn on power.\n");
  313. } else {
  314. LOG("%s: %s disabled\n", __func__, ldostr);
  315. while (regulator_is_enabled(ldo) > 0) {
  316. ret = regulator_disable(ldo);
  317. }
  318. wifi_power_state = 0;
  319. LOG("wifi shut off power.\n");
  320. }
  321. regulator_put(ldo);
  322. msleep(100);
  323. }
  324. } else {
  325. poweron = &mrfkill->pdata->power_n;
  326. reset = &mrfkill->pdata->reset_n;
  327. if (on){
  328. if (gpio_is_valid(poweron->io)) {
  329. gpio_set_value(poweron->io, poweron->enable);
  330. msleep(500);
  331. }
  332. if (gpio_is_valid(reset->io)) {
  333. gpio_set_value(reset->io, reset->enable);
  334. msleep(100);
  335. }
  336. wifi_power_state = 1;
  337. LOG("wifi turn on power. %d\n", poweron->io);
  338. }else{
  339. if (gpio_is_valid(poweron->io)) {
  340. gpio_set_value(poweron->io, !(poweron->enable));
  341. msleep(100);
  342. }
  343. if (gpio_is_valid(reset->io)) {
  344. gpio_set_value(reset->io, !(reset->enable));
  345. }
  346. wifi_power_state = 0;
  347. LOG("wifi shut off power.\n");
  348. }
  349. }
  350. return 0;
  351. }
  352. EXPORT_SYMBOL(rockchip_wifi_power);
  353. /**************************************************************************
  354. *
  355. * Wifi Sdio Detect Func
  356. *
  357. *************************************************************************/
  358. extern int mmc_host_rescan(struct mmc_host *host, int val, int irq_type);
  359. int rockchip_wifi_set_carddetect(int val)
  360. {
  361. // return mmc_host_rescan(NULL, val, 1);
  362. return 0;
  363. }
  364. EXPORT_SYMBOL(rockchip_wifi_set_carddetect);
  365. /**************************************************************************
  366. *
  367. * Wifi Get Interrupt irq Func
  368. *
  369. *************************************************************************/
  370. int rockchip_wifi_get_oob_irq(void)
  371. {
  372. struct rfkill_wlan_data *mrfkill = g_rfkill;
  373. struct rksdmmc_gpio *wifi_int_irq;
  374. LOG("%s: Enter\n", __func__);
  375. if (mrfkill == NULL) {
  376. LOG("%s: rfkill-wlan driver has not Successful initialized\n", __func__);
  377. return -1;
  378. }
  379. wifi_int_irq = &mrfkill->pdata->wifi_int_b;
  380. if (gpio_is_valid(wifi_int_irq->io)) {
  381. return gpio_to_irq(wifi_int_irq->io);
  382. //return wifi_int_irq->io;
  383. } else {
  384. LOG("%s: wifi OOB pin isn't defined.\n", __func__);
  385. }
  386. return -1;
  387. }
  388. EXPORT_SYMBOL(rockchip_wifi_get_oob_irq);
  389. int rockchip_wifi_get_oob_irq_flag(void)
  390. {
  391. struct rfkill_wlan_data *mrfkill = g_rfkill;
  392. struct rksdmmc_gpio *wifi_int_irq;
  393. int gpio_flags = -1;
  394. if (mrfkill) {
  395. wifi_int_irq = &mrfkill->pdata->wifi_int_b;
  396. if (gpio_is_valid(wifi_int_irq->io))
  397. gpio_flags = wifi_int_irq->enable;
  398. }
  399. return gpio_flags;
  400. }
  401. EXPORT_SYMBOL(rockchip_wifi_get_oob_irq_flag);
  402. /**************************************************************************
  403. *
  404. * Wifi Reset Func
  405. *
  406. *************************************************************************/
  407. int rockchip_wifi_reset(int on)
  408. {
  409. return 0;
  410. }
  411. EXPORT_SYMBOL(rockchip_wifi_reset);
  412. /**************************************************************************
  413. *
  414. * Wifi MAC custom Func
  415. *
  416. *************************************************************************/
  417. #include <linux/etherdevice.h>
  418. #include <linux/errno.h>
  419. u8 wifi_custom_mac_addr[6] = {0,0,0,0,0,0};
  420. //#define RANDOM_ADDRESS_SAVE
  421. // static int get_wifi_addr_vendor(unsigned char *addr)
  422. // {
  423. // int ret;
  424. // int count = 5;
  425. // while (count-- > 0) {
  426. // if (is_rk_vendor_ready())
  427. // break;
  428. // /* sleep 500ms wait rk vendor driver ready */
  429. // msleep(500);
  430. // }
  431. // ret = rk_vendor_read(WIFI_MAC_ID, addr, 6);
  432. // if (ret != 6 || is_zero_ether_addr(addr)) {
  433. // LOG("%s: rk_vendor_read wifi mac address failed (%d)\n",
  434. // __func__, ret);
  435. // #ifdef CONFIG_WIFI_GENERATE_RANDOM_MAC_ADDR
  436. // random_ether_addr(addr);
  437. // LOG("%s: generate random wifi mac address: "
  438. // "%02x:%02x:%02x:%02x:%02x:%02x\n",
  439. // __func__, addr[0], addr[1], addr[2],
  440. // addr[3], addr[4], addr[5]);
  441. // ret = rk_vendor_write(WIFI_MAC_ID, addr, 6);
  442. // if (ret != 0) {
  443. // LOG("%s: rk_vendor_write"
  444. // " wifi mac address failed (%d)\n",
  445. // __func__, ret);
  446. // memset(addr, 0, 6);
  447. // return -1;
  448. // }
  449. // #else
  450. // return -1;
  451. // #endif
  452. // } else {
  453. // LOG("%s: rk_vendor_read wifi mac address: "
  454. // "%02x:%02x:%02x:%02x:%02x:%02x\n",
  455. // __func__, addr[0], addr[1], addr[2],
  456. // addr[3], addr[4], addr[5]);
  457. // }
  458. // return 0;
  459. // }
  460. int rockchip_wifi_mac_addr(unsigned char *buf)
  461. {
  462. char mac_buf[20] = {0};
  463. LOG("%s: enter.\n", __func__);
  464. // from vendor storage
  465. // if (is_zero_ether_addr(wifi_custom_mac_addr)) {
  466. // if (get_wifi_addr_vendor(wifi_custom_mac_addr) != 0)
  467. // return -1;
  468. // }
  469. sprintf(mac_buf, "%02x:%02x:%02x:%02x:%02x:%02x",
  470. wifi_custom_mac_addr[0], wifi_custom_mac_addr[1],
  471. wifi_custom_mac_addr[2], wifi_custom_mac_addr[3],
  472. wifi_custom_mac_addr[4], wifi_custom_mac_addr[5]);
  473. LOG("falsh wifi_custom_mac_addr=[%s]\n", mac_buf);
  474. if (is_valid_ether_addr(wifi_custom_mac_addr)) {
  475. if (!strncmp(wifi_chip_type_string, "rtl", 3))
  476. wifi_custom_mac_addr[0] &= ~0x2; // for p2p
  477. } else {
  478. LOG("This mac address is not valid, ignored...\n");
  479. return -1;
  480. }
  481. memcpy(buf, wifi_custom_mac_addr, 6);
  482. return 0;
  483. }
  484. EXPORT_SYMBOL(rockchip_wifi_mac_addr);
  485. /**************************************************************************
  486. *
  487. * wifi get country code func
  488. *
  489. *************************************************************************/
  490. struct cntry_locales_custom {
  491. char iso_abbrev[4]; /* ISO 3166-1 country abbreviation */
  492. char custom_locale[4]; /* Custom firmware locale */
  493. int custom_locale_rev; /* Custom local revisin default -1 */
  494. };
  495. static struct cntry_locales_custom country_cloc;
  496. void *rockchip_wifi_country_code(char *ccode)
  497. {
  498. struct cntry_locales_custom *mcloc;
  499. LOG("%s: set country code [%s]\n", __func__, ccode);
  500. mcloc = &country_cloc;
  501. memcpy(mcloc->custom_locale, ccode, 4);
  502. mcloc->custom_locale_rev = 0;
  503. return mcloc;
  504. }
  505. EXPORT_SYMBOL(rockchip_wifi_country_code);
  506. /**************************************************************************/
  507. static 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. sprintf(gpio->name, "%s_%s", prefix, name);
  512. ret = gpio_request(gpio->io, gpio->name);
  513. if (ret) {
  514. LOG("Failed to get %s gpio.\n", gpio->name);
  515. return -1;
  516. }
  517. }
  518. return 0;
  519. }
  520. #ifdef CONFIG_OF
  521. static int wlan_platdata_parse_dt(struct device *dev,
  522. struct rksdmmc_gpio_wifi_moudle *data)
  523. {
  524. struct device_node *node = dev->of_node;
  525. const char *strings;
  526. u32 value;
  527. int gpio,ret;
  528. enum of_gpio_flags flags;
  529. u32 ext_clk_value = 0;
  530. if (!node)
  531. return -ENODEV;
  532. memset(data, 0, sizeof(*data));
  533. #ifdef CONFIG_MFD_SYSCON
  534. data->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
  535. if (IS_ERR(data->grf)) {
  536. LOG("can't find rockchip,grf property\n");
  537. //return -1;
  538. }
  539. #endif
  540. ret = of_property_read_string(node, "wifi_chip_type", &strings);
  541. if (ret) {
  542. LOG("%s: Can not read wifi_chip_type, set default to rkwifi.\n", __func__);
  543. strcpy(wifi_chip_type_string, "rkwifi");
  544. } else {
  545. strcpy(wifi_chip_type_string, strings);
  546. }
  547. LOG("%s: wifi_chip_type = %s\n", __func__, wifi_chip_type_string);
  548. if (of_find_property(node, "keep_wifi_power_on", NULL)) {
  549. data->wifi_power_remain = true;
  550. LOG("%s: wifi power will enabled while kernel starting and keep on.\n", __func__);
  551. } else {
  552. data->wifi_power_remain = false;
  553. LOG("%s: enable wifi power control.\n", __func__);
  554. }
  555. if (of_find_property(node, "power_ctrl_by_pmu", NULL)) {
  556. data->mregulator.power_ctrl_by_pmu = true;
  557. ret = of_property_read_string(node, "power_pmu_regulator", &strings);
  558. if (ret) {
  559. LOG("%s: Can not read property: power_pmu_regulator.\n", __func__);
  560. data->mregulator.power_ctrl_by_pmu = false;
  561. } else {
  562. LOG("%s: wifi power controled by pmu(%s).\n", __func__, strings);
  563. sprintf(data->mregulator.pmu_regulator, "%s", strings);
  564. }
  565. ret = of_property_read_u32(node, "power_pmu_enable_level", &value);
  566. if (ret) {
  567. LOG("%s: Can not read property: power_pmu_enable_level.\n", __func__);
  568. data->mregulator.power_ctrl_by_pmu = false;
  569. } else {
  570. LOG("%s: wifi power controled by pmu(level = %s).\n", __func__, (value == 1)?"HIGH":"LOW");
  571. data->mregulator.enable = value;
  572. }
  573. } else {
  574. data->mregulator.power_ctrl_by_pmu = false;
  575. LOG("%s: wifi power controled by gpio.\n", __func__);
  576. gpio = of_get_named_gpio_flags(node, "WIFI,poweren_gpio", 0, &flags);
  577. if (gpio_is_valid(gpio)){
  578. data->power_n.io = gpio;
  579. data->power_n.enable = (flags == GPIO_ACTIVE_HIGH)? 1:0;
  580. LOG("%s: get property: WIFI,poweren_gpio = %d, flags = %d.\n", __func__, gpio, flags);
  581. } else data->power_n.io = -1;
  582. gpio = of_get_named_gpio_flags(node, "WIFI,vbat_gpio", 0, &flags);
  583. if (gpio_is_valid(gpio)) {
  584. data->vbat_n.io = gpio;
  585. data->vbat_n.enable = (flags == GPIO_ACTIVE_HIGH) ? 1:0;
  586. LOG("%s: get property: WIFI,vbat_gpio = %d, flags = %d.\n", __func__, gpio, flags);
  587. } else {
  588. data->vbat_n.io = -1;
  589. }
  590. gpio = of_get_named_gpio_flags(node, "WIFI,reset_gpio", 0, &flags);
  591. if (gpio_is_valid(gpio)){
  592. data->reset_n.io = gpio;
  593. data->reset_n.enable = (flags == GPIO_ACTIVE_HIGH)? 1:0;
  594. LOG("%s: get property: WIFI,reset_gpio = %d, flags = %d.\n", __func__, gpio, flags);
  595. } else data->reset_n.io = -1;
  596. gpio = of_get_named_gpio_flags(node, "WIFI,host_wake_irq", 0, &flags);
  597. if (gpio_is_valid(gpio)){
  598. data->wifi_int_b.io = gpio;
  599. data->wifi_int_b.enable = !flags;
  600. LOG("%s: get property: WIFI,host_wake_irq = %d, flags = %d.\n", __func__, gpio, flags);
  601. } else data->wifi_int_b.io = -1;
  602. }
  603. data->ext_clk = devm_clk_get(dev, "clk_wifi");
  604. if (IS_ERR(data->ext_clk)) {
  605. LOG("%s: The ref_wifi_clk not found !\n", __func__);
  606. } else {
  607. of_property_read_u32(node, "ref-clock-frequency",
  608. &ext_clk_value);
  609. if (ext_clk_value > 0) {
  610. ret = clk_set_rate(data->ext_clk, ext_clk_value);
  611. if (ret)
  612. LOG("%s: set ref clk error!\n", __func__);
  613. ret = clk_prepare_enable(data->ext_clk);
  614. if (ret)
  615. LOG("%s: enable ref clk error!\n", __func__);
  616. /* WIFI clock (REF_CLKOUT) output enable.
  617. * 1'b0: drive disable
  618. * 1'b1: output enable
  619. */
  620. if (of_machine_is_compatible("rockchip,rk3308"))
  621. regmap_write(data->grf, 0x0314, 0x00020002);
  622. }
  623. }
  624. return 0;
  625. }
  626. #endif //CONFIG_OF
  627. #if defined(CONFIG_HAS_EARLYSUSPEND)
  628. #include <linux/earlysuspend.h>
  629. static void wlan_early_suspend(struct early_suspend *h)
  630. {
  631. LOG("%s :enter\n", __func__);
  632. return;
  633. }
  634. static void wlan_late_resume(struct early_suspend *h)
  635. {
  636. LOG("%s :enter\n", __func__);
  637. return;
  638. }
  639. struct early_suspend wlan_early_suspend {
  640. .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
  641. .suspend = wlan_early_suspend;
  642. .resume = wlan_late_resume;
  643. }
  644. #endif
  645. static void rfkill_wlan_early_suspend(void)
  646. {
  647. //LOG("%s :enter\n", __func__);
  648. return;
  649. }
  650. static void rfkill_wlan_later_resume(void)
  651. {
  652. //LOG("%s :enter\n", __func__);
  653. return;
  654. }
  655. static int rfkill_wlan_fb_event_notify(struct notifier_block *self,
  656. unsigned long action, void *data)
  657. {
  658. struct fb_event *event = data;
  659. int blank_mode = *((int *)event->data);
  660. switch (blank_mode) {
  661. case FB_BLANK_UNBLANK:
  662. rfkill_wlan_later_resume();
  663. break;
  664. case FB_BLANK_NORMAL:
  665. rfkill_wlan_early_suspend();
  666. break;
  667. default:
  668. rfkill_wlan_early_suspend();
  669. break;
  670. }
  671. return 0;
  672. }
  673. static struct notifier_block rfkill_wlan_fb_notifier = {
  674. .notifier_call = rfkill_wlan_fb_event_notify,
  675. };
  676. static int rfkill_wlan_probe(struct platform_device *pdev)
  677. {
  678. struct rfkill_wlan_data *rfkill;
  679. struct rksdmmc_gpio_wifi_moudle *pdata = pdev->dev.platform_data;
  680. int ret = -1;
  681. LOG("Enter %s\n", __func__);
  682. if (!pdata) {
  683. #ifdef CONFIG_OF
  684. pdata = kzalloc(sizeof(struct rksdmmc_gpio_wifi_moudle), GFP_KERNEL);
  685. if (!pdata)
  686. return -ENOMEM;
  687. ret = wlan_platdata_parse_dt(&pdev->dev, pdata);
  688. if (ret < 0) {
  689. #endif
  690. LOG("%s: No platform data specified\n", __func__);
  691. return ret;
  692. #ifdef CONFIG_OF
  693. }
  694. #endif
  695. }
  696. rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL);
  697. if (!rfkill)
  698. goto rfkill_alloc_fail;
  699. rfkill->pdata = pdata;
  700. g_rfkill = rfkill;
  701. LOG("%s: init gpio\n", __func__);
  702. if (!pdata->mregulator.power_ctrl_by_pmu) {
  703. ret = rfkill_rk_setup_gpio(&pdata->vbat_n, wlan_name, "wlan_vbat");
  704. if (ret)
  705. goto fail_alloc;
  706. ret = rfkill_rk_setup_gpio(&pdata->power_n, wlan_name, "wlan_poweren");
  707. if (ret)
  708. goto fail_alloc;
  709. ret = rfkill_rk_setup_gpio(&pdata->reset_n, wlan_name, "wlan_reset");
  710. if (ret)
  711. goto fail_alloc;
  712. }
  713. // wake_lock_init(&(rfkill->wlan_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_wlan_wake");
  714. if (gpio_is_valid(pdata->vbat_n.io)) {
  715. gpio_direction_output(pdata->vbat_n.io, pdata->vbat_n.enable);
  716. }
  717. // Turn off wifi power as default
  718. if (gpio_is_valid(pdata->power_n.io))
  719. {
  720. gpio_direction_output(pdata->power_n.io, !pdata->power_n.enable);
  721. }
  722. if (pdata->wifi_power_remain)
  723. {
  724. rockchip_wifi_power(1);
  725. }
  726. #if BCM_STATIC_MEMORY_SUPPORT
  727. rockchip_init_wifi_mem();
  728. #endif
  729. #if defined(CONFIG_HAS_EARLYSUSPEND)
  730. register_early_suspend(wlan_early_suspend);
  731. #endif
  732. fb_register_client(&rfkill_wlan_fb_notifier);
  733. LOG("Exit %s\n", __func__);
  734. return 0;
  735. fail_alloc:
  736. kfree(rfkill);
  737. rfkill_alloc_fail:
  738. kfree(pdata);
  739. g_rfkill = NULL;
  740. return ret;
  741. }
  742. static int rfkill_wlan_remove(struct platform_device *pdev)
  743. {
  744. struct rfkill_wlan_data *rfkill = platform_get_drvdata(pdev);
  745. LOG("Enter %s\n", __func__);
  746. // wake_lock_destroy(&rfkill->wlan_irq_wl);
  747. fb_unregister_client(&rfkill_wlan_fb_notifier);
  748. if (gpio_is_valid(rfkill->pdata->power_n.io))
  749. gpio_free(rfkill->pdata->power_n.io);
  750. if (gpio_is_valid(rfkill->pdata->reset_n.io))
  751. gpio_free(rfkill->pdata->reset_n.io);
  752. // if (gpio_is_valid(rfkill->pdata->vddio.io))
  753. // gpio_free(rfkill->pdata->vddio.io);
  754. //
  755. // if (gpio_is_valid(rfkill->pdata->bgf_int_b.io))
  756. // gpio_free(rfkill->pdata->bgf_int_b.io);
  757. //
  758. // if (gpio_is_valid(rfkill->pdata->gps_sync.io))
  759. // gpio_free(rfkill->pdata->gps_sync.io);
  760. //
  761. // if (gpio_is_valid(rfkill->pdata->ANTSEL2.io))
  762. // gpio_free(rfkill->pdata->ANTSEL2.io);
  763. //
  764. // if (gpio_is_valid(rfkill->pdata->ANTSEL3.io))
  765. // gpio_free(rfkill->pdata->ANTSEL3.io);
  766. //
  767. // if (gpio_is_valid(rfkill->pdata->GPS_LAN.io))
  768. // gpio_free(rfkill->pdata->GPS_LAN.io);
  769. kfree(rfkill);
  770. g_rfkill = NULL;
  771. return 0;
  772. }
  773. static int rfkill_wlan_suspend(struct platform_device *pdev, pm_message_t state)
  774. {
  775. LOG("Enter %s\n", __func__);
  776. return 0;
  777. }
  778. static int rfkill_wlan_resume(struct platform_device *pdev)
  779. {
  780. LOG("Enter %s\n", __func__);
  781. return 0;
  782. }
  783. #ifdef CONFIG_OF
  784. static struct of_device_id wlan_platdata_of_match[] = {
  785. { .compatible = "wlan-platdata" },
  786. { }
  787. };
  788. MODULE_DEVICE_TABLE(of, wlan_platdata_of_match);
  789. #endif //CONFIG_OF
  790. static struct platform_driver rfkill_wlan_driver = {
  791. .probe = rfkill_wlan_probe,
  792. .remove = rfkill_wlan_remove,
  793. .suspend = rfkill_wlan_suspend,
  794. .resume = rfkill_wlan_resume,
  795. .driver = {
  796. .name = "wlan-platdata",
  797. .owner = THIS_MODULE,
  798. .of_match_table = of_match_ptr(wlan_platdata_of_match),
  799. },
  800. };
  801. static int __init rfkill_wlan_init(void)
  802. {
  803. LOG("Enter %s\n", __func__);
  804. return platform_driver_register(&rfkill_wlan_driver);
  805. }
  806. static void __exit rfkill_wlan_exit(void)
  807. {
  808. LOG("Enter %s\n", __func__);
  809. platform_driver_unregister(&rfkill_wlan_driver);
  810. }
  811. module_init(rfkill_wlan_init);
  812. module_exit(rfkill_wlan_exit);
  813. MODULE_DESCRIPTION("rock-chips rfkill for wifi v0.1");
  814. MODULE_AUTHOR("gwl@rock-chips.com");
  815. MODULE_LICENSE("GPL");