2007-05-10 00:41:03 +04:00
/*
* arch / arm / mach - s3c2410 / h1940 - bluetooth . c
* Copyright ( c ) Arnaud Patard < arnaud . patard @ rtp - net . org >
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file COPYING in the main directory of this archive for
* more details .
*
* S3C2410 bluetooth " driver "
*
*/
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/delay.h>
# include <linux/string.h>
# include <linux/ctype.h>
# include <linux/leds.h>
2009-05-14 01:52:24 +04:00
# include <linux/gpio.h>
2009-11-17 16:54:59 +03:00
# include <linux/rfkill.h>
2009-05-14 01:52:24 +04:00
2008-08-05 19:14:15 +04:00
# include <mach/regs-gpio.h>
# include <mach/hardware.h>
# include <mach/h1940-latch.h>
2011-01-06 22:52:48 +03:00
# include <mach/h1940.h>
2007-05-10 00:41:03 +04:00
2011-01-06 22:52:48 +03:00
# define DRV_NAME "h1940-bt"
2007-05-10 00:41:03 +04:00
/* Bluetooth control */
static void h1940bt_enable ( int on )
{
if ( on ) {
/* Power on the chip */
2010-09-08 13:39:46 +04:00
gpio_set_value ( H1940_LATCH_BLUETOOTH_POWER , 1 ) ;
2007-05-10 00:41:03 +04:00
/* Reset the chip */
mdelay ( 10 ) ;
2010-05-04 06:23:05 +04:00
gpio_set_value ( S3C2410_GPH ( 1 ) , 1 ) ;
2007-05-10 00:41:03 +04:00
mdelay ( 10 ) ;
2010-05-04 06:23:05 +04:00
gpio_set_value ( S3C2410_GPH ( 1 ) , 0 ) ;
2011-01-06 22:52:48 +03:00
h1940_led_blink_set ( - EINVAL , GPIO_LED_BLINK , NULL , NULL ) ;
2007-05-10 00:41:03 +04:00
}
else {
2010-05-04 06:23:05 +04:00
gpio_set_value ( S3C2410_GPH ( 1 ) , 1 ) ;
2007-05-10 00:41:03 +04:00
mdelay ( 10 ) ;
2010-05-04 06:23:05 +04:00
gpio_set_value ( S3C2410_GPH ( 1 ) , 0 ) ;
2007-05-10 00:41:03 +04:00
mdelay ( 10 ) ;
2010-09-08 13:39:46 +04:00
gpio_set_value ( H1940_LATCH_BLUETOOTH_POWER , 0 ) ;
2011-01-06 22:52:48 +03:00
h1940_led_blink_set ( - EINVAL , GPIO_LED_NO_BLINK_LOW , NULL , NULL ) ;
2007-05-10 00:41:03 +04:00
}
}
2009-11-17 16:54:59 +03:00
static int h1940bt_set_block ( void * data , bool blocked )
2007-05-10 00:41:03 +04:00
{
2009-11-17 16:54:59 +03:00
h1940bt_enable ( ! blocked ) ;
return 0 ;
2007-05-10 00:41:03 +04:00
}
2009-11-17 16:54:59 +03:00
static const struct rfkill_ops h1940bt_rfkill_ops = {
. set_block = h1940bt_set_block ,
} ;
2007-05-10 00:41:03 +04:00
2010-02-04 22:56:49 +03:00
static int __devinit h1940bt_probe ( struct platform_device * pdev )
2007-05-10 00:41:03 +04:00
{
2009-11-17 16:54:59 +03:00
struct rfkill * rfk ;
int ret = 0 ;
2010-05-04 06:23:05 +04:00
ret = gpio_request ( S3C2410_GPH ( 1 ) , dev_name ( & pdev - > dev ) ) ;
if ( ret ) {
2010-09-08 13:39:46 +04:00
dev_err ( & pdev - > dev , " could not get GPH1 \n " ) ;
return ret ;
}
ret = gpio_request ( H1940_LATCH_BLUETOOTH_POWER , dev_name ( & pdev - > dev ) ) ;
if ( ret ) {
gpio_free ( S3C2410_GPH ( 1 ) ) ;
dev_err ( & pdev - > dev , " could not get BT_POWER \n " ) ;
2010-05-04 06:23:05 +04:00
return ret ;
}
2007-05-10 00:41:03 +04:00
/* Configures BT serial port GPIOs */
2010-05-04 09:38:49 +04:00
s3c_gpio_cfgpin ( S3C2410_GPH ( 0 ) , S3C2410_GPH0_nCTS0 ) ;
2010-11-16 12:11:59 +03:00
s3c_gpio_setpull ( S3C2410_GPH ( 0 ) , S3C_GPIO_PULL_NONE ) ;
2010-05-04 09:38:49 +04:00
s3c_gpio_cfgpin ( S3C2410_GPH ( 1 ) , S3C2410_GPIO_OUTPUT ) ;
2010-11-16 12:11:59 +03:00
s3c_gpio_setpull ( S3C2410_GPH ( 1 ) , S3C_GPIO_PULL_NONE ) ;
2010-05-04 09:38:49 +04:00
s3c_gpio_cfgpin ( S3C2410_GPH ( 2 ) , S3C2410_GPH2_TXD0 ) ;
2010-11-16 12:11:59 +03:00
s3c_gpio_setpull ( S3C2410_GPH ( 2 ) , S3C_GPIO_PULL_NONE ) ;
2010-05-04 09:38:49 +04:00
s3c_gpio_cfgpin ( S3C2410_GPH ( 3 ) , S3C2410_GPH3_RXD0 ) ;
2010-11-16 12:11:59 +03:00
s3c_gpio_setpull ( S3C2410_GPH ( 3 ) , S3C_GPIO_PULL_NONE ) ;
2007-05-10 00:41:03 +04:00
2009-11-17 16:54:59 +03:00
rfk = rfkill_alloc ( DRV_NAME , & pdev - > dev , RFKILL_TYPE_BLUETOOTH ,
& h1940bt_rfkill_ops , NULL ) ;
if ( ! rfk ) {
ret = - ENOMEM ;
goto err_rfk_alloc ;
}
ret = rfkill_register ( rfk ) ;
if ( ret )
goto err_rfkill ;
platform_set_drvdata ( pdev , rfk ) ;
return 0 ;
2007-05-10 00:41:03 +04:00
2009-11-17 16:54:59 +03:00
err_rfkill :
rfkill_destroy ( rfk ) ;
err_rfk_alloc :
return ret ;
2007-05-10 00:41:03 +04:00
}
static int h1940bt_remove ( struct platform_device * pdev )
{
2009-11-17 16:54:59 +03:00
struct rfkill * rfk = platform_get_drvdata ( pdev ) ;
platform_set_drvdata ( pdev , NULL ) ;
2010-05-04 06:23:05 +04:00
gpio_free ( S3C2410_GPH ( 1 ) ) ;
2009-11-17 16:54:59 +03:00
if ( rfk ) {
rfkill_unregister ( rfk ) ;
rfkill_destroy ( rfk ) ;
}
rfk = NULL ;
h1940bt_enable ( 0 ) ;
2007-05-10 00:41:03 +04:00
return 0 ;
}
static struct platform_driver h1940bt_driver = {
. driver = {
. name = DRV_NAME ,
} ,
. probe = h1940bt_probe ,
. remove = h1940bt_remove ,
} ;
2012-09-07 01:33:24 +04:00
module_platform_driver ( h1940bt_driver ) ;
2007-05-10 00:41:03 +04:00
MODULE_AUTHOR ( " Arnaud Patard <arnaud.patard@rtp-net.org> " ) ;
MODULE_DESCRIPTION ( " Driver for the iPAQ H1940 bluetooth chip " ) ;
MODULE_LICENSE ( " GPL " ) ;