From fbea64583c373f1a81b251187de371811b5eb0fa Mon Sep 17 00:00:00 2001 From: Mika Laitio Date: Tue, 20 Jan 2009 01:13:58 +0200 Subject: [PATCH] h63xx: bluetooth support --- arch/arm/configs/omap_h63xx_defconfig | 2 + arch/arm/mach-omap1/board-h6300.c | 21 +++ drivers/bluetooth/Kconfig | 10 ++ drivers/bluetooth/Makefile | 1 + drivers/bluetooth/omap/Makefile | 6 + drivers/bluetooth/omap/h6300_bt_brf6100.c | 154 ++++++++++++++++++++ drivers/bluetooth/omap/h6300_bt_led.c | 41 ++++++ drivers/bluetooth/omap/h6300_bt_led.h | 9 ++ include/asm-arm/arch-omap/h6300_uart_info.h | 33 +++++ include/asm-arm/arch-omap/omap_serial.h | 62 ++++++++ 10 files changed, 339 insertions(+) create mode 100644 drivers/bluetooth/omap/Makefile create mode 100644 drivers/bluetooth/omap/h6300_bt_brf6100.c create mode 100644 drivers/bluetooth/omap/h6300_bt_led.c create mode 100644 drivers/bluetooth/omap/h6300_bt_led.h create mode 100644 include/asm-arm/arch-omap/h6300_uart_info.h create mode 100644 include/asm-arm/arch-omap/omap_serial.h diff --git a/arch/arm/configs/omap_h63xx_defconfig b/arch/arm/configs/omap_h63xx_defconfig index 20d37c41b10..2bc595da2a8 100644 --- a/arch/arm/configs/omap_h63xx_defconfig +++ b/arch/arm/configs/omap_h63xx_defconfig @@ -480,6 +480,7 @@ CONFIG_BT_HCIUART_BCSP=y # CONFIG_BT_HCIBTUART is not set # CONFIG_BT_HCIBRF6150 is not set CONFIG_BT_HCIVHCI=m +CONFIG_BT_H6300=m # CONFIG_IEEE80211 is not set # @@ -907,6 +908,7 @@ CONFIG_I2C_OMAP=m # CONFIG_SENSORS_DS1374 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set +CONFIG_PCA9535=y # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_RTC8564 is not set diff --git a/arch/arm/mach-omap1/board-h6300.c b/arch/arm/mach-omap1/board-h6300.c index 2bcc34f9e6c..09f14777f1f 100644 --- a/arch/arm/mach-omap1/board-h6300.c +++ b/arch/arm/mach-omap1/board-h6300.c @@ -29,6 +29,7 @@ #include #include #include +#include #define _h6300_KEY_CALENDAR 67 // xmodmap 75 aka F9 #define _H6300_KEY_TELEPHONE 68 // xmodmap 76 aka F10 @@ -104,6 +105,24 @@ static struct platform_device h6300_kp_device = { .resource = h6300_kp_resources, }; +/* + * Bluetooth - Relies on h6300_bt module, + * so make the calls indirectly through pointers. Requires that the + * h6300_bt bluetooth module be loaded before any attempt to use + * bluetooth (obviously). + */ +static struct platform_omap_serial_funcs h6300_omap_platform__uart_bt_funcs = { + .configure = NULL, + .set_txrx = NULL, + .get_txrx = NULL, +}; + +struct platform_device btuart_device = { + .name = "h6300_bt", + .id = 1, +}; +EXPORT_SYMBOL(btuart_device); + static struct platform_device *h6300_devices[] __initdata = { &h6300_lcd_device, &h6300_kp_device, @@ -169,6 +188,8 @@ static void __init h6300_init(void) static void __init h6300_map_io(void) { omap1_map_common_io(); + + h63xx_uart_bt_device.dev.platform_data = &h6300_omap_platform__uart_bt_funcs; } MACHINE_START(OMAP_H6300, "HP iPAQ h6300") diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 9abcd6206ac..e05424c6749 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -166,6 +166,16 @@ config BT_HCIVHCI Say Y here to compile support for virtual HCI devices into the kernel or say M to compile it as module (hci_vhci). + +config BT_H6300 + tristate "H6300 BRF6100 BT DRIVER" + help + Bluetooth H6300 BRF6100 driver. + This driver provides the firmware loading mechanism for the BRF6100 + bt hardware in iPAQ h6300. + + Say Y here to compile support for BRF6100 BT devices into the + kernel or say M to compile it as module (h6300_BT). endmenu diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile index 18aa038db13..8f9df825342 100644 --- a/drivers/bluetooth/Makefile +++ b/drivers/bluetooth/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_BT_HCIBT3C) += bt3c_cs.o obj-$(CONFIG_BT_HCIBLUECARD) += bluecard_cs.o obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o obj-$(CONFIG_BT_HCIBRF6150) += brf6150.o +obj-$(CONFIG_BT_H6300) += omap/ hci_uart-y := hci_ldisc.o hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o diff --git a/drivers/bluetooth/omap/Makefile b/drivers/bluetooth/omap/Makefile new file mode 100644 index 00000000000..5465d7f12a9 --- /dev/null +++ b/drivers/bluetooth/omap/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the Linux iPAQ H6300 BRF6100 Bluetooth device drivers. +# + +h6300_bt-objs := h6300_bt_led.o h6300_bt_brf6100.o +obj-$(CONFIG_BT_H6300) += h6300_bt.o diff --git a/drivers/bluetooth/omap/h6300_bt_brf6100.c b/drivers/bluetooth/omap/h6300_bt_brf6100.c new file mode 100644 index 00000000000..3c9b564091e --- /dev/null +++ b/drivers/bluetooth/omap/h6300_bt_brf6100.c @@ -0,0 +1,154 @@ +/* + * Bluetooth interface driver for TI BRF6100 on h6300 + * + * Copyright (C) 2005 Mika Laitio + * Ideas taken from the brf6150 bt driver made by Todd Blumer for the pxa hx4700. + * + * 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 +#include +#include +#include + +#include +#include + +#include +#include "h6300_bt_led.h" + +static void +h6300_bt_configure(struct uart_omap_port *up, int enable) +{ + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() started, enable = %d\n", enable); + + // printk( KERN_NOTICE "h6300 configure bluetooth: %d\n", enable ); + if (enable == 0) { + omap_set_gpio_dataout(GPIO_N_BT_RST, 1); // turn off gpio, note 1 == off for negative gpios + mdelay(5); + h6300_clear_led(INDEX_BT_LED); + } + else if (enable == 1) { + omap_set_gpio_dataout(GPIO_N_BT_RST, 1); // turn on gpio, note 0 == on for negative gpios + mdelay(5); + } + else if (enable == 2) { + /* + * BRF6150's RTS goes low when firmware is ready + * so check for CTS=1 (nCTS=0 -> CTS=1). Typical 150ms + */ +/* + int tries = 0; + do + { + mdelay(10); + } + while ((BTMSR & MSR_CTS) == 0 && tries++ < 50); +*/ + h6300_set_led(INDEX_BT_LED, 16, 16); + } + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_configure() done\n"); +} + +static void +h6300_bt_set_txrx(struct uart_omap_port *up, int txrx) +{ + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_set_txrx(), txrx = %d done\n", txrx); + /* do nothing */ +} + +static int +h6300_bt_get_txrx(struct uart_omap_port *up) +{ + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_get_txrx() done\n"); + /* do nothing */ + return 0; +} + +static int +h6300_bt_probe(struct platform_device *pdev) +{ + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data; + + omap_request_gpio(GPIO_BT_PWR_EN); // ask bt_power_en gpio, remember to release in remove_function + omap_set_gpio_direction(GPIO_BT_PWR_EN, 1); // set gpio direction to be output + omap_set_gpio_dataout(GPIO_BT_PWR_EN, 1); // turn on gpio + + mdelay(200); + + omap_request_gpio(GPIO_N_BT_RST); // ask bt_reset gpio, remember to release in remove_function + omap_set_gpio_direction(GPIO_N_BT_RST, 1); // set gpio direction to be output + omap_set_gpio_dataout(GPIO_N_BT_RST, 0); // turn on gpio, note 0 == on for negative gpios + + /* configure bluetooth UART */ + //h6300_gpio_mode(GPIO_NR_H6300_BT_RXD_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_TXD_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_CTS_MD); + //h6300_gpio_mode(GPIO_NR_H6300_BT_UART_RTS_MD); + + funcs->configure = h6300_bt_configure; + funcs->set_txrx = h6300_bt_set_txrx; + funcs->get_txrx = h6300_bt_get_txrx; + + /* Make sure the LED is off */ + h6300_clear_led(INDEX_BT_LED); + + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_probe() done\n"); + + return 0; +} + +static int +h6300_bt_remove(struct platform_device *pdev) +{ + struct h6300_uart_funcs *funcs = (struct h6300_uart_funcs *)pdev->dev.platform_data; + + printk(KERN_NOTICE "h6300_bt_brf6100.c h6300_bt_remove() started\n"); + + omap_free_gpio(GPIO_BT_PWR_EN); + omap_free_gpio(GPIO_N_BT_RST); + + funcs->configure = NULL; + funcs->set_txrx = NULL; + funcs->get_txrx = NULL; + + /* Make sure the LED is off */ + h6300_clear_led(INDEX_BT_LED); + + printk(KERN_NOTICE "h6300_bt_brf6100.c, h6300_bt_remove() done\n"); + + return 0; +} + +static struct platform_driver bt_driver = { + .probe = h6300_bt_probe, + .remove = h6300_bt_remove, + .driver = { + .name = "h6300_bt", + }, +}; + +static int __init +h6300_bt_init(void) +{ + printk(KERN_NOTICE "h6300 Bluetooth Driver init()\n"); + return platform_driver_register(&bt_driver); +} + +static void __exit +h6300_bt_exit(void) +{ + printk(KERN_NOTICE "h6300 Bluetooth Driver exit()\n"); + platform_driver_unregister(&bt_driver); +} + +module_init(h6300_bt_init); +module_exit(h6300_bt_exit); + +MODULE_AUTHOR("Mika Laitio, "); +MODULE_DESCRIPTION("iPAQ h6300 BRF6100 Bluetooth driver."); +MODULE_LICENSE("GPL"); + diff --git a/drivers/bluetooth/omap/h6300_bt_led.c b/drivers/bluetooth/omap/h6300_bt_led.c new file mode 100644 index 00000000000..18458c3087b --- /dev/null +++ b/drivers/bluetooth/omap/h6300_bt_led.c @@ -0,0 +1,41 @@ +/* + * Bluetooth interface driver helper for controlling bluetooth leds available in iPAQ h6300. + * + * Copyright (C) 2005 Mika Laitio + * Ideas from the brf6150 bt driver made by Todd Blumer for the pxa hx4700. + * + * 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 +#include +#include +#include + +#include +#include + +/* + * Low level access for disabling h6300 bt led. + * + * TODO: implement for h6300 + */ +void h6300_clear_led(int led_num) +{ + printk(KERN_NOTICE "h6300_bt_led.c h6300_clear_led() done\n"); + //hx4700_set_led(led_num, 0, 16); +} +EXPORT_SYMBOL(h6300_clear_led); + +/* + * Low level access for setting up the bt led. + * + * TODO: implement for h6300 + */ +void h6300_set_led(int led_num, int duty_time, int cycle_time) +{ + printk(KERN_NOTICE "h6300_bt_led.c h6300_set_led() done\n"); +} +EXPORT_SYMBOL(h6300_set_led); diff --git a/drivers/bluetooth/omap/h6300_bt_led.h b/drivers/bluetooth/omap/h6300_bt_led.h new file mode 100644 index 00000000000..23a7174fee7 --- /dev/null +++ b/drivers/bluetooth/omap/h6300_bt_led.h @@ -0,0 +1,9 @@ +#ifndef H6300_BT_LED_H_ +#define H6300_BT_LED_H_ + +#define INDEX_BT_LED 2 + +void h6300_clear_led(int led_num); +void h6300_set_led(int led_num, int duty_time, int cycle_time); + +#endif /*H6300_BT_LED_H_*/ diff --git a/include/asm-arm/arch-omap/h6300_uart_info.h b/include/asm-arm/arch-omap/h6300_uart_info.h new file mode 100644 index 00000000000..7c36104d8c8 --- /dev/null +++ b/include/asm-arm/arch-omap/h6300_uart_info.h @@ -0,0 +1,33 @@ +/* + * Support file for calling h6300 uart configuration functions. + * Used at least by h6300_bt driver. + * + * Copyright (c) 2005 SDG Systems, LLC + * 2005-03-29 Todd Blumer Converted basic structure to support hx4700 + * 2005-10-03 Mika Laitio (lamikr@cc.jyu.fi) Reorganized for the iPAQ h6300 bt driver. + */ + +#ifndef _H6300_UART_INFO_H +#define _H6300_UART_INFO_H + +#include "omap_serial.h" + +#define GPIO_BT_PWR_EN 3 +#define GPIO_N_BT_RST 9 + +#define GPIO_I2C_GPRS_RESET 16 +#define GPIO_I2C_MIC_OP_EN 10 +#define GPIO_I2C_SPK_OP_PD 11 + +#define GPIO_VALUE_OFF 0 +#define GPIO_VALUE_ON 1 + +#define GPIO_DIR_OUTPUT 1 + +struct h6300_uart_funcs { + void (*configure)( struct uart_omap_port *up, int state); + void (*set_txrx)( struct uart_omap_port *up, int txrx); + int (*get_txrx)( struct uart_omap_port *up); +}; + +#endif diff --git a/include/asm-arm/arch-omap/omap_serial.h b/include/asm-arm/arch-omap/omap_serial.h new file mode 100644 index 00000000000..add09dc3580 --- /dev/null +++ b/include/asm-arm/arch-omap/omap_serial.h @@ -0,0 +1,62 @@ +/* + * Omap/h6300 serial driver private interface. + * Code originates from the pxa-serial.h available in the handheld org drivers + * for iPAQ PXA4700. + * + * Copyright (c) 2005 SDG Systems, LLC + * 2005-03-29 Todd Blumer Converted basic structure to support hx4700 + * 2005-10-03 Mika Laitio (lamikr@cc.jyu.fi) Reorganized for the iPAQ h6300 bt driver. + */ + +#ifndef _OMAP_SERIAL_H +#define _OMAP_SERIAL_H + +#define OMAP_SERIAL_TX 1 +#define OMAP_SERIAL_RX 2 + +#include +#include + +struct platform_omap_serial_funcs; + +struct uart_omap_port { + struct uart_port port; + unsigned char ier; + unsigned char lcr; + unsigned char mcr; + unsigned int lsr_break_flag; + unsigned int cken; + char *name; + struct platform_omap_serial_funcs *pf; +}; + +/* A pointer to such a structure can be contained in the platform_data + * field of every PXA UART platform_device. If the field is NULL, the + * serial port works as usual. + * + * For the sake of simplicity/performance no one of the function pointers + * in the structure below can be NULL. + */ +struct platform_omap_serial_funcs { + /* Platform-specific function to initialize whatever is connected + to this serial port... enable=1 -> enable transceiver, + 0 -> disable transceiver. */ + void (*configure) (struct uart_omap_port *up, int enable); + /* Platform-specific function to enable or disable the individual + transmitter/receiver submodules. On transceivers without echo + cancellation (e.g. SIR) transmitter always has priority, e.g. + if both bits are set, only the transmitter is enabled. */ + void (*set_txrx) (struct uart_omap_port *up, int txrx); + /* Get the current state of tx/rx (see bitflags above) */ + int (*get_txrx) (struct uart_omap_port *up); +}; + +/* + * The variables below are located in arch/arm/mach-omap/board_h6300.c + * Machine-specific code may want to put a pointer to a static + * platform_pxa_serial_funcs structure in the dev.platform_data + * field of the respective port device. + */ +extern struct platform_device btuart_device; + +#endif -- 2.41.1