3 * Machine specific driver for WLAN/BT module (bcm4329,bcm4330,etc)
4 * Most of functional blocks are implemented in dhd.ko module driver
5 * provided by Broadcom.
7 * Copyright (C) 2010 Samsung Electronics
8 * Jaehoon Chung <jh80.chung@samsung.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/slab.h>
16 #include <linux/module.h>
17 #include <linux/init.h>
18 #include <linux/platform_device.h>
19 #include <linux/regulator/consumer.h>
20 #include <linux/mutex.h>
21 #include <linux/err.h>
22 #include <linux/delay.h>
23 #include <linux/rfkill.h>
25 #include <linux/interrupt.h>
26 #include <linux/firmware.h>
28 #include <mach/gpio.h>
29 #include <mach/regs-gpio.h>
31 #include <plat/gpio-cfg.h>
32 #include <plat/sdhci.h>
36 #define BT_FW_NAME "BCM4330.hcd"
37 #define BT_FW_LOAD_SUCCESS 1
38 #define BT_FW_LOAD_FAIL 0
40 #define to_dev(obj) container_of(obj, struct device, kobj)
42 #define WLAN_STATIC_BUF // this feature for using static buffer on wifi driver /Kernel/drivers/net/wireless/bcm4330
44 #if defined (WLAN_STATIC_BUF)
45 #include <linux/skbuff.h>
46 #endif /* WLAN_STATIC_BUF */
49 struct bcm4330_platform_data *pdata;
50 struct rfkill *bt_rfk;
51 struct rfkill *wlan_rfk;
55 unsigned char *fw_data;
59 struct regulator *regulator_bt;
60 struct regulator *regulator_wlan;
63 struct bcm4330_data *bcm4330_bd;
65 /* The device name consist of chip name and revision informatin. */
66 #define BCM4330_NAME_SIZE 15
67 char bcm4330_name[][BCM4330_NAME_SIZE] = {
68 [TYPE_BCM4330_B1] = {"bcm4330-b1"}, /* BCM4330's rev : "b1" */
69 [TYPE_BCM4330_B0] = {"bcm4330-b0"}, /* BCM4330's rev : "b0" */
72 static void bcm4330_bt_enable(void *data)
74 struct bcm4330_data *bd = data;
75 struct bcm4330_platform_data *pdata = bd->pdata;
82 ret = regulator_enable(bd->regulator_bt);
84 printk(KERN_INFO "Failed to enable regulator_bt\n");
88 gpio_set_value(pdata->bt_en, 1);
90 /* 100msec delay is required but regulator handle this one */
91 gpio_set_value(pdata->bt_wake, 1);
92 gpio_set_value(pdata->bt_nrst, 1);
94 /* FIXME: BCM4330 has a error that is happened
95 when enable/disable repeatedly. Temporarily,
96 I extened delay time (100ms->150ms) */
102 static void bcm4330_bt_disable(void *data)
104 struct bcm4330_data *bd = data;
105 struct bcm4330_platform_data *pdata = bd->pdata;
111 if (bd->regulator_bt)
112 ret = regulator_disable(bd->regulator_bt);
114 printk(KERN_INFO "Failed to disable regulator_bt\n");
118 gpio_set_value(pdata->bt_wake, 0);
119 gpio_set_value(pdata->bt_nrst, 0);
121 gpio_set_value(pdata->bt_en, 0);
123 bd->bt_in_use = false;
126 static void bcm4330_wlan_enable(void *data)
128 struct bcm4330_data *bd = data;
129 struct bcm4330_platform_data *pdata = bd->pdata;
135 if (bd->regulator_wlan)
136 ret = regulator_enable(bd->regulator_wlan);
138 printk(KERN_INFO "Failed to enable regulator_wlan\n");
142 gpio_set_value(pdata->wlan_en, 1);
146 /* 100msec delay is required but regulator handle this one */
148 /* FIXME why BT_RST_N is required 100ms high at WLAN on? */
149 if (!bd->bt_in_use) {
150 gpio_set_value(pdata->bt_wake, 1);
151 gpio_set_value(pdata->bt_nrst, 1);
153 gpio_set_value(pdata->bt_wake, 0);
154 gpio_set_value(pdata->bt_nrst, 0);
157 bd->wlan_in_use = true;
160 static void bcm4330_wlan_disable(void *data)
162 struct bcm4330_data *bd = data;
163 struct bcm4330_platform_data *pdata = bd->pdata;
166 if (!bd->wlan_in_use)
169 if (bd->regulator_wlan)
170 ret = regulator_disable(bd->regulator_wlan);
172 printk(KERN_INFO "Failed to disable regulator_wlan\n");
176 gpio_set_value(pdata->wlan_en, 0);
178 bd->wlan_in_use = false;
181 static int bcm4330_set_bt_block(void *data, bool blocked)
184 /* RFKILL_STATE_UNBLOCKED */
185 printk(KERN_INFO "%s : Enable BCM4330 BT chip\n", __func__);
186 bcm4330_bt_enable(data);
188 /* RFKILL_STATE_SOFT_BLOCKED */
189 printk(KERN_INFO "%s : Disable BCM4330 BT chip\n", __func__);
190 bcm4330_bt_disable(data);
196 static int bcm4330_set_wlan_block(void *data, bool blocked)
199 /* RFKILL_STATE_UNBLOCKED */
200 printk(KERN_INFO "%s : Enable BCM4330 WLAN chip\n", __func__);
201 bcm4330_wlan_enable(data);
204 /* RFKILL_STATE_SOFT_BLOCKED */
205 printk(KERN_INFO "%s : Disable BCM4330 WLAN chip\n", __func__);
206 bcm4330_wlan_disable(data);
213 static const struct rfkill_ops bcm4330_rfkill_bt_ops = {
214 .set_block = bcm4330_set_bt_block,
217 static const struct rfkill_ops bcm4330_rfkill_wlan_ops = {
218 .set_block = bcm4330_set_wlan_block,
221 int wlan_set_power(int flag)
223 struct bcm4330_data *bd = bcm4330_bd;
224 struct bcm4330_platform_data *pdata = bd->pdata;
227 printk("%s[%d] Power ON\n",__func__,__LINE__);
228 gpio_set_value(pdata->wlan_en, 1);
231 printk("%s[%d] Power OFF\n",__func__,__LINE__);
232 gpio_set_value(pdata->wlan_en, 0);
235 if (pdata->wlan_host_enable)
236 pdata->wlan_host_enable(flag);
238 printk(KERN_ERR "%s: Didn't find SDIO card Host\n",__func__);
240 printk(KERN_DEBUG "%s[%d] Power OFF\n",__func__,__LINE__);
241 gpio_set_value(pdata->wlan_en, 0);
247 EXPORT_SYMBOL(wlan_set_power);
249 static void bcm4330_host_wake(struct work_struct *work)
251 printk(KERN_DEBUG "BT/WLAN_HOST_WAKE irq is occured!");
253 static DECLARE_WORK(bcm4330_host_wake_work, bcm4330_host_wake);
255 static irqreturn_t bcm4330_host_wake_handler(int irq, void *dev_id)
257 /* FIXME: The overhead of scheduling is occurred
258 * during data transmission through bluetooth,
259 * because bt_host_wake is frequently coming. */
260 /* schedule_work(&bcm4330_host_wake_work); */
264 static void bcm4330_firmware_handler(const struct firmware *fw,
268 bcm4330_bd->fw_size = fw->size;
269 bcm4330_bd->fw_data = kzalloc(fw->size, GFP_KERNEL);
270 if (!bcm4330_bd->fw_data) {
271 bcm4330_bd->fw_state = BT_FW_LOAD_FAIL;
273 printk(KERN_INFO "Failed to allocate memory for Bluetooth \
276 memcpy(bcm4330_bd->fw_data, fw->data, fw->size);
277 bcm4330_bd->fw_state = BT_FW_LOAD_SUCCESS;
279 printk(KERN_INFO "BT F/W loaded successfully (size: %d)\n", fw->size);
282 bcm4330_bd->fw_state = BT_FW_LOAD_FAIL;
284 printk(KERN_INFO "failed to load BT F/W, BT will not working\n");
288 static DEFINE_MUTEX(fw_lock);
289 static ssize_t bcm4330_firmware_read(struct file *filp, struct kobject *kobj,
290 struct bin_attribute *bin_attr,
291 char *buffer, loff_t offset, size_t count)
293 char *fw_data = bcm4330_bd->fw_data;
294 int fw_size = bcm4330_bd->fw_size;
297 mutex_lock(&fw_lock);
299 if (offset > fw_size) {
303 if (count > fw_size - offset)
304 count = fw_size - offset;
310 int page_nr = offset >> PAGE_SHIFT;
311 int page_ofs = offset & (PAGE_SIZE-1);
312 int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
314 page_data = fw_data + (4096 * page_nr);
316 memcpy(buffer, page_data, page_cnt);
323 mutex_unlock(&fw_lock);
327 static ssize_t bcm4330_firmware_write(struct file *filp, struct kobject *kobj,
328 struct bin_attribute *bin_attr,
329 char *buffer, loff_t offset, size_t count)
331 printk(KERN_INFO "Permission denied! Only read firmware of bcm4330\n");
335 static struct bin_attribute bcm4330_firmware_attr = {
336 .attr = { .name = "firmware", .mode = 0644 },
338 .read = bcm4330_firmware_read,
339 .write = bcm4330_firmware_write,
342 #if defined (WLAN_STATIC_BUF)
343 static int init_wifi_mem(void);
344 #endif /* WLAN_STATIC_BUF */
346 static int __devinit bcm4330_probe(struct platform_device *pdev)
348 struct bcm4330_platform_data *pdata;
349 struct bcm4330_data *bd;
350 int gpio, i, ret, irq, type;
354 * WLAN_BT_EN ____|```````````````````````````
355 * WLAN_nRST ______100ms__|``````````````````
356 * BT_nRST ______100ms__|``````````````````
359 pdata = pdev->dev.platform_data;
361 dev_err(&pdev->dev, "No BCM4330 platform data.\n");
365 #if defined (WLAN_STATIC_BUF)
366 ret = init_wifi_mem();
369 "%s : Failed to init wifi memory\n", __func__);
370 goto wlan_mem_failed;
372 #endif /* WLAN_STATIC_BUF */
374 bd = kzalloc(sizeof(struct bcm4330_data), GFP_KERNEL);
384 gpio = pdata->wlan_en;
385 gpio_request(gpio, "WLAN_EN");
386 gpio_direction_output(gpio, 0);
387 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
390 gpio = pdata->wlan_host_wake;
391 gpio_request(gpio, "WLAN_HOST_WAKE");
392 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
397 gpio_request(gpio, "BT_EN");
398 gpio_direction_output(gpio, 0);
399 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
402 gpio = pdata->bt_nrst;
403 gpio_request(gpio, "BT_nRST");
404 gpio_direction_output(gpio, 1);
405 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
408 gpio = pdata->bt_wake;
409 gpio_request(gpio, "BT_WAKE");
410 gpio_direction_output(gpio, 0);
413 gpio = pdata->bt_host_wake;
414 gpio_request(gpio, "BT_HOST_nWAKE");
415 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0xf));
417 /* - Register irq handler of BT_HOST_WAKE interrupt */
418 irq = gpio_to_irq(gpio);
419 ret = request_irq(irq, bcm4330_host_wake_handler,
420 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
421 "BT_HOST_WAKE", NULL);
424 "%s : Failed to register handler of BT_HOST_WAKE\n",
429 /* WLAN_HOST_WAKE - Interrupt */
430 gpio = pdata->wlan_host_wake;
431 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(0x0));
432 gpio_request(gpio, "WLAN_HOST_nWAKE");
433 gpio_direction_input(gpio);
434 /* Initialize and free gpio once,
435 * unless will float until DHD module get loaded.*/
439 /* - Register irq handler of WLAN_HOST_WAKE interrupt */
440 irq = gpio_to_irq(gpio);
441 ret = request_irq(irq, bcm4330_host_wake_handler,
442 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
443 "WLAN_HOST_WAKE", NULL);
446 "%s : Failed to register handler of WLAN_HOST_WAKE\n",
448 goto wlan_irq_failed;
451 /* BT_UART pin configuration - UART0 */
452 for (i = 0; i < 4; i++)
453 if (gpio_is_valid(pdata->bt_uart[i])) {
454 s3c_gpio_cfgpin(pdata->bt_uart[i], S3C_GPIO_SFN(2));
457 /* Check BCM4330 chip type */
458 type = platform_get_device_id(pdev)->driver_data;
459 for (i = 0 ; i < TYPE_BCM4330_NUM ; i++) {
461 name = bcm4330_name[i];
465 printk("%s module is ready to start\n", name);
467 /* Register BCM4330 to RFKILL class */
468 bd->wlan_rfk = rfkill_alloc(name, &pdev->dev, RFKILL_TYPE_WLAN,
469 &bcm4330_rfkill_wlan_ops, bd);
472 goto wlan_rfk_failed;
476 * described by the comment in rfkill.h
480 rfkill_init_sw_state(bd->wlan_rfk, true);
482 ret = rfkill_register(bd->wlan_rfk);
484 goto wlan_rfk_register_failed;
486 bd->bt_rfk = rfkill_alloc(name, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
487 &bcm4330_rfkill_bt_ops, bd);
493 rfkill_init_sw_state(bd->bt_rfk, true);
495 ret = rfkill_register(bd->bt_rfk);
497 goto bt_rfk_register_failed;
499 /* Get Clock of BT/WiFi */
500 bd->regulator_bt = regulator_get(NULL, "bt_clk");
501 if (bd->regulator_bt == NULL || IS_ERR(bd->regulator_bt)) {
503 "Failed to get the regulator : BT_WIFI_CLK32k(BT)\n");
504 goto wifi_regulator_failed;
507 bd->regulator_wlan = regulator_get(NULL, "wifi_clk");
508 if (bd->regulator_wlan == NULL || IS_ERR(bd->regulator_wlan)) {
510 "Failed to get the regulator : BT_WIFI_CLK32k(WiFi)\n");
511 goto bt_regulator_failed;
515 ret = request_firmware_nowait(THIS_MODULE,
521 bcm4330_firmware_handler);
523 printk(KERN_INFO "Failed to request firmware of Bluetooth : \
525 goto bt_rfk_register_failed;
528 /* Create sysfs for firmware of bluetooth, so the user can get firmware
529 * image through sysfs node in user-space. */
530 ret = device_create_bin_file(&pdev->dev, &bcm4330_firmware_attr);
532 dev_err(&pdev->dev, "Failed to create sysfs of Bluetooth : \
534 goto bt_sysfs_create_failed;
537 platform_set_drvdata(pdev, bd);
541 bt_sysfs_create_failed:
542 device_remove_bin_file(&pdev->dev, &bcm4330_firmware_attr);
543 wifi_regulator_failed:
544 regulator_put(bd->regulator_wlan);
546 regulator_put(bd->regulator_bt);
547 bt_rfk_register_failed:
548 rfkill_destroy(bd->bt_rfk);
550 rfkill_unregister(bd->wlan_rfk);
551 wlan_rfk_register_failed:
552 rfkill_destroy(bd->wlan_rfk);
556 gpio_free(pdata->bt_host_wake);
557 gpio_free(pdata->bt_wake);
558 gpio_free(pdata->bt_nrst);
559 gpio_free(pdata->bt_en);
560 gpio_free(pdata->wlan_host_wake);
561 gpio_free(pdata->wlan_en);
563 #if defined (WLAN_STATIC_BUF)
565 #endif /* WLAN_STATIC_BUF */
569 static int __devexit bcm4330_remove(struct platform_device *pdev)
571 struct bcm4330_data *bd = platform_get_drvdata(pdev);
572 struct bcm4330_platform_data *pdata = bd->pdata;
574 rfkill_unregister(bd->bt_rfk);
575 rfkill_destroy(bd->bt_rfk);
576 rfkill_unregister(bd->wlan_rfk);
577 rfkill_destroy(bd->wlan_rfk);
578 gpio_free(pdata->bt_host_wake);
579 gpio_free(pdata->bt_wake);
580 gpio_free(pdata->bt_nrst);
581 gpio_free(pdata->bt_en);
582 gpio_free(pdata->wlan_host_wake);
583 gpio_free(pdata->wlan_en);
586 platform_set_drvdata(pdev, NULL);
592 static int bcm4330_suspend(struct platform_device *pdev, pm_message_t state)
594 struct bcm4330_data *bd = platform_get_drvdata(pdev);
595 struct bcm4330_platform_data *pdata = bd->pdata;
598 s5p_gpio_set_pdn_config(pdata->wlan_en, S3C_GPIO_PDNCFG_OUTPUT1);
600 s5p_gpio_set_pdn_config(pdata->wlan_en, S3C_GPIO_PDNCFG_OUTPUT0);
603 s5p_gpio_set_pdn_config(pdata->bt_en, S3C_GPIO_PDNCFG_OUTPUT1);
604 s5p_gpio_set_pdn_config(pdata->bt_nrst, S3C_GPIO_PDNCFG_OUTPUT1);
605 s5p_gpio_set_pdn_config(pdata->bt_wake, S3C_GPIO_PDNCFG_OUTPUT0);
607 s5p_gpio_set_pdn_config(pdata->bt_en, S3C_GPIO_PDNCFG_OUTPUT0);
608 s5p_gpio_set_pdn_config(pdata->bt_nrst, S3C_GPIO_PDNCFG_OUTPUT0);
609 s5p_gpio_set_pdn_config(pdata->bt_wake, S3C_GPIO_PDNCFG_OUTPUT0);
615 static int bcm4330_resume(struct platform_device *pdev)
620 #define bcm4330_suspend NULL
621 #define bcm4330_resume NULL
624 #if defined (WLAN_STATIC_BUF)
626 #define PREALLOC_WLAN_SEC_NUM 4
627 #define PREALLOC_WLAN_BUF_NUM 160
628 #define PREALLOC_WLAN_SECTION_HEADER 24
631 #define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_BUF_NUM * 128)
632 #define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_BUF_NUM * 128)
633 #define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_BUF_NUM * 512)
634 #define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_BUF_NUM * 1024)
636 #define WLAN_SKB_BUF_NUM 17
638 static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
640 #endif /* WLAN_STATIC_BUF */
642 #if defined (WLAN_STATIC_BUF)
644 struct wifi_mem_prealloc {
649 static struct wifi_mem_prealloc wifi_mem_array[PREALLOC_WLAN_SEC_NUM] = {
650 {NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER)},
651 {NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER)},
652 {NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER)},
653 {NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER)}
656 void *wlan_mem_prealloc(int section, unsigned long size)
658 if (section == PREALLOC_WLAN_SEC_NUM)
659 return wlan_static_skb;
661 if ((section < 0) || (section > PREALLOC_WLAN_SEC_NUM))
664 if (wifi_mem_array[section].size < size)
667 return wifi_mem_array[section].mem_ptr;
669 EXPORT_SYMBOL(wlan_mem_prealloc);
671 #define DHD_SKB_HDRSIZE 336
672 #define DHD_SKB_1PAGE_BUFSIZE ((PAGE_SIZE*1)-DHD_SKB_HDRSIZE)
673 #define DHD_SKB_2PAGE_BUFSIZE ((PAGE_SIZE*2)-DHD_SKB_HDRSIZE)
674 #define DHD_SKB_4PAGE_BUFSIZE ((PAGE_SIZE*4)-DHD_SKB_HDRSIZE)
676 static int init_wifi_mem(void)
681 for (i = 0; i < 8; i++) {
682 wlan_static_skb[i] = alloc_skb(DHD_SKB_1PAGE_BUFSIZE, GFP_KERNEL);
683 if (!wlan_static_skb[i])
687 for (; i < 16; i++) {
688 wlan_static_skb[i] = alloc_skb(DHD_SKB_2PAGE_BUFSIZE, GFP_KERNEL);
689 if (!wlan_static_skb[i])
693 wlan_static_skb[i] = alloc_skb(DHD_SKB_4PAGE_BUFSIZE, GFP_KERNEL);
694 if (!wlan_static_skb[i])
697 for (i = 0 ; i < PREALLOC_WLAN_SEC_NUM ; i++) {
698 wifi_mem_array[i].mem_ptr =
699 kmalloc(wifi_mem_array[i].size, GFP_KERNEL);
701 if (!wifi_mem_array[i].mem_ptr)
707 pr_err("Failed to mem_alloc for WLAN\n");
708 for (j = 0 ; j < i ; j++)
709 kfree(wifi_mem_array[j].mem_ptr);
711 i = WLAN_SKB_BUF_NUM;
714 pr_err("Failed to skb_alloc for WLAN\n");
715 for (j = 0 ; j < i ; j++)
716 dev_kfree_skb(wlan_static_skb[j]);
721 #endif /* WLAN_STATIC_BUF */
723 static struct platform_device_id bcm4330_ids[] = {
725 .name = "bcm4330-b1",
726 .driver_data = TYPE_BCM4330_B1,
728 .name = "bcm4330-b0",
729 .driver_data = TYPE_BCM4330_B0,
732 MODULE_DEVICE_TABLE(platform, bcm4330_ids);
734 static struct platform_driver bcm4330_driver = {
735 .probe = bcm4330_probe,
736 .remove = __devexit_p(bcm4330_remove),
737 .suspend = bcm4330_suspend,
738 .resume = bcm4330_resume,
742 .id_table = bcm4330_ids,
745 static int __init bcm4330_init(void)
747 return platform_driver_register(&bcm4330_driver);
750 static void __exit bcm4330_exit(void)
752 platform_driver_unregister(&bcm4330_driver);
755 module_init(bcm4330_init);
756 module_exit(bcm4330_exit);
758 MODULE_AUTHOR("Jaehoon Chung <jh80.chung@samsung.com>");
759 MODULE_DESCRIPTION("BCM4330 (WLAN/BT) module driver");
760 MODULE_LICENSE("GPL");