[ARM] 5150/1: Tosa: support built-in bluetooth power-up
authorDmitry Baryshkov <dbaryshkov@gmail.com>
Sat, 5 Jul 2008 08:02:48 +0000 (09:02 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 7 Jul 2008 12:22:10 +0000 (13:22 +0100)
The driver is pretty much generic and will be later shared with
a few other devices, like hx4700 ipaq.

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/tosa-bt.c [new file with mode: 0644]
arch/arm/mach-pxa/tosa.c
include/asm-arm/arch-pxa/tosa.h
include/asm-arm/arch-pxa/tosa_bt.h [new file with mode: 0644]

index 5da7a68..6c162f8 100644 (file)
@@ -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
index c9e66fb..18e0b24 100644 (file)
@@ -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 (file)
index 0000000..7d85054
--- /dev/null
@@ -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);
index fa903e7..5a9d329 100644 (file)
@@ -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)
index a16c103..a72803f 100644 (file)
 #define TOSA_GPIO_SD_WP                        (TOSA_SCOOP_GPIO_BASE + 3)
 #define TOSA_GPIO_PWR_ON               (TOSA_SCOOP_GPIO_BASE + 4)
 #define TOSA_SCOOP_AUD_PWR_ON          SCOOP_GPCR_PA16
-#define TOSA_SCOOP_BT_RESET            SCOOP_GPCR_PA17
-#define TOSA_SCOOP_BT_PWR_EN           SCOOP_GPCR_PA18
+#define TOSA_GPIO_BT_RESET             (TOSA_SCOOP_GPIO_BASE + 6)
+#define TOSA_GPIO_BT_PWR_EN            (TOSA_SCOOP_GPIO_BASE + 7)
 #define TOSA_SCOOP_AC_IN_OL            SCOOP_GPCR_PA19
 
 /* GPIO Direction   1 : output mode / 0:input mode */
 #define TOSA_SCOOP_IO_DIR     (TOSA_SCOOP_PXA_VCORE1 | \
-               TOSA_SCOOP_AUD_PWR_ON |\
-               TOSA_SCOOP_BT_RESET | TOSA_SCOOP_BT_PWR_EN)
+               TOSA_SCOOP_AUD_PWR_ON)
 
 /*
  * SCOOP2 jacket GPIOs
diff --git a/include/asm-arm/arch-pxa/tosa_bt.h b/include/asm-arm/arch-pxa/tosa_bt.h
new file mode 100644 (file)
index 0000000..efc3c3d
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Tosa bluetooth built-in chip control.
+ *
+ * Later it may be shared with some other platforms.
+ *
+ * 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.
+ *
+ */
+#ifndef TOSA_BT_H
+#define TOSA_BT_H
+
+struct tosa_bt_data {
+       int gpio_pwr;
+       int gpio_reset;
+};
+
+#endif
+