From 89a4d1b739cf2b21e4f77bc2e729e1d28bdf713a Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Fri, 1 Mar 2019 14:43:27 +0530 Subject: [PATCH] soc: qcom: mem-offline: add pasr support for rpm-smd based targets Some targets have RPM than RPMh controllers where the message format to the controller is different. Add support for it. Change-Id: Icb1056badac7ef17df2a52a5f725d9f8aa96503e Signed-off-by: Charan Teja Reddy Signed-off-by: Prakash Gupta --- drivers/soc/qcom/mem-offline.c | 55 ++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/soc/qcom/mem-offline.c b/drivers/soc/qcom/mem-offline.c index aefe453281fd..210dac4520b8 100644 --- a/drivers/soc/qcom/mem-offline.c +++ b/drivers/soc/qcom/mem-offline.c @@ -19,7 +19,9 @@ #include #include #include +#include +#define RPM_DDR_REQ 0x726464 #define AOP_MSG_ADDR_MASK 0xffffffff #define AOP_MSG_ADDR_HIGH_SHIFT 32 #define MAX_LEN 96 @@ -27,6 +29,7 @@ static unsigned long start_section_nr, end_section_nr; static struct kobject *kobj; static unsigned int offline_granule, sections_per_block; +static bool is_rpm_controller; #define MODULE_CLASS_NAME "mem-offline" #define BUF_LEN 100 @@ -53,6 +56,15 @@ static struct mem_offline_mailbox { struct mbox_chan *mbox; } mailbox; +struct memory_refresh_request { + u64 start; /* Lower bit signifies action + * 0 - disable self-refresh + * 1 - enable self-refresh + * upper bits are for base address + */ + u32 size; /* size of memory region */ +}; + static struct section_stat *mem_info; static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) @@ -119,6 +131,25 @@ void record_stat(unsigned long sec, ktime_t delay, int mode) mem_info[blk_nr].last_recorded_time = delay; } +static int mem_region_refresh_control(unsigned long pfn, + unsigned long nr_pages, + bool enable) +{ + struct memory_refresh_request mem_req; + struct msm_rpm_kvp rpm_kvp; + + mem_req.start = enable; + mem_req.start |= pfn << PAGE_SHIFT; + mem_req.size = nr_pages * PAGE_SIZE; + + rpm_kvp.key = RPM_DDR_REQ; + rpm_kvp.data = (void *)&mem_req; + rpm_kvp.length = sizeof(mem_req); + + return msm_rpm_send_message(MSM_RPM_CTX_ACTIVE_SET, RPM_DDR_REQ, 0, + &rpm_kvp, 1); +} + static int aop_send_msg(unsigned long addr, bool online) { struct qmp_pkt pkt; @@ -163,9 +194,16 @@ static int send_msg(struct memory_notify *mn, bool online, int count) start = section_nr_to_pfn(base_sec_nr); for (i = 0; i < count; ++i) { - ret = aop_send_msg(__pfn_to_phys(start), online); + if (is_rpm_controller) + ret = mem_region_refresh_control(start, + segment_size >> PAGE_SHIFT, + online); + else + ret = aop_send_msg(__pfn_to_phys(start), online); + if (ret) { - pr_err("PASR: AOP %s request addr:0x%llx failed\n", + pr_err("PASR: %s %s request addr:0x%llx failed\n", + is_rpm_controller ? "RPM" : "AOP", online ? "online" : "offline", __pfn_to_phys(start)); goto undo; @@ -180,7 +218,13 @@ undo: while (i-- > 0) { int ret; - ret = aop_send_msg(__pfn_to_phys(start), !online); + if (is_rpm_controller) + ret = mem_region_refresh_control(start, + segment_size >> PAGE_SHIFT, + !online); + else + ret = aop_send_msg(__pfn_to_phys(start), !online); + if (ret) panic("Failed to completely online/offline a hotpluggable segment. A quasi state of memblock can cause randomn system failures."); start = __phys_to_pfn(__pfn_to_phys(start) + segment_size); @@ -530,6 +574,11 @@ static int mem_parse_dt(struct platform_device *pdev) return -EINVAL; } + if (!of_find_property(node, "mboxes", NULL)) { + is_rpm_controller = true; + return 0; + } + mailbox.cl.dev = &pdev->dev; mailbox.cl.tx_block = true; mailbox.cl.tx_tout = 1000;