22 Jun 21:34
[PATCH][RFC] Tosa bluetooth powerup/down
Dmitry Baryshkov <dbaryshkov <at> gmail.com>
2008-06-22 19:34:58 GMT
2008-06-22 19:34:58 GMT
Hi,
The patch below depends on my recent patch with pm hook into pxa serial
driver. It also requires few changes to rfkill, some of which aren't
even submitted. However I'd like to know your oppinion about these
ideas.
>From e24a002a7b47fc3f88c4ee03bd0c21b1c3713111 Mon Sep 17 00:00:00 2001
From: Dmitry Baryshkov <dbaryshkov <at> gmail.com>
Date: Sun, 22 Jun 2008 23:26:30 +0400
Subject: [PATCH] Tosa: support built-in bluetooth power-up
Signed-off-by: Dmitry Baryshkov <dbaryshkov <at> gmail.com>
---
arch/arm/mach-pxa/Kconfig | 8 ++
arch/arm/mach-pxa/Makefile | 2 +
arch/arm/mach-pxa/tosa-bt.c | 201 +++++++++++++++++++++++++++++++++++++++
arch/arm/mach-pxa/tosa.c | 8 ++-
include/asm-arm/arch-pxa/tosa.h | 7 +-
5 files changed, 221 insertions(+), 5 deletions(-)
create mode 100644 arch/arm/mach-pxa/tosa-bt.c
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 5da7a68..6f2a736 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 "Enable support for built-in bluetooth in Sharp SL-6000"
+ select RFKILL
+ help
+ Some Sharp Zaurus SL-6000 models do contain internat
+ bluetooth module.
+ Enable support for it's powerup/down.
endif
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index c9e66fb..65dc5a9 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 0000000..06b8f68
--- /dev/null
+++ b/arch/arm/mach-pxa/tosa-bt.c
@@ -0,0 +1,201 @@
+/*
+ * 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 <linux/input.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/serial.h>
+#include <asm/arch/tosa.h>
+
+static struct rfkill *rfk;
+static struct input_dev *input_dev;
+static bool change_req;
+
+static void tosa_bt_on(void)
+{
+ gpio_set_value(TOSA_GPIO_BT_RESET, 0);
+ gpio_set_value(TOSA_GPIO_BT_PWR_EN, 1);
+ gpio_set_value(TOSA_GPIO_BT_RESET, 1);
+ mdelay(20);
+ gpio_set_value(TOSA_GPIO_BT_RESET, 0);
+}
+
+static void tosa_bt_off(void)
+{
+ gpio_set_value(TOSA_GPIO_BT_RESET, 1);
+ mdelay(10);
+ gpio_set_value(TOSA_GPIO_BT_PWR_EN, 0);
+ gpio_set_value(TOSA_GPIO_BT_RESET, 0);
+}
+
+static void tosa_bt_serial_pm(struct platform_device *dev,
+ unsigned int oldstate,
+ unsigned int state)
+{
+ pr_info("BT_PM: %d\n", state);
+
+ BUG_ON(!rfk);
+
+ if (((rfk->state == RFKILL_STATE_ON) != (state == 0)) || change_req) {
+ pr_info("BT_PM: toggle\n");
+ change_req = true;
+ input_report_key(input_dev, KEY_BLUETOOTH, 1);
+ input_report_key(input_dev, KEY_BLUETOOTH, 0);
+ }
+}
+
+static struct pxa_serial_platform_data tosa_btdata = {
+ .pm = tosa_bt_serial_pm,
+};
+
+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");
+ pr_info("BT_RADIO was : %s\n",
+ rfk->state == RFKILL_STATE_ON ? "on" : "off");
+
+ change_req = false;
+
+ if (state == RFKILL_STATE_ON) {
+ pr_info("TOSA_BT: going ON\n");
+ tosa_bt_on();
+ } else {
+ pr_info("TOSA_BT: going OFF\n");
+ tosa_bt_off();
+ }
+ return 0;
+}
+
+static int tosa_bt_probe(struct platform_device *dev)
+{
+ int rc;
+
+ if (!machine_is_tosa())
+ return -ENODEV;
+
+ rc = gpio_request(TOSA_GPIO_BT_RESET, "Bluetooth reset");
+ if (rc)
+ goto err_reset;
+ rc = gpio_direction_output(TOSA_GPIO_BT_RESET, 0);
+ if (rc)
+ goto err_reset_dir;
+ rc = gpio_request(TOSA_GPIO_BT_PWR_EN, "Bluetooth power");
+ if (rc)
+ goto err_pwr;
+ rc = gpio_direction_output(TOSA_GPIO_BT_PWR_EN, 0);
+ if (rc)
+ goto err_pwr_dir;
+
+ pxa_set_btuart_info(&tosa_btdata);
+
+ 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 = dev;
+#ifdef CONFIG_RFKILL_LEDS
+ rfk->led_trigger.name = "tosa-bt";
+#endif
+
+ input_dev = input_allocate_device();
+ if (!input_dev)
+ goto err_input_alloc;
+
+ input_dev->name = "tosa-bt";
+ input_dev->phys = "btuart";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x02;
+ input_dev->dev.parent = &dev->dev;
+ input_dev->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_BLUETOOTH, input_dev->keybit);
+
+ rc = rfkill_register(rfk);
+ if (rc)
+ goto err_rfkill;
+
+ rc = input_register_device(input_dev);
+ if (rc)
+ goto err_rfkill;
+
+ /* if we disagree with rfkill, switch it off */
+ tosa_bt_serial_pm(dev, 0, 3);
+
+ return 0;
+
+err_rfkill:
+ if (input_dev)
+ input_free_device(input_dev);
+ input_dev = NULL;
+err_input_alloc:
+ if (rfk)
+ rfkill_free(rfk);
+ rfk = NULL;
+err_rfk_alloc:
+ pxa_set_btuart_info(NULL);
+ tosa_bt_off();
+err_pwr_dir:
+ gpio_free(TOSA_GPIO_BT_PWR_EN);
+err_pwr:
+err_reset_dir:
+ gpio_free(TOSA_GPIO_BT_RESET);
+err_reset:
+ return rc;
+}
+
+static int __devexit tosa_bt_remove(struct platform_device *dev)
+{
+ if (input_dev)
+ input_unregister_device(input_dev);
+ input_dev = NULL;
+
+ if (rfk)
+ rfkill_unregister(rfk);
+ rfk = NULL;
+
+ pxa_set_btuart_info(NULL);
+
+ tosa_bt_off();
+
+ gpio_free(TOSA_GPIO_BT_PWR_EN);
+ gpio_free(TOSA_GPIO_BT_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 f9ebf6a..076a39d 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -570,7 +570,7 @@ static struct gpio_led tosa_gpio_leds[] = {
},
{
.name = "tosa:blue:bluetooth",
- .default_trigger = "none",
+ .default_trigger = "tosa-bt",
.gpio = TOSA_GPIO_BT_LED,
},
};
@@ -740,6 +740,11 @@ static struct platform_device tc6393xb_device = {
.resource = tc6393xb_resources,
};
+static struct platform_device tosa_bt_device = {
+ .name = "tosa-bt",
+ .id = -1,
+};
+
static struct platform_device *devices[] __initdata = {
&tosascoop_device,
&tosascoop_jc_device,
@@ -748,6 +753,7 @@ static struct platform_device *devices[] __initdata = {
&tosakbd_device,
&tosa_gpio_keys_device,
&tosaled_device,
+ &tosa_bt_device,
};
static void tosa_poweroff(void)
diff --git a/include/asm-arm/arch-pxa/tosa.h b/include/asm-arm/arch-pxa/tosa.h
index a16c103..a72803f 100644
--- a/include/asm-arm/arch-pxa/tosa.h
+++ b/include/asm-arm/arch-pxa/tosa.h
@@ -30,14 +30,13 @@
#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
--
1.5.5.4
--
--
With best wishes
Dmitry
-------------------------------------------------------------------
List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm-kernel
FAQ: http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette: http://www.arm.linux.org.uk/mailinglists/etiquette.php
RSS Feed