summaryrefslogtreecommitdiff
path: root/drivers/staging/cg2900/mfd/cg2900_chip.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/cg2900/mfd/cg2900_chip.c')
-rw-r--r--drivers/staging/cg2900/mfd/cg2900_chip.c67
1 files changed, 53 insertions, 14 deletions
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;