diff options
author | Arun Murthy <arun.murthy@stericsson.com> | 2011-10-04 12:21:07 +0530 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 10:59:20 +0200 |
commit | 895997faaaff7ab9fb3f19cf9f6c981e5b337bc6 (patch) | |
tree | 16ecccceaa6473febfa2eae9e23ae69fd608ca2f | |
parent | f6a20dd13d85196d2fd4f5a00c393c164bd99a62 (diff) |
mfd: db5500-prcmu: add modem_req and modem_rel API
When APE has some messages to send to modem, APE will issue a modem_req
and then start sending the messages to modem.
Once APE is done with sending messages to modem, it will send modem_rel
to free the ape-modem communication protocol.
This protocol will be used to achieve APE-Modem power management.
ST-Ericsson Linux next: NA
ST-Ericsson ID: 350108
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I331654967ddd4b77818f7f4a8427ea8c63fd90a8
Signed-off-by: Arun Murthy <arun.murthy@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32722
Reviewed-by: QATOOLS
Reviewed-by: Rabin VINCENT <rabin.vincent@stericsson.com>
-rw-r--r-- | drivers/mfd/db5500-prcmu-regs.h | 6 | ||||
-rw-r--r-- | drivers/mfd/db5500-prcmu.c | 71 | ||||
-rw-r--r-- | include/linux/mfd/db5500-prcmu.h | 15 | ||||
-rw-r--r-- | include/linux/mfd/dbx500-prcmu.h | 2 |
4 files changed, 89 insertions, 5 deletions
diff --git a/drivers/mfd/db5500-prcmu-regs.h b/drivers/mfd/db5500-prcmu-regs.h index e8aa2901478..30234a86263 100644 --- a/drivers/mfd/db5500-prcmu-regs.h +++ b/drivers/mfd/db5500-prcmu-regs.h @@ -123,4 +123,10 @@ #define PRCM_RESOUTN_SET_OFFSET 0x214 #define PRCM_RESOUTN_CLR_OFFSET 0x218 +/* APE - Modem Registers */ +#define PRCM_HOSTACCESS_REQ 0x334 +/* APE - Modem register bit maipulation */ +#define PRCM_HOSTACCESS_REQ_BIT BIT(0) +#define PRCM_APE_ACK 0x49c +#define PRCM_APE_ACK_BIT 0x01 #endif diff --git a/drivers/mfd/db5500-prcmu.c b/drivers/mfd/db5500-prcmu.c index 4ab200498c5..3f1e481fb11 100644 --- a/drivers/mfd/db5500-prcmu.c +++ b/drivers/mfd/db5500-prcmu.c @@ -362,12 +362,14 @@ static u32 prcmu_wakeup_bit[NUM_PRCMU_WAKEUP_INDICES] = { * @lock The transaction lock. * @dbb_irqs_lock lock used for (un)masking DBB wakeup interrupts * @mask_work: Work structure used for (un)masking wakeup interrupts. + * @ac_wake_lock: mutex to lock modem_req and modem_rel * @req: Request data that need to persist between requests. */ static struct { spinlock_t lock; spinlock_t dbb_irqs_lock; struct work_struct mask_work; + struct mutex ac_wake_lock; struct { u32 dbb_irqs; u32 dbb_wakeups; @@ -532,9 +534,73 @@ static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { CLK_MGT_ENTRY(SVACLK, false), }; -bool db5500_prcmu_is_ac_wake_requested(void) +static atomic_t modem_req_state = ATOMIC_INIT(0); + +bool db5500_prcmu_is_modem_requested(void) { - return false; + return (atomic_read(&modem_req_state) != 0); +} + +/** + * prcmu_modem_req - APE requests Modem to wake up + * + * Whenever APE wants to send message to the modem, it will have to call this + * function to make sure that modem is awake. + */ +void prcmu_modem_req(void) +{ + u32 val; + + mutex_lock(&mb0_transfer.ac_wake_lock); + + val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); + if (val & PRCM_HOSTACCESS_REQ_BIT) + goto unlock_and_return; + + writel((val | PRCM_HOSTACCESS_REQ_BIT), + (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); + atomic_set(&modem_req_state, 1); + +unlock_and_return: + mutex_unlock(&mb0_transfer.ac_wake_lock); + +} + +/** + * prcmu_modem_rel - APE has no more messages to send and hence releases modem. + * + * APE to Modem communication is initiated by modem_req and once the + * communication is completed, APE sends modem_rel to complete the protocol. + */ +void prcmu_modem_rel(void) +{ + u32 val; + + mutex_lock(&mb0_transfer.ac_wake_lock); + + val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); + if (!(val & PRCM_HOSTACCESS_REQ_BIT)) + goto unlock_and_return; + + writel((val & ~PRCM_HOSTACCESS_REQ_BIT), + (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); + + atomic_set(&modem_req_state, 0); + +unlock_and_return: + mutex_unlock(&mb0_transfer.ac_wake_lock); +} + +/** + * prcm_ape_ack - send an acknowledgement to modem + * + * On ape receiving ape_req, APE will have to acknowledge for the interrupt + * received. This function will send the acknowledgement by writing to the + * prcmu register and an interrupt is trigerred to modem. + */ +void prcmu_ape_ack(void) +{ + writel(PRCM_APE_ACK_BIT, (_PRCMU_BASE + PRCM_APE_ACK)); } /** @@ -1933,6 +1999,7 @@ void __init db5500_prcmu_early_init(void) tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE); spin_lock_init(&mb0_transfer.lock); spin_lock_init(&mb0_transfer.dbb_irqs_lock); + mutex_init(&mb0_transfer.ac_wake_lock); mutex_init(&mb1_transfer.lock); init_completion(&mb1_transfer.work); mutex_init(&mb2_transfer.lock); diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h index ffbd415e6c7..8b8470cb24e 100644 --- a/include/linux/mfd/db5500-prcmu.h +++ b/include/linux/mfd/db5500-prcmu.h @@ -27,7 +27,12 @@ int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, int db5500_prcmu_config_esram0_deep_sleep(u8 state); void db5500_prcmu_system_reset(u16 reset_code); u16 db5500_prcmu_get_reset_code(void); -bool db5500_prcmu_is_ac_wake_requested(void); +#ifdef CONFIG_UX500_SOC_DB5500 +void prcmu_modem_req(void); +void prcmu_modem_rel(void); +void prcmu_ape_ack(void); +#endif +bool db5500_prcmu_is_modem_requested(void); int db5500_prcmu_set_arm_opp(u8 opp); int db5500_prcmu_get_arm_opp(void); int db5500_prcmu_set_ape_opp(u8 opp); @@ -136,11 +141,17 @@ static inline u16 db5500_prcmu_get_reset_code(void) return 0; } -static inline bool db5500_prcmu_is_ac_wake_requested(void) +static inline bool db5500_prcmu_is_modem_requested(void) { return 0; } +#ifdef CONFIG_UX500_SOC_DB5500 +static void prcmu_ape_ack(void) {} +static void prcmu_modem_req(void) {} +static void prcmu_modem_rel(void) {} +#endif + static inline int db5500_prcmu_set_arm_opp(u8 opp) { return 0; diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 39062eca535..4baf982fabf 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -460,7 +460,7 @@ static inline void prcmu_modem_reset(void) static inline bool prcmu_is_ac_wake_requested(void) { if (cpu_is_u5500()) - return db5500_prcmu_is_ac_wake_requested(); + return db5500_prcmu_is_modem_requested(); else return db8500_prcmu_is_ac_wake_requested(); } |