2 * Copyright (C) 2011 Google, Inc.
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.
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.
15 #include <linux/kernel.h>
16 #include <linux/delay.h>
17 #include <linux/device.h>
18 #include <linux/module.h>
19 #include <linux/platform_device.h>
20 #include <linux/rfkill.h>
21 #include <linux/gpio.h>
22 #include <linux/ioport.h>
23 #include <linux/clk.h>
24 #include <soc/sprd/board.h>
25 #include <linux/of_gpio.h>
28 static struct rfkill *bt_rfk;
29 static const char bt_name[] = "bluetooth";
31 static unsigned long bt_power;
32 static unsigned long bt_reset;
34 static void bt_clk_init(void)
37 bt_clk = clk_get(NULL, "clk_aux0");
39 printk("clock: failed to get clk_aux0\n");
41 clk_set_rate(bt_clk, 32000);
43 clk_prepare_enable(bt_clk);
47 static void getIoResource(struct platform_device *pdev)
51 printk("rfkill get gpio\n");
53 res = platform_get_resource_byname(pdev, IORESOURCE_IO,"bt_power");
55 printk("couldn't bt_power gpio\n");
58 bt_power = res->start;
60 res = platform_get_resource_byname(pdev, IORESOURCE_IO,"bt_reset");
62 printk("couldn't find bt_reset gpio\n");
65 bt_reset = res->start;
67 printk("bt_reset = %ld, bt_power = %ld\n", bt_reset, bt_power);
70 static void getIoResourceDT(struct platform_device *pdev)
72 struct device_node *np = pdev->dev.of_node;
74 bt_power = of_get_gpio(np, 0);
76 printk("couldn't bt_power gpio\n");
78 bt_reset = of_get_gpio(np, 1);
80 printk("couldn't bt_reset gpio\n");
83 printk("bt_reset = %ld, bt_power = %ld\n", bt_reset, bt_power);
86 static int bluetooth_set_power(void *data, bool blocked)
88 printk("%s: start_block=%d\n",__func__, blocked);
91 gpio_direction_output(bt_power, 0);
92 gpio_direction_output(bt_reset, 0);
94 gpio_direction_output(bt_power, 1);
95 gpio_direction_output(bt_reset, 1);
99 gpio_direction_output(bt_power, 0);
100 gpio_direction_output(bt_reset, 0);
103 printk("%s: end_block=%d\n",__func__, blocked);
107 static struct rfkill_ops rfkill_bluetooth_ops = {
108 .set_block = bluetooth_set_power,
111 static void rfkill_gpio_init(void)
113 if(gpio_request(bt_power,"bt_power")){
114 printk("request bt power fail\n");
116 if(gpio_request(bt_reset,"bt_reset")){
117 printk("request bt reset fail\n");
121 static void rfkill_gpio_deinit(void)
126 static int rfkill_bluetooth_probe(struct platform_device *pdev)
130 bool default_state = true;
132 printk(KERN_INFO "-->%s\n", __func__);
136 if (pdev->dev.of_node)
137 getIoResourceDT(pdev);
139 bt_rfk = rfkill_alloc(bt_name, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
140 &rfkill_bluetooth_ops, NULL);
143 goto err_rfkill_alloc;
146 /* userspace cannot take exclusive control */
147 rfkill_init_sw_state(bt_rfk,false);
148 rc = rfkill_register(bt_rfk);
152 rfkill_set_sw_state(bt_rfk,true);
153 bluetooth_set_power(NULL, default_state);
156 printk(KERN_INFO "<--%s\n", __func__);
160 rfkill_destroy(bt_rfk);
165 static int rfkill_bluetooth_remove(struct platform_device *dev)
167 printk(KERN_INFO "-->%s\n", __func__);
168 rfkill_gpio_deinit();
169 rfkill_unregister(bt_rfk);
170 rfkill_destroy(bt_rfk);
171 printk(KERN_INFO "<--%s\n", __func__);
175 static const struct of_device_id rfkill_of_match[] = {
176 { .compatible = "broadcom,rfkill", },
180 MODULE_DEVICE_TABLE(of, rfkill_of_match);
183 static struct platform_driver rfkill_bluetooth_driver = {
184 .probe = rfkill_bluetooth_probe,
185 .remove = rfkill_bluetooth_remove,
188 .owner = THIS_MODULE,
190 .of_match_table = rfkill_of_match,
195 static int __init rfkill_bluetooth_init(void)
197 printk(KERN_INFO "-->%s\n", __func__);
198 return platform_driver_register(&rfkill_bluetooth_driver);
201 static void __exit rfkill_bluetooth_exit(void)
203 printk(KERN_INFO "-->%s\n", __func__);
204 platform_driver_unregister(&rfkill_bluetooth_driver);
207 //late_initcall(rfkill_bluetooth_init);
208 module_init(rfkill_bluetooth_init);
209 module_exit(rfkill_bluetooth_exit);
210 MODULE_DESCRIPTION("bluetooth rfkill");
211 MODULE_AUTHOR("Yale Wu <ye.wu@spreadtrum.com>");
212 MODULE_LICENSE("GPL");