aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeo Hall <teo.hall@freescale.com>2015-10-30 09:00:36 -0500
committerTeo Hall <teo.hall@freescale.com>2015-11-02 15:31:09 -0600
commit52234ae38e6e4f2b3452d807dd1c1e199be6350c (patch)
treed8b4dae480a6550d131b02ee2faf809226fbfaf3
parent58983b6522c324affdbbeaa5b7b192a673c615a7 (diff)
downloadfreescale-52234ae38e6e4f2b3452d807dd1c1e199be6350c.tar.gz
MLK-11262-2: ARM: imx: Add MU messages for LPM messages
add LPM messages for: -M4 reporting state -M4 Request/Release High Bus Freq -A7 tell M4 it is ready Signed-off-by: Teo Hall <teo.hall@freescale.com>
-rw-r--r--arch/arm/mach-imx/common.h2
-rw-r--r--arch/arm/mach-imx/mu.c47
2 files changed, 45 insertions, 4 deletions
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index a41a00058bf..cb3873fb211 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -101,6 +101,8 @@ bool imx_src_is_m4_enabled(void);
void mcc_receive_from_mu_buffer(unsigned int index, unsigned int *data);
void mcc_send_via_mu_buffer(unsigned int index, unsigned int data);
bool imx_mu_is_m4_in_low_freq(void);
+bool imx_mu_is_m4_in_stop(void);
+int imx_mu_lpm_ready(bool ready);
unsigned int imx_gpcv2_is_mf_mix_off(void);
int imx_gpc_mf_power_on(unsigned int irq, unsigned int on);
#ifdef CONFIG_HAVE_IMX_GPCV2
diff --git a/arch/arm/mach-imx/mu.c b/arch/arm/mach-imx/mu.c
index 56ab9ce18a6..69ae71844e4 100644
--- a/arch/arm/mach-imx/mu.c
+++ b/arch/arm/mach-imx/mu.c
@@ -47,6 +47,11 @@
#define MU_LPM_M4_WAKEUP_ENABLE_MASK 0xF
#define MU_LPM_M4_WAKEUP_ENABLE_SHIFT 0x0
+#define MU_LPM_M4_A7_READY 0xFFFFAAAA
+#define MU_LPM_M4_RUN_MODE 0x5A5A0001
+#define MU_LPM_M4_WAIT_MODE 0x5A5A0002
+#define MU_LPM_M4_STOP_MODE 0x5A5A0003
+
struct imx_mu_rpmsg_box {
const char *name;
struct blocking_notifier_head notifier;
@@ -62,6 +67,7 @@ static u32 m4_message;
static struct delayed_work mu_work, rpmsg_work;
static u32 m4_wake_irqs[4];
static bool m4_freq_low;
+static bool m4_in_stop;
struct imx_sema4_mutex *mcc_shm_ptr;
unsigned int imx_mcc_buffer_freed = 0, imx_mcc_buffer_queued = 0;
@@ -70,6 +76,11 @@ static DECLARE_WAIT_QUEUE_HEAD(buffer_freed_wait_queue);
/* Used for blocking recv */
static DECLARE_WAIT_QUEUE_HEAD(buffer_queued_wait_queue);
+bool imx_mu_is_m4_in_stop(void)
+{
+ return m4_in_stop;
+}
+
bool imx_mu_is_m4_in_low_freq(void)
{
return m4_freq_low;
@@ -163,10 +174,18 @@ static void mu_work_handler(struct work_struct *work)
pr_debug("receive M4 message 0x%x\n", m4_message);
switch (m4_message) {
+ case MU_LPM_M4_RUN_MODE:
+ case MU_LPM_M4_WAIT_MODE:
+ m4_in_stop = false;
+ break;
+ case MU_LPM_M4_STOP_MODE:
+ m4_in_stop = true;
+ break;
case MU_LPM_M4_REQUEST_HIGH_BUS:
request_bus_freq(BUS_FREQ_HIGH);
#ifdef CONFIG_SOC_IMX6SX
- imx6sx_set_m4_highfreq(true);
+ if (cpu_is_imx6sx())
+ imx6sx_set_m4_highfreq(true);
#endif
imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
MU_LPM_BUS_HIGH_READY_FOR_M4);
@@ -175,10 +194,12 @@ static void mu_work_handler(struct work_struct *work)
case MU_LPM_M4_RELEASE_HIGH_BUS:
release_bus_freq(BUS_FREQ_HIGH);
#ifdef CONFIG_SOC_IMX6SX
- imx6sx_set_m4_highfreq(false);
+ if (cpu_is_imx6sx()) {
+ imx6sx_set_m4_highfreq(false);
+ imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
+ MU_LPM_M4_FREQ_CHANGE_READY);
+ }
#endif
- imx_mu_send_message(MU_LPM_HANDSHAKE_INDEX,
- MU_LPM_M4_FREQ_CHANGE_READY);
m4_freq_low = true;
break;
default:
@@ -219,6 +240,18 @@ int imx_mu_rpmsg_send(unsigned int rpmsg)
return imx_mu_send_message(MU_RPMSG_HANDSHAKE_INDEX, rpmsg);
}
+int imx_mu_lpm_ready(bool ready)
+{
+ u32 val;
+
+ val = readl_relaxed(mu_base + MU_ACR);
+ if (ready)
+ writel_relaxed(val | BIT(0), mu_base + MU_ACR);
+ else
+ writel_relaxed(val & ~BIT(0), mu_base + MU_ACR);
+ return 0;
+}
+
int imx_mu_rpmsg_register_nb(const char *name, struct notifier_block *nb)
{
if ((name == NULL) || (nb == NULL))
@@ -566,6 +599,12 @@ static int imx_mu_probe(struct platform_device *pdev)
/* enable the bit31(GIE3) of MU_ACR, used for MCC */
writel_relaxed(readl_relaxed(mu_base + MU_ACR) | BIT(31),
mu_base + MU_ACR);
+ INIT_DELAYED_WORK(&mu_work, mu_work_handler);
+ INIT_DELAYED_WORK(&rpmsg_work, rpmsg_work_handler);
+ /* enable the bit26(RIE1) of MU_ACR */
+ writel_relaxed(readl_relaxed(mu_base + MU_ACR) |
+ BIT(26) | BIT(27), mu_base + MU_ACR);
+ imx_mu_lpm_ready(true);
} else {
INIT_DELAYED_WORK(&mu_work, mu_work_handler);