summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNitin Dhingra <nitin.dhingra@stericsson.com>2011-12-23 10:57:33 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:05:57 +0200
commitb231eb1acabe59c01e7cf57e56b62048ff147f09 (patch)
treef376f7467214f23988ff638e9a01d80a7c05d2f7
parent15bbc7531477dc3d0a868b66bb69d28a768594c7 (diff)
CG2900: changing sleep timers
Reducing the sleep timer value from 10 sec to 150ms, to put CG29XX chip to sleep. and after 50ms checking CG29XX has gone to sleep then release the wakelocks for system to go in sleep mode. This will decrease the power consumption greatly. ST-Ericsson Linux next: NA ST-Ericsson ID: 375669 ST-Ericsson FOSS-OUT ID: trivial Change-Id: I48b8b2c3962747743fc8fef5288bcd05921be8f6 Signed-off-by: Nitin Dhingra <nitin.dhingra@stericsson.com> Depends-On: I0618c5f7e507b540907546d10fd217b046484263 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43737 Reviewed-by: Hemant GUPTA <hemant.gupta@stericsson.com> Reviewed-by: QATOOLS
-rw-r--r--drivers/staging/cg2900/bluetooth/cg2900_uart.c45
-rw-r--r--drivers/staging/cg2900/include/cg2900.h2
-rw-r--r--drivers/staging/cg2900/mfd/cg2900_core.c13
3 files changed, 48 insertions, 12 deletions
diff --git a/drivers/staging/cg2900/bluetooth/cg2900_uart.c b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
index 783b8327786..3c88ed6d18f 100644
--- a/drivers/staging/cg2900/bluetooth/cg2900_uart.c
+++ b/drivers/staging/cg2900/bluetooth/cg2900_uart.c
@@ -126,6 +126,16 @@
#define CG2900_BAUD_RATE_3250000 0x28
#define CG2900_BAUD_RATE_4000000 0x2B
+/**
+ * enum sleep_allowed_bits - bits indicating if sleep is allowed.
+ * @SLEEP_TTY_READY: Bit for checking if break can be applied using tty.
+ * @SLEEP_CORE_READY: Bit for checking if core is ready for sleep or not.
+ */
+enum sleep_allowed_bits {
+ SLEEP_TTY_READY,
+ SLEEP_CORE_READY
+};
+
/* GNSS */
struct gnss_hci_hdr {
__u8 op_code;
@@ -290,7 +300,7 @@ struct uart_delayed_work_struct {
* @wakeup_work: Wake-up work struct.
* @restart_sleep_work: Reschedule sleep_work and wake-up work struct.
* @sleep_state_lock: Used to protect chip state.
- * @sleep_allowed: Indicates if tty has functions needed for sleep mode.
+ * @sleep_flags: Indicates whether sleep mode is allowed.
* @tx_in_progress: Indicates data sending in progress.
* @rx_in_progress: Indicates data receiving in progress.
* @transmission_lock: Spin_lock to protect tx/rx_in_progress.
@@ -320,7 +330,7 @@ struct uart_info {
struct uart_work_struct wakeup_work;
struct uart_work_struct restart_sleep_work;
struct mutex sleep_state_lock;
- bool sleep_allowed;
+ unsigned long sleep_flags;
bool tx_in_progress;
bool rx_in_progress;
spinlock_t transmission_lock;
@@ -559,16 +569,22 @@ static void unset_cts_irq(struct uart_info *uart_info)
* Check all conditions for sleep and return sleep timeout.
* Return:
* 0: sleep not allowed.
- * other: Timeout value in ms.
+ * other: Timeout value in jiffies.
*/
static unsigned long get_sleep_timeout(struct uart_info *uart_info)
{
- unsigned long timeout_jiffies = cg2900_get_sleep_timeout();
+ unsigned long timeout_jiffies = 0;
+ bool check_sleep = false;
+ if (uart_info->sleep_state == CHIP_FALLING_ASLEEP)
+ check_sleep = true;
+
+ timeout_jiffies = cg2900_get_sleep_timeout(check_sleep);
if (timeout_jiffies &&
uart_info->hu &&
uart_info->hu->fd &&
- uart_info->sleep_allowed)
+ test_bit(SLEEP_TTY_READY, &uart_info->sleep_flags) &&
+ test_bit(SLEEP_CORE_READY, &uart_info->sleep_flags))
return timeout_jiffies;
return 0;
@@ -789,7 +805,7 @@ schedule_sleep_work:
error:
/* Disable sleep mode.*/
dev_err(MAIN_DEV, "Disable sleep mode\n");
- uart_info->sleep_allowed = false;
+ clear_bit(SLEEP_CORE_READY, &uart_info->sleep_flags);
mutex_unlock(&(uart_info->sleep_state_lock));
}
@@ -1448,6 +1464,12 @@ static void uart_set_chip_power(struct cg2900_chip_dev *dev, bool chip_on)
dev_dbg(MAIN_DEV,
"New sleep_state: CHIP_POWERED_DOWN\n");
uart_info->sleep_state = CHIP_POWERED_DOWN;
+ /*
+ * This is to ensure when chip is switched
+ * on next time sleep_flags is again set with
+ * SLEEP_CORE_READY when startup is done properly
+ */
+ clear_bit(SLEEP_CORE_READY, &uart_info->sleep_flags);
}
cg2900_disable_regulator(uart_info);
@@ -1487,6 +1509,11 @@ static void uart_chip_startup_finished(struct cg2900_chip_dev *dev)
struct uart_info *uart_info = dev_get_drvdata(dev->dev);
unsigned long timeout_jiffies = get_sleep_timeout(uart_info);
+ /*
+ * Chip startup is done, now chip is allowed
+ * to go to sleep
+ */
+ set_bit(SLEEP_CORE_READY, &uart_info->sleep_flags);
/* Schedule work to put the chip and transport to sleep. */
if (timeout_jiffies)
queue_delayed_work(uart_info->wq, &uart_info->sleep_work.work,
@@ -1867,10 +1894,10 @@ static int cg2900_hu_open(struct hci_uart *hu)
err);
if (hu->tty->ops->tiocmget && hu->tty->ops->break_ctl)
- uart_info->sleep_allowed = true;
+ set_bit(SLEEP_TTY_READY, &uart_info->sleep_flags);
else {
dev_err(MAIN_DEV, "Sleep mode not available\n");
- uart_info->sleep_allowed = false;
+ clear_bit(SLEEP_TTY_READY, &uart_info->sleep_flags);
}
return err;
@@ -1893,6 +1920,8 @@ static int cg2900_hu_close(struct hci_uart *hu)
BUG_ON(!uart_info);
BUG_ON(!uart_info->wq);
+ clear_bit(SLEEP_TTY_READY, &uart_info->sleep_flags);
+
/* Purge any stored sk_buffers */
skb_queue_purge(&uart_info->tx_queue);
diff --git a/drivers/staging/cg2900/include/cg2900.h b/drivers/staging/cg2900/include/cg2900.h
index eddfb71c8e4..99ac90da58f 100644
--- a/drivers/staging/cg2900/include/cg2900.h
+++ b/drivers/staging/cg2900/include/cg2900.h
@@ -277,7 +277,7 @@ extern int cg2900_register_chip_driver(struct cg2900_id_callbacks *cb);
extern void cg2900_deregister_chip_driver(struct cg2900_id_callbacks *cb);
extern int cg2900_register_trans_driver(struct cg2900_chip_dev *dev);
extern int cg2900_deregister_trans_driver(struct cg2900_chip_dev *dev);
-extern unsigned long cg2900_get_sleep_timeout(void);
+extern unsigned long cg2900_get_sleep_timeout(bool check_sleep);
#endif /* __KERNEL__ */
#endif /* _CG2900_H_ */
diff --git a/drivers/staging/cg2900/mfd/cg2900_core.c b/drivers/staging/cg2900/mfd/cg2900_core.c
index b1f34d71eec..fe28ab6b7ae 100644
--- a/drivers/staging/cg2900/mfd/cg2900_core.c
+++ b/drivers/staging/cg2900/mfd/cg2900_core.c
@@ -55,7 +55,9 @@
*/
#define CHIP_READY_TIMEOUT (100) /* ms */
#define REVISION_READOUT_TIMEOUT (500) /* ms */
-#define SLEEP_TIMEOUT_MS (10000) /* ms */
+#define SLEEP_TIMEOUT_MS (150) /* ms */
+/* Timeout value to check CTS line for low power */
+#define READY_FOR_SLEEP_TIMEOUT_MS (50) /* ms */
/**
* enum boot_state - BOOT-state for CG2900 Core.
@@ -592,16 +594,21 @@ EXPORT_SYMBOL_GPL(cg2900_deregister_trans_driver);
/**
* cg2900_get_sleep_timeout() - Return sleep timeout in jiffies.
+ * @check_sleep: If we want to check whether chip has gone
+ * to sleep then use lesser timeout value
*
* Returns:
* Sleep timeout in jiffies. 0 means that sleep timeout shall not be used.
*/
-unsigned long cg2900_get_sleep_timeout(void)
+unsigned long cg2900_get_sleep_timeout(bool check_sleep)
{
if (!sleep_timeout_ms)
return 0;
- return msecs_to_jiffies(sleep_timeout_ms);
+ if (check_sleep)
+ return msecs_to_jiffies(READY_FOR_SLEEP_TIMEOUT_MS);
+ else
+ return msecs_to_jiffies(sleep_timeout_ms);
}
EXPORT_SYMBOL_GPL(cg2900_get_sleep_timeout);