Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 89a4d1b7 authored by Prakash Gupta's avatar Prakash Gupta
Browse files

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: default avatarCharan Teja Reddy <charante@codeaurora.org>
Signed-off-by: default avatarPrakash Gupta <guptap@codeaurora.org>
parent 6f79272a
Loading
Loading
Loading
Loading
+52 −3
Original line number Diff line number Diff line
@@ -19,7 +19,9 @@
#include <linux/mailbox/qmp.h>
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
#include <soc/qcom/rpm-smd.h>

#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) {
		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 @@ static int send_msg(struct memory_notify *mn, bool online, int count)
	while (i-- > 0) {
		int ret;

		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;