From c82fe62fcb94b6d7c1844aad317bcb71f58b8152 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 19 Oct 2011 11:57:49 +0200 Subject: cg2900: bluetooth support for 5500 This patch enables cg2900 functionality in 5500 boards. All tests have been made on B5500 (big board BBM R1A) with new CG2900 hardware. NOTE: For proper work new B5500 FPGA firmware is needed (v536). Depends-On: I7820139cc44e347c5b113b1beb665c2489bf74c2 ST-Ericsson Linux next: NA ST-Ericsson ID: 281802 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iebdacf94fd125c7ead843ecee6927d95f8e32738 Signed-off-by: Grzegorz Sygieda Tested-by: Grzegorz Sygieda Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/22941 Reviewed-by: Grzegorz SYGIEDA Tested-by: Grzegorz SYGIEDA Reviewed-by: Par-Gunnar HJALMDAHL Reviewed-by: Srinidhi KASAGAR Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30035 Reviewed-by: Virupax SADASHIVPETIMATH Tested-by: Virupax SADASHIVPETIMATH --- drivers/staging/cg2900/Makefile | 10 +- drivers/staging/cg2900/board-u5500-cg2900.c | 155 ++++++++++++++++++++++++++ drivers/staging/cg2900/devices-cg2900-u5500.c | 65 +++++++++++ drivers/staging/cg2900/devices-cg2900-u8500.c | 130 +++++++++++++++++++++ drivers/staging/cg2900/devices-cg2900.c | 99 +--------------- drivers/staging/cg2900/devices-cg2900.h | 22 ++++ 6 files changed, 384 insertions(+), 97 deletions(-) create mode 100644 drivers/staging/cg2900/board-u5500-cg2900.c create mode 100644 drivers/staging/cg2900/devices-cg2900-u5500.c create mode 100644 drivers/staging/cg2900/devices-cg2900-u8500.c diff --git a/drivers/staging/cg2900/Makefile b/drivers/staging/cg2900/Makefile index c6414c21c5d..0e76f4bf5bd 100644 --- a/drivers/staging/cg2900/Makefile +++ b/drivers/staging/cg2900/Makefile @@ -6,7 +6,15 @@ ccflags-y := \ -Idrivers/staging/cg2900/include \ -Iarch/arm/mach-ux500 -obj-$(CONFIG_CG2900) += board-mop500-cg2900.o devices-cg2900.o +obj-$(CONFIG_CG2900) += devices-cg2900.o +ifeq ($(CONFIG_UX500_SOC_DB8500), y) +obj-$(CONFIG_CG2900) += devices-cg2900-u8500.o +obj-$(CONFIG_CG2900) += board-mop500-cg2900.o +endif +ifeq ($(CONFIG_UX500_SOC_DB5500), y) +obj-$(CONFIG_CG2900) += devices-cg2900-u5500.o +obj-$(CONFIG_CG2900) += board-u5500-cg2900.o +endif obj-y += mfd/ obj-y += bluetooth/ diff --git a/drivers/staging/cg2900/board-u5500-cg2900.c b/drivers/staging/cg2900/board-u5500-cg2900.c new file mode 100644 index 00000000000..d22685f6b88 --- /dev/null +++ b/drivers/staging/cg2900/board-u5500-cg2900.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include "devices-cg2900.h" +#include "pins-db5500.h" + +#define CG2900_BT_CTS_GPIO 168 + +enum cg2900_gpio_pull_sleep cg2900_sleep_gpio[21] = { + CG2900_NO_PULL, /* GPIO 0: PTA_CONFX */ + CG2900_PULL_DN, /* GPIO 1: PTA_STATUS */ + CG2900_NO_PULL, /* GPIO 2: UART_CTSN */ + CG2900_PULL_UP, /* GPIO 3: UART_RTSN */ + CG2900_PULL_UP, /* GPIO 4: UART_TXD */ + CG2900_NO_PULL, /* GPIO 5: UART_RXD */ + CG2900_PULL_DN, /* GPIO 6: IOM_DOUT */ + CG2900_NO_PULL, /* GPIO 7: IOM_FSC */ + CG2900_NO_PULL, /* GPIO 8: IOM_CLK */ + CG2900_NO_PULL, /* GPIO 9: IOM_DIN */ + CG2900_PULL_DN, /* GPIO 10: PWR_REQ */ + CG2900_PULL_DN, /* GPIO 11: HOST_WAKEUP */ + CG2900_PULL_DN, /* GPIO 12: IIS_DOUT */ + CG2900_NO_PULL, /* GPIO 13: IIS_WS */ + CG2900_NO_PULL, /* GPIO 14: IIS_CLK */ + CG2900_NO_PULL, /* GPIO 15: IIS_DIN */ + CG2900_PULL_DN, /* GPIO 16: PTA_FREQ */ + CG2900_PULL_DN, /* GPIO 17: PTA_RF_ACTIVE */ + CG2900_NO_PULL, /* GPIO 18: NotConnected (J6428) */ + CG2900_NO_PULL, /* GPIO 19: EXT_DUTY_CYCLE */ + CG2900_NO_PULL, /* GPIO 20: EXT_FRM_SYNCH */ +}; + +static struct platform_device ux500_cg2900_device = { + .name = "cg2900", +}; + +static struct platform_device ux500_cg2900_chip_device = { + .name = "cg2900-chip", + .dev = { + .parent = &ux500_cg2900_device.dev, + }, +}; + +static struct cg2900_platform_data cg2900_test_platform_data = { + .bus = HCI_VIRTUAL, + .gpio_sleep = cg2900_sleep_gpio, +}; + +static struct platform_device ux500_cg2900_test_device = { + .name = "cg2900-test", + .dev = { + .parent = &ux500_cg2900_device.dev, + .platform_data = &cg2900_test_platform_data, + }, +}; + +static struct resource cg2900_uart_resources[] = { + { + .start = CG2900_BT_CTS_GPIO, + .end = CG2900_BT_CTS_GPIO, + .flags = IORESOURCE_IO, + .name = "cts_gpio", + }, + { + .start = NOMADIK_GPIO_TO_IRQ(CG2900_BT_CTS_GPIO), + .end = NOMADIK_GPIO_TO_IRQ(CG2900_BT_CTS_GPIO), + .flags = IORESOURCE_IRQ, + .name = "cts_irq", + }, +}; + +static pin_cfg_t cg2900_uart_enabled[] = { + GPIO165_U3_RXD | PIN_INPUT_PULLUP, + GPIO166_U3_TXD | PIN_OUTPUT_HIGH, + GPIO167_U3_RTSn | PIN_OUTPUT_HIGH, + GPIO168_U3_CTSn | PIN_INPUT_PULLUP, +}; + +static pin_cfg_t cg2900_uart_disabled[] = { + GPIO165_GPIO | PIN_INPUT_PULLUP, /* RX pull down. */ + GPIO166_GPIO | PIN_OUTPUT_LOW, /* TX low - break on. */ + GPIO167_GPIO | PIN_OUTPUT_HIGH, /* RTS high-flow off. */ + GPIO168_GPIO | PIN_INPUT_PULLUP, /* CTS pull up. */ +}; + +static struct cg2900_platform_data cg2900_uart_platform_data = { + .bus = HCI_UART, + .gpio_sleep = cg2900_sleep_gpio, + .uart = { + .n_uart_gpios = 4, + .uart_enabled = cg2900_uart_enabled, + .uart_disabled = cg2900_uart_disabled, + }, +}; + +static struct platform_device ux500_cg2900_uart_device = { + .name = "cg2900-uart", + .dev = { + .platform_data = &cg2900_uart_platform_data, + .parent = &ux500_cg2900_device.dev, + }, + .num_resources = ARRAY_SIZE(cg2900_uart_resources), + .resource = cg2900_uart_resources, +}; + +static int __init u5500_cg2900_init(void) +{ + int err; + + dcg2900_init_platdata(&cg2900_test_platform_data); + dcg2900_init_platdata(&cg2900_uart_platform_data); + + err = platform_device_register(&ux500_cg2900_device); + if (err) + return err; + err = platform_device_register(&ux500_cg2900_uart_device); + if (err) + return err; + err = platform_device_register(&ux500_cg2900_test_device); + if (err) + return err; + err = platform_device_register(&ux500_cg2900_chip_device); + if (err) + return err; + + dev_info(&ux500_cg2900_device.dev, "CG2900 initialized\n"); + + return 0; +} + +static void __exit u5500_cg2900_exit(void) +{ + platform_device_unregister(&ux500_cg2900_chip_device); + platform_device_unregister(&ux500_cg2900_test_device); + platform_device_unregister(&ux500_cg2900_uart_device); + platform_device_unregister(&ux500_cg2900_device); + + dev_info(&ux500_cg2900_device.dev, "CG2900 removed\n"); +} + +module_init(u5500_cg2900_init); +module_exit(u5500_cg2900_exit); diff --git a/drivers/staging/cg2900/devices-cg2900-u5500.c b/drivers/staging/cg2900/devices-cg2900-u5500.c new file mode 100644 index 00000000000..fac30589696 --- /dev/null +++ b/drivers/staging/cg2900/devices-cg2900-u5500.c @@ -0,0 +1,65 @@ +/* + * arch/arm/mach-ux500/devices-cg2900-u5500.c + * + * Copyright (C) ST-Ericsson SA 2010 + * Authors: + * Par-Gunnar Hjalmdahl (par-gunnar.p.hjalmdahl@stericsson.com) for ST-Ericsson. + * Henrik Possung (henrik.possung@stericsson.com) for ST-Ericsson. + * Josef Kindberg (josef.kindberg@stericsson.com) for ST-Ericsson. + * Dariusz Szymszak (dariusz.xd.szymczak@stericsson.com) for ST-Ericsson. + * Kjell Andersson (kjell.k.andersson@stericsson.com) for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2 + * + * Board specific device support for the Linux Bluetooth HCI H:4 Driver + * for ST-Ericsson connectivity controller. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "devices-cg2900.h" + +/* prcmu resout1 pin is used for CG2900 reset*/ +void dcg2900_enable_chip(struct cg2900_chip_dev *dev) +{ + struct dcg2900_info *info = dev->b_data; + + clk_enable(info->lpoclk); + /* + * Due to a bug in CG2900 we cannot just set GPIO high to enable + * the chip. We must wait more than 100 msecs before enbling the + * chip. + * - Set PDB to low. + * - Wait for 100 msecs + * - Set PDB to high. + */ + prcmu_resetout(1, 0); + schedule_timeout_uninterruptible(msecs_to_jiffies( + CHIP_ENABLE_PDB_LOW_TIMEOUT)); + prcmu_resetout(1, 1); +} + +void dcg2900_disable_chip(struct cg2900_chip_dev *dev) +{ + struct dcg2900_info *info = dev->b_data; + + prcmu_resetout(1, 0); + clk_disable(info->lpoclk); +} + +int dcg2900_setup(struct cg2900_chip_dev *dev, + struct dcg2900_info *info) +{ + info->lpoclk = clk_get(dev->dev, "lpoclk"); + if (IS_ERR(info->lpoclk)) + return PTR_ERR(info->lpoclk); + + return 0; +} diff --git a/drivers/staging/cg2900/devices-cg2900-u8500.c b/drivers/staging/cg2900/devices-cg2900-u8500.c new file mode 100644 index 00000000000..cbadeee248d --- /dev/null +++ b/drivers/staging/cg2900/devices-cg2900-u8500.c @@ -0,0 +1,130 @@ +/* + * arch/arm/mach-ux500/devices-cg2900-u8500.c + * + * Copyright (C) ST-Ericsson SA 2010 + * Authors: + * Par-Gunnar Hjalmdahl (par-gunnar.p.hjalmdahl@stericsson.com) for ST-Ericsson. + * Henrik Possung (henrik.possung@stericsson.com) for ST-Ericsson. + * Josef Kindberg (josef.kindberg@stericsson.com) for ST-Ericsson. + * Dariusz Szymszak (dariusz.xd.szymczak@stericsson.com) for ST-Ericsson. + * Kjell Andersson (kjell.k.andersson@stericsson.com) for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2 + * + * Board specific device support for the Linux Bluetooth HCI H:4 Driver + * for ST-Ericsson connectivity controller. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "devices-cg2900.h" + +void dcg2900_enable_chip(struct cg2900_chip_dev *dev) +{ + struct dcg2900_info *info = dev->b_data; + + if (info->gbf_gpio == -1) + return; + + /* + * Due to a bug in CG2900 we cannot just set GPIO high to enable + * the chip. We must wait more than 100 msecs before enbling the + * chip. + * - Set PDB to low. + * - Wait for 100 msecs + * - Set PDB to high. + */ + gpio_set_value(info->gbf_gpio, 0); + schedule_timeout_uninterruptible(msecs_to_jiffies( + CHIP_ENABLE_PDB_LOW_TIMEOUT)); + gpio_set_value(info->gbf_gpio, 1); +} + +void dcg2900_disable_chip(struct cg2900_chip_dev *dev) +{ + struct dcg2900_info *info = dev->b_data; + + if (info->gbf_gpio != -1) + gpio_set_value(info->gbf_gpio, 0); +} + +int dcg2900_setup(struct cg2900_chip_dev *dev, + struct dcg2900_info *info) +{ + int err = 0; + struct resource *resource; + const char *gbf_name; + const char *bt_name = NULL; + + resource = platform_get_resource_byname(dev->pdev, IORESOURCE_IO, + "gbf_ena_reset"); + if (!resource) { + dev_err(dev->dev, "GBF GPIO does not exist\n"); + err = -EINVAL; + goto err_handling; + } + + info->gbf_gpio = resource->start; + gbf_name = resource->name; + + resource = platform_get_resource_byname(dev->pdev, IORESOURCE_IO, + "bt_enable"); + /* BT Enable GPIO may not exist */ + if (resource) { + info->bt_gpio = resource->start; + bt_name = resource->name; + } + + /* Now setup the GPIOs */ + err = gpio_request(info->gbf_gpio, gbf_name); + if (err < 0) { + dev_err(dev->dev, "gpio_request failed with err: %d\n", err); + goto err_handling; + } + + err = gpio_direction_output(info->gbf_gpio, 0); + if (err < 0) { + dev_err(dev->dev, "gpio_direction_output failed with err: %d\n", + err); + goto err_handling_free_gpio_gbf; + } + + if (!bt_name) { + info->bt_gpio = -1; + goto finished; + } + + err = gpio_request(info->bt_gpio, bt_name); + if (err < 0) { + dev_err(dev->dev, "gpio_request failed with err: %d\n", err); + goto err_handling_free_gpio_gbf; + } + + err = gpio_direction_output(info->bt_gpio, 1); + if (err < 0) { + dev_err(dev->dev, "gpio_direction_output failed with err: %d\n", + err); + goto err_handling_free_gpio_bt; + } + +finished: + + return 0; + +err_handling_free_gpio_bt: + gpio_free(info->bt_gpio); +err_handling_free_gpio_gbf: + gpio_free(info->gbf_gpio); +err_handling: + + return err; +} diff --git a/drivers/staging/cg2900/devices-cg2900.c b/drivers/staging/cg2900/devices-cg2900.c index 567639d9e34..689235989d9 100644 --- a/drivers/staging/cg2900/devices-cg2900.c +++ b/drivers/staging/cg2900/devices-cg2900.c @@ -11,6 +11,7 @@ * Board specific device support for the Linux Bluetooth HCI H:4 Driver * for ST-Ericsson connectivity controller. */ + #define NAME "devices-cg2900" #define pr_fmt(fmt) NAME ": " fmt "\n" @@ -23,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -45,8 +45,6 @@ #define CG2900_PG2_HCI_REV 0x0200 #define CG2900_PG1_SPECIAL_HCI_REV 0x0700 -#define CHIP_ENABLE_PDB_LOW_TIMEOUT 100 /* ms */ - struct vs_power_sw_off_cmd { __le16 op_code; u8 len; @@ -58,48 +56,6 @@ struct vs_power_sw_off_cmd { u8 gpio_16_20_pull_down; } __packed; -struct dcg2900_info { - int gbf_gpio; - int bt_gpio; - bool sleep_gpio_set; - u8 gpio_0_7_pull_up; - u8 gpio_8_15_pull_up; - u8 gpio_16_20_pull_up; - u8 gpio_0_7_pull_down; - u8 gpio_8_15_pull_down; - u8 gpio_16_20_pull_down; - struct regulator *regulator_wlan; -}; - -static void dcg2900_enable_chip(struct cg2900_chip_dev *dev) -{ - struct dcg2900_info *info = dev->b_data; - - if (info->gbf_gpio == -1) - return; - - /* - * Due to a bug in CG2900 we cannot just set GPIO high to enable - * the chip. We must wait more than 20 msecs before enbling the - * chip. - * - Set PDB to low. - * - Wait for 20 msecs - * - Set PDB to high. - */ - gpio_set_value(info->gbf_gpio, 0); - schedule_timeout_uninterruptible(msecs_to_jiffies( - CHIP_ENABLE_PDB_LOW_TIMEOUT)); - gpio_set_value(info->gbf_gpio, 1); -} - -static void dcg2900_disable_chip(struct cg2900_chip_dev *dev) -{ - struct dcg2900_info *info = dev->b_data; - - if (info->gbf_gpio != -1) - gpio_set_value(info->gbf_gpio, 0); -} - static struct sk_buff *dcg2900_get_power_switch_off_cmd (struct cg2900_chip_dev *dev, u16 *op_code) { @@ -184,9 +140,6 @@ static int dcg2900_init(struct cg2900_chip_dev *dev) { int err = 0; struct dcg2900_info *info; - struct resource *resource; - const char *gbf_name; - const char *bt_name = NULL; struct cg2900_platform_data *pdata = dev_get_platdata(dev->dev); /* First retrieve and save the resources */ @@ -203,55 +156,9 @@ static int dcg2900_init(struct cg2900_chip_dev *dev) goto finished; } - resource = platform_get_resource_byname(dev->pdev, IORESOURCE_IO, - "gbf_ena_reset"); - if (!resource) { - dev_err(dev->dev, "GBF GPIO does not exist\n"); - err = -EINVAL; - goto err_handling; - } - info->gbf_gpio = resource->start; - gbf_name = resource->name; - - resource = platform_get_resource_byname(dev->pdev, IORESOURCE_IO, - "bt_enable"); - /* BT Enable GPIO may not exist */ - if (resource) { - info->bt_gpio = resource->start; - bt_name = resource->name; - } - - /* Now setup the GPIOs */ - err = gpio_request(info->gbf_gpio, gbf_name); - if (err < 0) { - dev_err(dev->dev, "gpio_request failed with err: %d\n", err); + err = dcg2900_setup(dev, info); + if (err) goto err_handling; - } - - err = gpio_direction_output(info->gbf_gpio, 0); - if (err < 0) { - dev_err(dev->dev, "gpio_direction_output failed with err: %d\n", - err); - goto err_handling_free_gpio_gbf; - } - - if (!bt_name) { - info->bt_gpio = -1; - goto finished; - } - - err = gpio_request(info->bt_gpio, bt_name); - if (err < 0) { - dev_err(dev->dev, "gpio_request failed with err: %d\n", err); - goto err_handling_free_gpio_gbf; - } - - err = gpio_direction_output(info->bt_gpio, 1); - if (err < 0) { - dev_err(dev->dev, "gpio_direction_output failed with err: %d\n", - err); - goto err_handling_free_gpio_bt; - } /* * Enable the power on snowball diff --git a/drivers/staging/cg2900/devices-cg2900.h b/drivers/staging/cg2900/devices-cg2900.h index e365a4fae1e..c4dc060e22e 100644 --- a/drivers/staging/cg2900/devices-cg2900.h +++ b/drivers/staging/cg2900/devices-cg2900.h @@ -9,6 +9,28 @@ #define __DEVICES_CG2900_H #include "cg2900.h" +#include + +#define CHIP_ENABLE_PDB_LOW_TIMEOUT 100 /* ms */ + +struct dcg2900_info { + int gbf_gpio; + int bt_gpio; + bool sleep_gpio_set; + u8 gpio_0_7_pull_up; + u8 gpio_8_15_pull_up; + u8 gpio_16_20_pull_up; + u8 gpio_0_7_pull_down; + u8 gpio_8_15_pull_down; + u8 gpio_16_20_pull_down; + struct clk *lpoclk; + struct regulator *regulator_wlan; +}; + +extern void dcg2900_enable_chip(struct cg2900_chip_dev *dev); +extern void dcg2900_disable_chip(struct cg2900_chip_dev *dev); +extern int dcg2900_setup(struct cg2900_chip_dev *dev, + struct dcg2900_info *info); /** * enum cg2900_gpio_pull_sleep - GPIO pull setting in sleep. -- cgit v1.2.3