[ARM] 5150/1: Tosa: support built-in bluetooth power-up
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>
This commit is contained in:
parent
5289fecda0
commit
16b32fd0a3
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
150
arch/arm/mach-pxa/tosa-bt.c
Normal file
150
arch/arm/mach-pxa/tosa-bt.c
Normal file
|
@ -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);
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
22
include/asm-arm/arch-pxa/tosa_bt.h
Normal file
22
include/asm-arm/arch-pxa/tosa_bt.h
Normal file
|
@ -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
|
||||
|
Loading…
Reference in a new issue