msm: ocmem: Ocmem staging while turning memory on
The HPG is updated to power up memories one cbc at a time
and stagger the core and peripheral power controls. Update
the ocmem driver to reflect this staggering.
CRs-Fixed: 478540
Change-Id: I4bfe06500af50f254e9efddb8f5c8b79059a1fc9
Signed-off-by: Neeti Desai <neetid@codeaurora.org>
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 4ea1de9..4ed4eda 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -97,9 +97,12 @@
#define REGION_SLEEP_PERI_ON 0x00007777
#define REGION_DEFAULT_OFF REGION_SLEEP_NO_RETENTION
-#define REGION_DEFAULT_ON REGION_NORMAL_PASSTHROUGH
+#define REGION_DEFAULT_ON REGION_FORCE_CORE_ON
#define REGION_DEFAULT_RETENTION REGION_SLEEP_PERI_OFF
+#define REGION_STAGING_SET(x) (REGION_SLEEP_PERI_OFF & (0xF << (x * 0x4)))
+#define REGION_ON_SET(x) (REGION_DEFAULT_OFF & (0xF << (x * 0x4)))
+
enum rpm_macro_state {
rpm_macro_off = 0x0,
rpm_macro_retain,
@@ -195,6 +198,51 @@
return state;
}
+#ifndef CONFIG_MSM_OCMEM_POWER_DISABLE
+static int commit_region_staging(unsigned region_num, unsigned start_m,
+ unsigned new_state)
+{
+ int rc = -1;
+ unsigned state = 0x0;
+ unsigned read_state = 0x0;
+ unsigned curr_state = 0x0;
+
+ if (region_num >= num_regions)
+ return -EINVAL;
+
+ if (rpm_power_control)
+ return 0;
+ else {
+ if (new_state != REGION_DEFAULT_OFF) {
+ curr_state = read_region_state(region_num);
+ state = curr_state | REGION_STAGING_SET(start_m);
+ rc = ocmem_write(state,
+ ocmem_base + PSCGC_CTL_n(region_num));
+ /* Barrier to commit the region state */
+ mb();
+ read_state = read_region_state(region_num);
+ if (new_state == REGION_DEFAULT_ON) {
+ curr_state = read_region_state(region_num);
+ state = curr_state ^ REGION_ON_SET(start_m);
+ rc = ocmem_write(state,
+ ocmem_base + PSCGC_CTL_n(region_num));
+ /* Barrier to commit the region state */
+ mb();
+ read_state = read_region_state(region_num);
+ }
+ } else {
+ curr_state = read_region_state(region_num);
+ state = curr_state ^ REGION_STAGING_SET(start_m);
+ rc = ocmem_write(state,
+ ocmem_base + PSCGC_CTL_n(region_num));
+ /* Barrier to commit the region state */
+ mb();
+ read_state = read_region_state(region_num);
+ }
+ }
+ return 0;
+}
+#endif
/* Returns the current state of a OCMEM macro that belongs to a region */
static int read_macro_state(unsigned region_num, unsigned macro_num)
@@ -948,9 +996,11 @@
apply_macro_vote(id, i, j,
hw_macro_state(new_state));
aggregate_macro_state(i, j);
+ commit_region_staging(i, j, new_state);
}
aggregate_region_state(i);
- commit_region_state(i);
+ if (rpm_power_control)
+ commit_region_state(i);
len -= region_size;
/* If we voted ON/retain the banks must never be OFF */
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 8afe695..a14b960 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -1515,6 +1515,18 @@
pr_err("ocmem: Failed to unmap %p\n", req);
goto free_fail;
}
+ /* Turn off the memory */
+ if (req->req_sz != 0) {
+
+ offset = phys_to_offset(req->req_start);
+ rc = ocmem_memory_off(req->owner, offset,
+ req->req_sz);
+
+ if (rc < 0) {
+ pr_err("Failed to switch OFF memory macros\n");
+ goto free_fail;
+ }
+ }
rc = do_free(req);
if (rc < 0) {
@@ -1525,21 +1537,19 @@
pr_debug("request %p was already shrunk to 0\n", req);
}
- /* Turn off the memory */
- if (req->req_sz != 0) {
+ if (!TEST_STATE(req, R_FREE)) {
+ /* Turn off the memory */
+ if (req->req_sz != 0) {
- offset = phys_to_offset(req->req_start);
+ offset = phys_to_offset(req->req_start);
+ rc = ocmem_memory_off(req->owner, offset, req->req_sz);
- rc = ocmem_memory_off(req->owner, offset, req->req_sz);
-
- if (rc < 0) {
- pr_err("Failed to switch OFF memory macros\n");
- goto free_fail;
+ if (rc < 0) {
+ pr_err("Failed to switch OFF memory macros\n");
+ goto free_fail;
+ }
}
- }
-
- if (!TEST_STATE(req, R_FREE)) {
/* free the allocation */
rc = do_free(req);
if (rc < 0)