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

Commit 83380d6b authored by Charan Teja Reddy's avatar Charan Teja Reddy
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>
parent c1b1f71e
Loading
Loading
Loading
Loading
+54 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -24,7 +24,9 @@
#include <linux/of.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox/qmp.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
@@ -32,6 +34,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

@@ -56,6 +59,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;

void record_stat(unsigned long sec, ktime_t delay, int mode)
@@ -85,6 +97,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;
@@ -103,6 +134,17 @@ static int aop_send_msg(unsigned long addr, bool online)
	return mbox_send_message(mailbox.mbox, &pkt);
}

static int send_msg(struct memory_notify *mn, bool online)
{
	int start = SECTION_ALIGN_DOWN(mn->start_pfn);

	if (is_rpm_controller)
		return mem_region_refresh_control(start, mn->nr_pages,
						  online);
	else
		return aop_send_msg(__pfn_to_phys(start), online);
}

static int mem_event_callback(struct notifier_block *self,
				unsigned long action, void *arg)
{
@@ -142,8 +184,9 @@ static int mem_event_callback(struct notifier_block *self,
			   idx) / sections_per_block].fail_count;
		cur = ktime_get();

		if (aop_send_msg(__pfn_to_phys(start), true))
			pr_err("PASR: AOP online request addr:0x%llx failed\n",
		if (send_msg(mn, true))
			pr_err("PASR: %s online request addr:0x%llx failed\n",
			       is_rpm_controller ? "RPM" : "AOP",
			       __pfn_to_phys(start));

		break;
@@ -163,8 +206,9 @@ static int mem_event_callback(struct notifier_block *self,
	case MEM_OFFLINE:
		pr_info("mem-offline: Offlined memory block mem%lu\n", sec_nr);

		if (aop_send_msg(__pfn_to_phys(start), false))
			pr_err("PASR: AOP offline request addr:0x%llx failed\n",
		if (send_msg(mn, false))
			pr_err("PASR: %s offline request addr:0x%llx failed\n",
			       is_rpm_controller ? "RPM" : "AOP",
			       __pfn_to_phys(start));

		delay = ktime_ms_delta(ktime_get(), cur);
@@ -347,6 +391,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;