blob: ed5c36f0e82a0a2b3c33f105861c781e28db1cda [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * rfkill power contorl for wlan/bt on ASR platform
3 *
4 * Copyright (C) 2018 ASR, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/debugfs.h>
23#include <linux/device.h>
24
25#include <linux/err.h>
26#include <linux/slab.h>
27#include <linux/delay.h>
28#include <linux/platform_device.h>
29#include <linux/mmc/host.h>
30#include <linux/platform_data/asr_sdhci.h>
31#include <linux/pm.h>
32#include <linux/pm_runtime.h>
33#include <linux/suspend.h>
34#include <linux/clk.h>
35#include <linux/of_device.h>
36#include <linux/of_gpio.h>
37#include <linux/of_platform.h>
38#include <linux/edge_wakeup_mmp.h>
39#include <linux/regulator/consumer.h>
40#include <linux/asr_rfkill.h>
41
42#include "../mmc/host/sdhci.h"
43
44#define ASR_DEV_NAME "asr-rfkill"
45
46/*
47 * Define optimum max current to 200mA while min current to 0.
48 * They will be handled in regulator_set_optimum_mode and
49 * enable or disable the regulator sleep mode accordingly.
50 */
51#define OPTIMUM_MAX_CURRENT 200000
52#define OPTIMUM_MIN_CURRENT 0
53
54#define ASR_MAX_SDIO_HOST 2
55static int sdio_rfkill_id;
56struct asr_rfkill_platform_data *rfkill_plat[ASR_MAX_SDIO_HOST];
57static DEFINE_MUTEX(asr_pwr_mutex);
58
59static void wlan_edge_wakeup(int irq, void *p_rsv)
60{
61 pr_debug("wlan_edge_wakeup event +++++\n");
62}
63
64static void asr_rfkill_platform_data_init(
65 struct asr_rfkill_platform_data *pdata)
66{
67 /* all intems are invalid just after alloc */
68 pdata->gpio_power_down = -1;
69 pdata->gpio_reset = -1;
70 pdata->gpio_edge_wakeup = -1;
71 pdata->gpio_3v3_en = -1;
72 pdata->gpio_1v8_en = -1;
73 pdata->gpio_wakeup_device = -1;
74
75 pdata->wib_3v3 = NULL;
76 pdata->wib_1v8 = NULL;
77 pdata->wib_sdio_1v8 = NULL;
78
79 /*for issue mmc card_detection interrupt */
80 pdata->mmc = NULL;
81
82 /* power status, unknown status at first */
83 pdata->is_on = -1;
84}
85
86static struct asr_rfkill_platform_data
87 *asr_rfkill_platform_data_alloc(struct platform_device *pdev)
88{
89 struct asr_rfkill_platform_data *pdata;
90
91 /* create a new one and init it */
92 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
93 if (pdata) {
94 asr_rfkill_platform_data_init(pdata);
95 return pdata;
96 }
97
98 return NULL;
99}
100
101/*
102 * For asr_wlan device, there are two power: supply 1v8 and 3v3
103 *
104 * If 18v and 3v3 can't be both disabled during power off stage,
105 * it is recommand to keep them both on and disable pd-gpio only
106 * TODO: add flags to check gpio active level
107 */
108static int asr_1v8_3v3_control(struct asr_rfkill_platform_data *pdata, int on)
109{
110 int gpio_3v3_en = pdata->gpio_3v3_en;
111 int gpio_1v8_en = pdata->gpio_1v8_en;
112
113 if (gpio_3v3_en >= 0) {
114 if (gpio_request(gpio_3v3_en, "asr_wlan 3v3 on")) {
115 pr_info("gpio %d request failed\n", gpio_3v3_en);
116 return -1;
117 }
118 }
119
120 if (gpio_1v8_en >= 0) {
121 if (gpio_request(gpio_1v8_en, "asr_wlan 1v8 on")) {
122 pr_info("gpio %d request failed\n", gpio_1v8_en);
123 if (gpio_3v3_en >= 0)
124 gpio_free(gpio_3v3_en);
125 return -1;
126 }
127 }
128
129 if (on) {
130 if (gpio_1v8_en >= 0)
131 gpio_direction_output(gpio_1v8_en, 1);
132 if (gpio_3v3_en >= 0)
133 gpio_direction_output(gpio_3v3_en, 1);
134 if (pdata->wib_3v3) {
135 if (regulator_set_voltage(pdata->wib_3v3, 3300000, 3300000))
136 pr_err("fail to set regulator wib_3v3 to 3.3v\n");
137
138 if (!regulator_is_enabled(pdata->wib_3v3) &&
139 regulator_enable(pdata->wib_3v3))
140 pr_err("fail to enable regulator wib_3v3\n");
141 }
142 if (pdata->wib_1v8) {
143 if (regulator_set_voltage(pdata->wib_1v8, 1800000, 1800000))
144 pr_err("fail to set regulator wib_1v8 to 1.8v\n");
145
146 if (!regulator_is_enabled(pdata->wib_1v8) &&
147 regulator_enable(pdata->wib_1v8))
148 pr_err("fail to enable regulator wib_1v8\n");
149 }
150 if (pdata->wib_sdio_1v8) {
151 if (regulator_set_voltage(pdata->wib_sdio_1v8, 1800000, 1800000))
152 pr_err("fail to set regulator wib_sdio_1v8 to 1.8v\n");
153
154 if (!regulator_is_enabled(pdata->wib_sdio_1v8) &&
155 regulator_enable(pdata->wib_sdio_1v8))
156 pr_err("fail to enable regulator wib_sdio_1v8\n");
157 }
158 } else {
159 if (gpio_1v8_en >= 0)
160 gpio_direction_output(gpio_1v8_en, 0);
161
162 if (gpio_3v3_en >= 0)
163 gpio_direction_output(gpio_3v3_en, 0);
164
165 if (pdata->wib_3v3) {
166 if (regulator_is_enabled(pdata->wib_3v3) &&
167 regulator_disable(pdata->wib_3v3))
168 pr_err("fail to disable regulator wib_3v3\n");
169
170 }
171 if (pdata->wib_1v8) {
172 if (regulator_is_enabled(pdata->wib_1v8) &&
173 regulator_disable(pdata->wib_1v8))
174 pr_err("fail to disable regulator wib_1v8\n");
175 }
176 if (pdata->wib_sdio_1v8) {
177 if (regulator_is_enabled(pdata->wib_sdio_1v8) &&
178 regulator_disable(pdata->wib_sdio_1v8))
179 pr_err("fail to disable regulator wib_sdio_1v8\n");
180 }
181 }
182
183 if (gpio_3v3_en >= 0)
184 gpio_free(gpio_3v3_en);
185 if (gpio_1v8_en >= 0)
186 gpio_free(gpio_1v8_en);
187
188 return 0;
189}
190/*
191 * Power on/off asr_wlan by control GPIO or regulator
192 * TODO: fine tune the function if need, like adding regulator
193 * support
194 *
195 */
196static int asr_pwr_ctrl(struct asr_rfkill_platform_data *pdata, int on)
197{
198 int gpio_power_down = pdata->gpio_power_down;
199 int gpio_reset = pdata->gpio_reset;
200 int host_wakeup_wlan_gpio = pdata->gpio_wakeup_device;
201 int ret = 0;
202
203 pr_info("%s(%s): on=%d\n", __func__, mmc_hostname(pdata->mmc), on);
204
205 if (gpio_power_down >= 0) {
206 if (gpio_request(gpio_power_down, "asr_wlan power down")) {
207 pr_info("gpio %d request failed\n", gpio_power_down);
208 return -1;
209 }
210 }
211
212 if (gpio_reset >= 0) {
213 if (gpio_request(gpio_reset, "asr_wlan reset")) {
214 pr_info("gpio %d request failed\n", gpio_reset);
215 ret = -1;
216 goto err_reset;
217 }
218 }
219
220 if (host_wakeup_wlan_gpio >= 0) {
221 if (gpio_request(host_wakeup_wlan_gpio, "asr_wlan host wakeup")) {
222 pr_info("gpio %d request failed\n", host_wakeup_wlan_gpio);
223 ret = -1;
224 goto err_wakeup;
225 }
226 }
227
228 if (on) {
229 if (host_wakeup_wlan_gpio >= 0) {
230 msleep(1);
231 gpio_direction_output(host_wakeup_wlan_gpio, 0);
232 msleep(1);
233 }
234
235 asr_1v8_3v3_control(pdata, 1);
236 if (gpio_reset >= 0) {
237 gpio_direction_output(gpio_reset, 0);
238 msleep(1);
239 gpio_direction_output(gpio_reset, 1);
240 }
241 if (gpio_power_down >= 0) {
242 msleep(1);
243 gpio_direction_output(gpio_power_down, 1);
244 }
245
246 msleep(10);
247 } else {
248 if (gpio_power_down >= 0)
249 gpio_direction_output(gpio_power_down, 0);
250
251 if (gpio_reset >= 0)
252 gpio_direction_output(gpio_reset, 0);
253
254 asr_1v8_3v3_control(pdata, 0);
255 }
256
257 if (host_wakeup_wlan_gpio >= 0)
258 gpio_free(host_wakeup_wlan_gpio);
259 err_wakeup:
260 if (gpio_reset >= 0)
261 gpio_free(gpio_reset);
262 err_reset:
263 if (gpio_power_down >= 0)
264 gpio_free(gpio_power_down);
265
266 return 0;
267}
268
269static int asr_trigger_mmc_detect(struct mmc_host *host)
270{
271 unsigned long timeout = msecs_to_jiffies(10 * 1000); //HoopoeL need more than 5seconds cost by rf calibration
272 unsigned long ret = 0;
273 unsigned long flags;
274 int retry = 2;
275
276 BUG_ON(!host);
277
278 while (retry--) {
279 spin_lock_irqsave(&host->lock, flags);
280 host->rescan_entered = 0;
281 spin_unlock_irqrestore(&host->lock, flags);
282
283 ret = mmc_detect_change_sync(host, msecs_to_jiffies(10),
284 timeout);
285 if (!ret)
286 pr_warn("mmc detect has taken %u ms,something wrong\n",
287 jiffies_to_msecs(timeout));
288
289 if (host->card)
290 return 0;
291
292 pr_info("Retry mmc detection\n");
293 }
294
295 return -EBUSY;
296}
297
298static int asr_pwr_on(struct asr_rfkill_platform_data *pdata)
299{
300 int ret = 0;
301 struct platform_device *pdev;
302 struct asr_sdhci_platdata *sdhci_pdata;
303 struct sdhci_host *host;
304
305 if (pdata->is_on)
306 return 0;
307
308 if (!pdata->mmc)
309 return -EINVAL;
310
311 pr_info("asr_wlan(%s) set_power on start\n", mmc_hostname(pdata->mmc));
312
313 pdev = to_platform_device(mmc_dev(pdata->mmc));
314 sdhci_pdata = pdev->dev.platform_data;
315
316 host = mmc_priv(pdata->mmc);
317
318 if (pdata->set_power)
319 pdata->set_power(1);
320
321 /*
322 * As we known, if we want to support Card Interrupt well, SDIO Host's
323 * Main Source CLK should be free running.
324 *
325 * But if PM Runtime is enabled, the host's RPM callback may dynamic
326 * on/off the SDIO Host's SRC CLK
327 *
328 * Here we call clk_prepare_enable to make sure Source Clock will not
329 * be disabled untill is called again
330 *
331 */
332
333 /* First: power up asr_wlan device */
334 asr_pwr_ctrl(pdata, 1);
335
336 /* Second: check whether sdio device can be detected */
337 if (pdata->mmc) {
338 ret = asr_trigger_mmc_detect(pdata->mmc);
339 if (ret)
340 pr_err("%s: fail to detect SDIO device\n",
341 mmc_hostname(pdata->mmc));
342 else
343 pr_info("%s: succeed to detect SDIO device\n",
344 mmc_hostname(pdata->mmc));
345 }
346
347 /* Last: save power on status after detection */
348 if (!ret) {
349 pdata->is_on = 1;
350
351 if (pdata->gpio_edge_wakeup >= 0) {
352 request_mfp_edge_wakeup(pdata->gpio_edge_wakeup,
353 wlan_edge_wakeup, NULL, pdata->mmc->parent);
354 }
355
356 if (pdata->pinctrl && pdata->pin_on)
357 pinctrl_select_state(pdata->pinctrl, pdata->pin_on);
358 } else {
359 pdata->is_on = 0;
360
361 /* roll back if fail */
362 asr_pwr_ctrl(pdata, 0);
363
364 if (pdata->set_power)
365 pdata->set_power(0);
366
367 if (pdata->pinctrl && pdata->pin_off)
368 pinctrl_select_state(pdata->pinctrl, pdata->pin_off);
369 }
370
371 pr_info("asr_wlan(%s) set_power on end\n", mmc_hostname(pdata->mmc));
372 return ret;
373}
374
375static int asr_pwr_off(struct asr_rfkill_platform_data *pdata)
376{
377 int ret = 0;
378 struct sdhci_host *host;
379 struct platform_device *pdev;
380 struct asr_sdhci_platdata *sdhci_pdata;
381
382 if (!pdata->is_on)
383 return 0;
384
385 if (!pdata->mmc)
386 return -EINVAL;
387
388 pr_info("asr_wlan(%s) set_power off start\n", mmc_hostname(pdata->mmc));
389
390 host = mmc_priv(pdata->mmc);
391
392 pdev = to_platform_device(mmc_dev(pdata->mmc));
393 sdhci_pdata = pdev->dev.platform_data;
394
395 /* First: tell SDIO bus the device will be power off */
396 if (host->mmc && host->mmc->card)
397 mmc_disable_sdio(host->mmc);
398
399 /* Second: power off asr_wlan device */
400 asr_pwr_ctrl(pdata, 0);
401
402 if (pdata->pinctrl && pdata->pin_off)
403 pinctrl_select_state(pdata->pinctrl, pdata->pin_off);
404
405 /* TODO: check sdio device can't be detected indeed */
406
407 /*
408 * Last: update the status
409 */
410
411 if (pdata->gpio_edge_wakeup >= 0)
412 remove_mfp_edge_wakeup(pdata->gpio_edge_wakeup);
413
414 if (pdata->set_power)
415 pdata->set_power(0);
416 pdata->is_on = 0;
417
418 pr_info("asr_wlan(%s) set_power off end\n", mmc_hostname(pdata->mmc));
419 return ret;
420}
421
422int asr_sdio_card_enable(int pwr_ctrl)
423{
424 struct asr_rfkill_platform_data *pdata;
425 int i;
426
427 mutex_lock(&asr_pwr_mutex);
428 for (i = 0; i < ASR_MAX_SDIO_HOST; i++) {
429 pdata = rfkill_plat[i];
430 if (pdata) {
431 if (pwr_ctrl)
432 asr_pwr_on(pdata);
433 else
434 asr_pwr_off(pdata);
435 }
436 }
437 mutex_unlock(&asr_pwr_mutex);
438
439 return 0;
440}
441EXPORT_SYMBOL(asr_sdio_card_enable);
442
443static ssize_t asr_pwr_show(struct device *dev,
444 struct device_attribute *attr, char *buf)
445{
446 int len = 0;
447 struct asr_rfkill_platform_data *pdata = dev->platform_data;
448
449 mutex_lock(&asr_pwr_mutex);
450
451 len = sprintf(buf, "asr_wlan(%s) Device is power %s\n",
452 mmc_hostname(pdata->mmc), pdata->is_on ? "on" : "off");
453
454 mutex_unlock(&asr_pwr_mutex);
455
456 return (ssize_t)len;
457}
458
459static ssize_t asr_pwr_store(struct device *dev,
460 struct device_attribute *attr, const char *buf, size_t size)
461{
462 int pwr_ctrl;
463 int valid_ctrl = 0;
464 struct asr_rfkill_platform_data *pdata = dev->platform_data;
465
466 mutex_lock(&asr_pwr_mutex);
467
468 if (sscanf(buf, "%d", &pwr_ctrl) == 1) {
469 if ((pwr_ctrl == 1) || (pwr_ctrl == 0))
470 valid_ctrl = 1;
471 }
472
473 if (valid_ctrl != 1) {
474 pr_err("Please input valid ctrl: 0: Close, 1: Open\n");
475 mutex_unlock(&asr_pwr_mutex);
476 return size;
477 }
478
479 if (pwr_ctrl)
480 asr_pwr_on(pdata);
481 else
482 asr_pwr_off(pdata);
483
484 pr_info("Now asr_wlan(%s) Device is power %s\n",
485 mmc_hostname(pdata->mmc), pdata->is_on ? "on" : "off");
486
487 mutex_unlock(&asr_pwr_mutex);
488
489 return size;
490}
491
492static DEVICE_ATTR(pwr_ctrl, S_IRUGO | S_IWUSR, asr_pwr_show, asr_pwr_store);
493
494#ifdef CONFIG_OF
495static const struct of_device_id asr_rfkill_of_match[] = {
496 {
497 .compatible = "asr,asr-rfkill",
498 },
499 {},
500};
501
502MODULE_DEVICE_TABLE(of, asr_rfkill_of_match);
503
504static int asr_rfkill_probe_dt(struct platform_device *pdev)
505{
506 struct device_node *np = pdev->dev.of_node, *sdh_np;
507 struct asr_rfkill_platform_data *pdata = pdev->dev.platform_data;
508 struct platform_device *sdh_pdev;
509 struct sdhci_host *host;
510 int sdh_phandle, gpio;
511 struct regulator *wib_3v3, *wib_1v8, *wib_sdio_1v8;
512
513 /* Get PD/RST pins status */
514 pdata->pinctrl = devm_pinctrl_get(&pdev->dev);
515 if (IS_ERR(pdata->pinctrl)) {
516 pdata->pinctrl = NULL;
517 dev_warn(&pdev->dev, "could not get PD/RST pinctrl.\n");
518 } else {
519 pdata->pin_off = pinctrl_lookup_state(pdata->pinctrl, "off");
520 if (IS_ERR(pdata->pin_off)) {
521 pdata->pin_off = NULL;
522 dev_err(&pdev->dev, "could not get off pinstate.\n");
523 }
524
525 pdata->pin_on = pinctrl_lookup_state(pdata->pinctrl, "on");
526 if (IS_ERR(pdata->pin_on)) {
527 pdata->pin_on = NULL;
528 dev_err(&pdev->dev, "could not get on pinstate.\n");
529 }
530 }
531
532 if (pdata->pinctrl && pdata->pin_off)
533 pinctrl_select_state(pdata->pinctrl, pdata->pin_off);
534
535 if (of_property_read_u32(np, "sd-host", &sdh_phandle)) {
536 dev_err(&pdev->dev, "failed to find sd-host in dt\n");
537 return -1;
538 }
539
540 /* we've got the phandle for sdh */
541 sdh_np = of_find_node_by_phandle(sdh_phandle);
542 if (unlikely(IS_ERR(sdh_np))) {
543 dev_err(&pdev->dev, "failed to find device_node for sdh\n");
544 return -1;
545 }
546
547 sdh_pdev = of_find_device_by_node(sdh_np);
548 if (unlikely(IS_ERR(sdh_pdev))) {
549 dev_err(&pdev->dev, "failed to find platform_device for sdh\n");
550 return -1;
551 }
552
553 /* sdh_pdev->dev->driver_data was set as sdhci_host in sdhci driver */
554 host = platform_get_drvdata(sdh_pdev);
555
556 /*
557 * If we cannot find host, it's because sdh device is not registered
558 * yet. Probe again later.
559 */
560 if (!host)
561 return -EPROBE_DEFER;
562
563 pdata->mmc = host->mmc;
564 if (sdio_rfkill_id >= ASR_MAX_SDIO_HOST)
565 dev_warn(&pdev->dev, "exceed max sdio host number\n");
566 else
567 rfkill_plat[sdio_rfkill_id++] = pdata;
568
569 /* get gpios from dt */
570 gpio = of_get_named_gpio(np, "edge-wakeup-gpio", 0);
571 if (unlikely(gpio < 0)) {
572 dev_warn(&pdev->dev, "edge-wakeup-gpio undefined\n");
573 pdata->gpio_edge_wakeup = -1;
574 } else {
575 pdata->gpio_edge_wakeup = gpio;
576 }
577
578 gpio = of_get_named_gpio(np, "pd-gpio", 0);
579 if (unlikely(gpio < 0)) {
580 dev_err(&pdev->dev, "pd-gpio undefined\n");
581 pdata->gpio_power_down = -1;
582 } else {
583 pdata->gpio_power_down = gpio;
584 }
585
586 gpio = of_get_named_gpio(np, "rst-gpio", 0);
587 if (unlikely(gpio < 0)) {
588 printk(KERN_DEBUG "rst-gpio undefined\n");
589 pdata->gpio_reset = -1;
590 } else {
591 pdata->gpio_reset = gpio;
592 }
593
594 gpio = of_get_named_gpio(np, "3v3-ldo-gpio", 0);
595 if (unlikely(gpio < 0)) {
596 printk(KERN_DEBUG "3v3-ldo-gpio undefined\n");
597 pdata->gpio_3v3_en = -1;
598 } else {
599 pdata->gpio_3v3_en = gpio;
600 }
601
602 gpio = of_get_named_gpio(np, "1v8-ldo-gpio", 0);
603 if (unlikely(gpio < 0)) {
604 printk(KERN_DEBUG "1v8-ldo-gpio undefined\n");
605 pdata->gpio_1v8_en = -1;
606 } else {
607 pdata->gpio_1v8_en = gpio;
608 }
609
610 wib_3v3 = regulator_get_optional(&pdev->dev, "wib_3v3");
611 if (IS_ERR_OR_NULL(wib_3v3))
612 printk(KERN_DEBUG "%s: regulator wib_3v3 not found\n", __func__);
613 else
614 pdata->wib_3v3 = wib_3v3;
615
616 wib_1v8 = regulator_get_optional(&pdev->dev, "wib_1v8");
617 if (IS_ERR_OR_NULL(wib_1v8))
618 printk(KERN_DEBUG "%s: regulator wib_1v8 not found\n", __func__);
619 else
620 pdata->wib_1v8 = wib_1v8;
621
622 wib_sdio_1v8 = regulator_get_optional(&pdev->dev, "wib_sdio_1v8");
623 if (IS_ERR_OR_NULL(wib_sdio_1v8))
624 printk(KERN_DEBUG "%s: regulator wib_sdio_1v8 not found\n", __func__);
625 else
626 pdata->wib_sdio_1v8 = wib_sdio_1v8;
627
628 gpio = of_get_named_gpio(np, "host-wakeup-wlan-gpio", 0);
629 if (unlikely(gpio < 0)) {
630 pdata->gpio_wakeup_device = -1;
631 dev_err(&pdev->dev, "host-wakeup-wlan-gpio undefined\n");
632 } else {
633 pdata->gpio_wakeup_device = gpio;
634 printk(KERN_DEBUG "%s: host_wakeup_wlan_gpio %d\n", __func__, gpio);
635 }
636 return 0;
637}
638#else
639static int asr_rfkill_probe_dt(struct platform_device *pdev)
640{
641 return 0;
642}
643#endif
644
645static int asr_rfkill_probe(struct platform_device *pdev)
646{
647 struct asr_rfkill_platform_data *pdata = NULL;
648 struct device *dev = &pdev->dev;
649 /* flag: whether pdata is passed from platfrom_data */
650 int pdata_passed = 1;
651 const struct of_device_id *match = NULL;
652 int ret = -1;
653
654 /* make sure asr_rfkill_platform_data is valid */
655 pdata = pdev->dev.platform_data;
656 if (!pdata) {
657 /* if platfrom data do not pass the struct to us */
658 pdata_passed = 0;
659
660 pdata = asr_rfkill_platform_data_alloc(pdev);
661 if (!pdata) {
662 pr_err("can't get asr_rfkill_platform_data struct during probe\n");
663 goto err_pdata;
664 }
665
666 pdev->dev.platform_data = pdata;
667 }
668
669 pdata->clk_26m_out = devm_clk_get(dev, "wifi_26m");
670 if (!IS_ERR(pdata->clk_26m_out)) {
671 dev_info(dev, "enable 26M output for wifi\n");
672 clk_prepare_enable(pdata->clk_26m_out);
673 }
674
675 /* set value to asr_rfkill_platform_data if DT pass them to us */
676#ifdef CONFIG_OF
677 match = of_match_device(of_match_ptr(asr_rfkill_of_match),
678 &pdev->dev);
679#endif
680 if (match) {
681 ret = asr_rfkill_probe_dt(pdev);
682 if (ret)
683 goto err_dt;
684 }
685
686 pdata->is_on = 0;
687 asr_pwr_ctrl(pdata, 0);
688
689 /*
690 * Create a proc interface, allowing user space to control
691 * asr_wlan devices' power
692 */
693 device_create_file(&pdev->dev, &dev_attr_pwr_ctrl);
694 return 0;
695
696err_dt:
697 if (!pdata_passed)
698 pdev->dev.platform_data = NULL;
699err_pdata:
700
701 return ret;
702}
703
704static int asr_rfkill_remove(struct platform_device *pdev)
705{
706 struct asr_rfkill_platform_data *pdata;
707 pdata = pdev->dev.platform_data;
708
709 if (pdata->wib_3v3)
710 regulator_put(pdata->wib_3v3);
711
712 if (pdata->wib_1v8)
713 regulator_put(pdata->wib_1v8);
714
715 if (pdata->wib_sdio_1v8)
716 regulator_put(pdata->wib_sdio_1v8);
717
718 if (!IS_ERR(pdata->clk_26m_out))
719 clk_disable_unprepare(pdata->clk_26m_out);
720 return 0;
721}
722
723static int asr_rfkill_suspend(struct platform_device *pdev,
724 pm_message_t pm_state)
725{
726 return 0;
727}
728
729static int asr_rfkill_resume(struct platform_device *pdev)
730{
731 return 0;
732}
733
734static struct platform_driver asr_rfkill_platform_driver = {
735 .probe = asr_rfkill_probe,
736 .remove = asr_rfkill_remove,
737 .driver = {
738 .name = ASR_DEV_NAME,
739 .owner = THIS_MODULE,
740#ifdef CONFIG_OF
741 .of_match_table = asr_rfkill_of_match,
742#endif
743
744 },
745 .suspend = asr_rfkill_suspend,
746 .resume = asr_rfkill_resume,
747};
748
749static int __init asr_rfkill_init(void)
750{
751 return platform_driver_register(&asr_rfkill_platform_driver);
752}
753
754static void __exit asr_rfkill_exit(void)
755{
756 platform_driver_unregister(&asr_rfkill_platform_driver);
757}
758
759module_init(asr_rfkill_init);
760module_exit(asr_rfkill_exit);
761
762MODULE_ALIAS("platform:asr_rfkill");
763MODULE_DESCRIPTION("asr_rfkill");
764MODULE_AUTHOR("ASR");
765MODULE_LICENSE("GPL");