summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornitin.dhingra <nitin.dhingra@stericsson.com>2011-11-16 16:22:19 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:05:57 +0200
commitba58062a85795460be0658d5c4930b103eb15de2 (patch)
treec7e5dd7ee0ad4e0975287a3a01d4066a53b5c692
parent07694d213b343410cd3c7461f54ab29d2027fd88 (diff)
cg2900: Code optimizations for CG2900 init time
Some general code optimizations during intialization done. Also we are releasing clock user like WLAN earlier as READ SELF TEST is not required for WLAN functionality. All these optimizations are done to reduce CG2900 init time which will also impact WLAN start-up time. Also ESD Clamp workaround has been removed from the code completely. This is not required anymore. ST-Ericsson Linux next: NA ST-Ericsson ID: 370603 ST-Ericsson FOSS-OUT ID: trivial Change-Id: I7895e21193d20d24ff65a51ff3591108d575399c Signed-off-by: Nitin Dhingra <nitin.dhingra@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37998 Reviewed-by: QATOOLS
-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;