summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/cg2900/bluetooth/cg2900_uart.c4
-rw-r--r--drivers/staging/cg2900/clock-cg2900.c5
-rw-r--r--drivers/staging/cg2900/devices-cg2900-ux500.c18
-rw-r--r--drivers/staging/cg2900/devices-cg2900.h1
-rw-r--r--drivers/staging/cg2900/include/cg2900.h3
-rw-r--r--drivers/staging/cg2900/mfd/cg2900_chip.c67
-rw-r--r--drivers/staging/cg2900/mfd/cg2900_core.c3
7 files changed, 64 insertions, 37 deletions
diff --git a/drivers/staging/cg2900/bluetooth/cg2900_uart.c b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
index 6cde9d75c21..79b4efa189c 100644
--- a/drivers/staging/cg2900/bluetooth/cg2900_uart.c
+++ b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
@@ -55,8 +55,8 @@
#define HCI_BT_CMD_COMPLETE_LEN (sizeof(struct hci_ev_cmd_complete) + 1)
/* Timers used in milliseconds */
-#define UART_TX_TIMEOUT 100
-#define UART_RX_TIMEOUT 20
+#define UART_TX_TIMEOUT 10
+#define UART_RX_TIMEOUT 10
#define UART_RESP_TIMEOUT 1000
#define UART_RESUME_TIMEOUT 20
diff --git a/drivers/staging/cg2900/clock-cg2900.c b/drivers/staging/cg2900/clock-cg2900.c
index 6e3c738e49d..54900c185fb 100644
--- a/drivers/staging/cg2900/clock-cg2900.c
+++ b/drivers/staging/cg2900/clock-cg2900.c
@@ -41,9 +41,10 @@ static struct clk_lookup *cg2900_clk_lookup;
static int cg2900_clk_enable(struct clk *clk)
{
int err = -EINVAL;
- if (pf_data)
+ if (pf_data) {
+ pf_data->is_clk_user = true;
err = pf_data->open(pf_data);
-
+ }
return err;
}
diff --git a/drivers/staging/cg2900/devices-cg2900-ux500.c b/drivers/staging/cg2900/devices-cg2900-ux500.c
index 7e7c12ce4a0..5a5734671cb 100644
--- a/drivers/staging/cg2900/devices-cg2900-ux500.c
+++ b/drivers/staging/cg2900/devices-cg2900-ux500.c
@@ -37,16 +37,10 @@ void dcg2900_u8500_enable_chip(struct cg2900_chip_dev *dev)
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 enabling the
- * chip.
- * - Set PDB to low.
- * - Wait for 100 msecs
+ * - SET PMU_EN to high
+ * - Wait for 300usec
* - Set PDB to high.
*/
- gpio_set_value(info->gbf_gpio, 0);
- schedule_timeout_uninterruptible(msecs_to_jiffies(
- CHIP_ENABLE_PDB_LOW_TIMEOUT));
if (info->pmuen_gpio != -1) {
/*
@@ -186,16 +180,8 @@ void dcg2900_u5500_enable_chip(struct cg2900_chip_dev *dev)
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);
}
diff --git a/drivers/staging/cg2900/devices-cg2900.h b/drivers/staging/cg2900/devices-cg2900.h
index 5ca95e1e0a1..0a1db162279 100644
--- a/drivers/staging/cg2900/devices-cg2900.h
+++ b/drivers/staging/cg2900/devices-cg2900.h
@@ -9,6 +9,7 @@
#define __DEVICES_CG2900_H
#include "cg2900.h"
+#include "mfd/cg2900_chip.h"
#include <linux/clk.h>
#define CHIP_ENABLE_PDB_LOW_TIMEOUT 100 /* ms */
diff --git a/drivers/staging/cg2900/include/cg2900.h b/drivers/staging/cg2900/include/cg2900.h
index bd165c0048b..eddfb71c8e4 100644
--- a/drivers/staging/cg2900/include/cg2900.h
+++ b/drivers/staging/cg2900/include/cg2900.h
@@ -196,6 +196,8 @@ struct cg2900_platform_data {
* @h4_channel: H4 channel. Set by CG2900 driver.
* @is_audio: True if this channel is an audio channel. Set by CG2900
* driver.
+ * @is_clk_user: whether enabling CG29XX was started external entity
+ * for eg. WLAN.
* @chip_independent: True if this channel does not require chip to be
* powered. Set by CG2900 driver.
* @bt_bus: Transport used, see @include/net/bluetooth/hci.h.
@@ -224,6 +226,7 @@ struct cg2900_user_data {
int h4_channel;
bool is_audio;
+ bool is_clk_user;
bool chip_independent;
union {
diff --git a/drivers/staging/cg2900/mfd/cg2900_chip.c b/drivers/staging/cg2900/mfd/cg2900_chip.c
index 020f7c906ad..3ff07714508 100644
--- a/drivers/staging/cg2900/mfd/cg2900_chip.c
+++ b/drivers/staging/cg2900/mfd/cg2900_chip.c
@@ -180,6 +180,8 @@
* @CG2900_CLOSING: CG2900 closing after last user has deregistered.
* @CG2900_RESETING: CG2900 reset requested.
* @CG2900_ACTIVE: CG2900 up and running with at least one user.
+ * @CG2900_ACTIVE_BEFORE_SELFTEST: CG2900 up and running before
+ * BT self test is run.
*/
enum main_state {
CG2900_INIT,
@@ -187,7 +189,8 @@ enum main_state {
CG2900_BOOTING,
CG2900_CLOSING,
CG2900_RESETING,
- CG2900_ACTIVE
+ CG2900_ACTIVE,
+ CG2900_ACTIVE_BEFORE_SELFTEST
};
/**
@@ -404,6 +407,13 @@ static struct main_info *main_info;
* main_wait_queue - Main Wait Queue in CG2900 driver.
*/
static DECLARE_WAIT_QUEUE_HEAD(main_wait_queue);
+/*
+ * Clock enabler should be released earlier
+ * before running read self test
+ * as that is not required for clock enabler
+ * as is the case for WLAN
+ */
+static DECLARE_WAIT_QUEUE_HEAD(clk_user_wait_queue);
static struct mfd_cell cg2900_devs[];
static struct mfd_cell cg2900_char_devs[];
@@ -1814,10 +1824,20 @@ static bool handle_rx_data_bt_evt(struct cg2900_chip_dev *dev,
pkt_handled =
handle_vs_power_switch_off_cmd_complete(dev,
data);
- else if (op_code == CG2900_BT_OP_VS_SYSTEM_RESET)
- pkt_handled = handle_vs_system_reset_cmd_complete(dev,
- data);
- else if (op_code == CG2900_BT_OP_VS_BT_ENABLE)
+ else if (op_code == CG2900_BT_OP_VS_SYSTEM_RESET) {
+ struct cg2900_chip_info *info = dev->c_data;
+ /*
+ * Don't wait till READ_SELFTESTS_RESULT is complete
+ * for clock users
+ */
+ dev_dbg(dev->dev,
+ "New main_state: CG2900_ACTIVE_BEFORE_SELFTEST\n");
+ info->main_state = CG2900_ACTIVE_BEFORE_SELFTEST;
+ wake_up_all(&clk_user_wait_queue);
+
+ pkt_handled =
+ handle_vs_system_reset_cmd_complete(dev, data);
+ } else if (op_code == CG2900_BT_OP_VS_BT_ENABLE)
pkt_handled = handle_vs_bt_enable_cmd_complete(dev,
data);
else if (op_code == CG2900_BT_OP_VS_READ_SELTESTS_RESULT)
@@ -2296,8 +2316,14 @@ static void chip_startup_finished(struct cg2900_chip_info *info, int err)
wake_up_all(&main_wait_queue);
- if (err)
+ if (err) {
+ /*
+ * This will wakeup clock user too
+ * if it started the initialization process
+ */
+ wake_up_all(&clk_user_wait_queue);
return;
+ }
if (!info->chip_dev->t_cb.chip_startup_finished)
dev_dbg(BOOT_DEV, "chip_startup_finished callback not found\n");
@@ -2328,6 +2354,7 @@ static int cg2900_open(struct cg2900_user_data *user)
struct cg2900_chip_info *info;
struct list_head *cursor;
struct cg2900_channel_item *tmp;
+ enum main_state state_to_check = CG2900_ACTIVE;
BUG_ON(!main_info);
@@ -2427,18 +2454,30 @@ static int cg2900_open(struct cg2900_user_data *user)
cg2900_create_work_item(info->wq, work_load_patch_and_settings,
dev);
- dev_dbg(user->dev, "Wait up to 15 seconds for chip to start\n");
- wait_event_timeout(main_wait_queue,
- (CG2900_ACTIVE == info->main_state ||
- CG2900_IDLE == info->main_state),
- msecs_to_jiffies(CHIP_STARTUP_TIMEOUT));
- if (CG2900_ACTIVE != info->main_state) {
- dev_err(user->dev, "CG2900 driver failed to start\n");
+ dev_dbg(user->dev, "Wait 15sec for chip to start\n");
+ if (user->is_clk_user) {
+ dev_dbg(user->dev, "Clock user is Waiting here\n");
+ wait_event_timeout(clk_user_wait_queue,
+ CG2900_ACTIVE_BEFORE_SELFTEST
+ == info->main_state,
+ msecs_to_jiffies(CHIP_STARTUP_TIMEOUT));
+
+ state_to_check = CG2900_ACTIVE_BEFORE_SELFTEST;
+ } else {
+ dev_dbg(user->dev, "Not a Clock user\n");
+ wait_event_timeout(main_wait_queue,
+ (CG2900_ACTIVE == info->main_state ||
+ CG2900_IDLE == info->main_state),
+ msecs_to_jiffies(CHIP_STARTUP_TIMEOUT));
+ }
+
+ if (state_to_check != info->main_state) {
+ dev_err(user->dev, "CG2900 init failed\n");
if (dev->t_cb.close)
dev->t_cb.close(dev);
- dev_dbg(user->dev, "New main_state: CG2900_IDLE\n");
+ dev_dbg(user->dev, "main_state: CG2900_IDLE\n");
info->main_state = CG2900_IDLE;
err = -EIO;
goto err_free_list_item;
diff --git a/drivers/staging/cg2900/mfd/cg2900_core.c b/drivers/staging/cg2900/mfd/cg2900_core.c
index 6ac27748e44..b1f34d71eec 100644
--- a/drivers/staging/cg2900/mfd/cg2900_core.c
+++ b/drivers/staging/cg2900/mfd/cg2900_core.c
@@ -354,9 +354,6 @@ static void work_hw_registered(struct work_struct *work)
if (dev->t_cb.set_chip_power)
dev->t_cb.set_chip_power(dev, true);
- /* Wait 100ms before continuing to be sure that the chip is ready */
- schedule_timeout_killable(msecs_to_jiffies(CHIP_READY_TIMEOUT));
-
/* Set our function to receive data from chip */
dev->c_cb.data_from_chip = cg2900_data_from_chip;