summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Sygieda <grzegorz.sygieda@tieto.com>2011-09-02 14:23:10 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:05:53 +0200
commitd79c17dfa54a096b7c197bdf6555ff5a0b6b4690 (patch)
tree1719d3136abcfb0bc9fa6570fcfe0c41d88d62f8
parente5cbb2e48412db6884abe4c01194df9ac86b396b (diff)
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: I3df0bc1e41e60ce6abf4be9cb18465073ba8d738 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30348 Reviewed-by: Par-Gunnar HJALMDAHL <par-gunnar.p.hjalmdahl@stericsson.com> Reviewed-by: Virupax SADASHIVPETIMATH <virupax.sadashivpetimath@stericsson.com> Tested-by: Virupax SADASHIVPETIMATH <virupax.sadashivpetimath@stericsson.com>
-rw-r--r--drivers/staging/cg2900/Makefile10
-rw-r--r--drivers/staging/cg2900/board-u5500-cg2900.c154
-rw-r--r--drivers/staging/cg2900/devices-cg2900-u5500.c64
-rw-r--r--drivers/staging/cg2900/devices-cg2900-u8500.c130
-rw-r--r--drivers/staging/cg2900/devices-cg2900.c99
-rw-r--r--drivers/staging/cg2900/devices-cg2900.h23
6 files changed, 383 insertions, 97 deletions
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..07b29b2a997
--- /dev/null
+++ b/drivers/staging/cg2900/board-u5500-cg2900.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/gpio/nomadik.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+
+#include <plat/pincfg.h>
+
+#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..5b8c5fb8064
--- /dev/null
+++ b/drivers/staging/cg2900/devices-cg2900-u5500.c
@@ -0,0 +1,64 @@
+/*
+ * 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 <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/mfd/abx500/ab5500.h>
+
+#include <mach/prcmu-db5500.h>
+
+#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 <asm/byteorder.h>
+#include <asm-generic/errno-base.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <plat/pincfg.h>
+
+#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 847a6ebe28e..8f342a4a1fc 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 <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/types.h>
@@ -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 */
@@ -205,55 +158,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..49023c0c45b 100644
--- a/drivers/staging/cg2900/devices-cg2900.h
+++ b/drivers/staging/cg2900/devices-cg2900.h
@@ -9,6 +9,29 @@
#define __DEVICES_CG2900_H
#include "cg2900.h"
+#include <linux/clk.h>
+
+#define CHIP_ENABLE_PDB_LOW_TIMEOUT 100 /* ms */
+
+struct dcg2900_info {
+ int gbf_gpio;
+ int pmuen_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.