aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-pxa/Kconfig8
-rw-r--r--arch/arm/mach-pxa/Makefile2
-rw-r--r--arch/arm/mach-pxa/tosa-bt.c150
-rw-r--r--arch/arm/mach-pxa/tosa.c17
4 files changed, 176 insertions, 1 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 5da7a682049..6c162f8fdce 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -273,4 +273,12 @@ config PXA_SSP
tristate
help
Enable support for PXA2xx SSP ports
+
+config TOSA_BT
+ tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
+ depends on MACH_TOSA
+ select RFKILL
+ help
+ This is a simple driver that is able to control
+ the state of built in bluetooth chip on tosa.
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index c9e66fbe622..18e0b249f7c 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -58,3 +58,5 @@ obj-$(CONFIG_LEDS) += $(led-y)
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_MACH_ARMCORE) += cm-x270-pci.o
endif
+
+obj-$(CONFIG_TOSA_BT) += tosa-bt.o
diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c
new file mode 100644
index 00000000000..7d8505466e5
--- /dev/null
+++ b/arch/arm/mach-pxa/tosa-bt.c
@@ -0,0 +1,150 @@
+/*
+ * Bluetooth built-in chip control
+ *
+ * Copyright (c) 2008 Dmitry Baryshkov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/rfkill.h>
+
+#include <asm/arch/tosa_bt.h>
+
+static void tosa_bt_on(struct tosa_bt_data *data)
+{
+ gpio_set_value(data->gpio_reset, 0);
+ gpio_set_value(data->gpio_pwr, 1);
+ gpio_set_value(data->gpio_reset, 1);
+ mdelay(20);
+ gpio_set_value(data->gpio_reset, 0);
+}
+
+static void tosa_bt_off(struct tosa_bt_data *data)
+{
+ gpio_set_value(data->gpio_reset, 1);
+ mdelay(10);
+ gpio_set_value(data->gpio_pwr, 0);
+ gpio_set_value(data->gpio_reset, 0);
+}
+
+static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
+{
+ pr_info("BT_RADIO going: %s\n",
+ state == RFKILL_STATE_ON ? "on" : "off");
+
+ if (state == RFKILL_STATE_ON) {
+ pr_info("TOSA_BT: going ON\n");
+ tosa_bt_on(data);
+ } else {
+ pr_info("TOSA_BT: going OFF\n");
+ tosa_bt_off(data);
+ }
+ return 0;
+}
+
+static int tosa_bt_probe(struct platform_device *dev)
+{
+ int rc;
+ struct rfkill *rfk;
+
+ struct tosa_bt_data *data = dev->dev.platform_data;
+
+ rc = gpio_request(data->gpio_reset, "Bluetooth reset");
+ if (rc)
+ goto err_reset;
+ rc = gpio_direction_output(data->gpio_reset, 0);
+ if (rc)
+ goto err_reset_dir;
+ rc = gpio_request(data->gpio_pwr, "Bluetooth power");
+ if (rc)
+ goto err_pwr;
+ rc = gpio_direction_output(data->gpio_pwr, 0);
+ if (rc)
+ goto err_pwr_dir;
+
+ rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH);
+ if (!rfk) {
+ rc = -ENOMEM;
+ goto err_rfk_alloc;
+ }
+
+ rfk->name = "tosa-bt";
+ rfk->toggle_radio = tosa_bt_toggle_radio;
+ rfk->data = data;
+#ifdef CONFIG_RFKILL_LEDS
+ rfk->led_trigger.name = "tosa-bt";
+#endif
+
+ rc = rfkill_register(rfk);
+ if (rc)
+ goto err_rfkill;
+
+ platform_set_drvdata(dev, rfk);
+
+ return 0;
+
+err_rfkill:
+ if (rfk)
+ rfkill_free(rfk);
+ rfk = NULL;
+err_rfk_alloc:
+ tosa_bt_off(data);
+err_pwr_dir:
+ gpio_free(data->gpio_pwr);
+err_pwr:
+err_reset_dir:
+ gpio_free(data->gpio_reset);
+err_reset:
+ return rc;
+}
+
+static int __devexit tosa_bt_remove(struct platform_device *dev)
+{
+ struct tosa_bt_data *data = dev->dev.platform_data;
+ struct rfkill *rfk = platform_get_drvdata(dev);
+
+ platform_set_drvdata(dev, NULL);
+
+ if (rfk)
+ rfkill_unregister(rfk);
+ rfk = NULL;
+
+ tosa_bt_off(data);
+
+ gpio_free(data->gpio_pwr);
+ gpio_free(data->gpio_reset);
+
+ return 0;
+}
+
+static struct platform_driver tosa_bt_driver = {
+ .probe = tosa_bt_probe,
+ .remove = __devexit_p(tosa_bt_remove),
+
+ .driver = {
+ .name = "tosa-bt",
+ .owner = THIS_MODULE,
+ },
+};
+
+
+static int __init tosa_bt_init(void)
+{
+ return platform_driver_register(&tosa_bt_driver);
+}
+
+static void __exit tosa_bt_exit(void)
+{
+ platform_driver_unregister(&tosa_bt_driver);
+}
+
+module_init(tosa_bt_init);
+module_exit(tosa_bt_exit);
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index fa903e7ae62..5a9d329f504 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -31,6 +31,7 @@
#include <linux/input.h>
#include <linux/gpio.h>
#include <linux/pda_power.h>
+#include <linux/rfkill.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
@@ -40,6 +41,7 @@
#include <asm/arch/i2c.h>
#include <asm/arch/mmc.h>
#include <asm/arch/udc.h>
+#include <asm/arch/tosa_bt.h>
#include <asm/mach/arch.h>
#include <asm/arch/tosa.h>
@@ -562,7 +564,7 @@ static struct gpio_led tosa_gpio_leds[] = {
},
{
.name = "tosa:blue:bluetooth",
- .default_trigger = "none",
+ .default_trigger = "tosa-bt",
.gpio = TOSA_GPIO_BT_LED,
},
};
@@ -732,6 +734,18 @@ static struct platform_device tc6393xb_device = {
.resource = tc6393xb_resources,
};
+static struct tosa_bt_data tosa_bt_data = {
+ .gpio_pwr = TOSA_GPIO_BT_PWR_EN,
+ .gpio_reset = TOSA_GPIO_BT_RESET,
+};
+
+static struct platform_device tosa_bt_device = {
+ .name = "tosa-bt",
+ .id = -1,
+ .dev.platform_data = &tosa_bt_data,
+};
+
+
static struct platform_device *devices[] __initdata = {
&tosascoop_device,
&tosascoop_jc_device,
@@ -740,6 +754,7 @@ static struct platform_device *devices[] __initdata = {
&tosakbd_device,
&tosa_gpio_keys_device,
&tosaled_device,
+ &tosa_bt_device,
};
static void tosa_poweroff(void)