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

Commit b0c2b454 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "clk: msm: mdss: update the procedure for storing DSI PLL codes"

parents 6792df69 eefbc43c
Loading
Loading
Loading
Loading
+52 −13
Original line number Diff line number Diff line
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, 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
@@ -19,6 +19,8 @@
#include <linux/clk/msm-clock-generic.h>
#include <linux/of_address.h>
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
#include <linux/memblock.h>

#include "mdss-pll.h"

@@ -329,12 +331,26 @@ clk_err:
	return rc;
}

static void mdss_pll_free_bootmem(u32 mem_addr, u32 size)
{
	unsigned long pfn_start, pfn_end, pfn_idx;

	pfn_start = mem_addr >> PAGE_SHIFT;
	pfn_end = (mem_addr + size) >> PAGE_SHIFT;
	for (pfn_idx = pfn_start; pfn_idx < pfn_end; pfn_idx++)
		free_reserved_page(pfn_to_page(pfn_idx));
}

static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev,
					struct mdss_pll_resources *pll_res)
{
	int rc = 0;
	struct device_node *pnode;
	void __iomem *addr;
	const u32 *addr;
	struct vm_struct *area;
	u64 size;
	u32 offsets[2];
	unsigned long virt_add;

	pnode = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
	if (IS_ERR_OR_NULL(pnode)) {
@@ -342,13 +358,29 @@ static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev,
		goto pnode_err;
	}

	/* get the physical address for pll codes */
	addr = of_iomap(pnode, 0);
	if (IS_ERR_OR_NULL(addr)) {
			rc = PTR_ERR(addr);
			pr_err("couldn't get dfps physical address\n");
	addr = of_get_address(pnode, 0, &size, NULL);
	if (!addr) {
		pr_err("failed to parse the dfps memory address\n");
		rc = -EINVAL;
		goto pnode_err;
	}
	/* maintain compatibility for 32/64 bit */
	offsets[0] = (u32) of_read_ulong(addr, 2);
	offsets[1] = (u32) size;

	area = get_vm_area(offsets[1], VM_IOREMAP);
	if (!area) {
		rc = -ENOMEM;
		goto dfps_mem_err;
	}

	virt_add = (unsigned long)area->addr;
	rc = ioremap_page_range(virt_add, (virt_add + offsets[1]),
			offsets[0], PAGE_KERNEL);
	if (rc) {
		rc = -ENOMEM;
		goto ioremap_err;
	}

	pll_res->dfps = kzalloc(sizeof(struct dfps_info), GFP_KERNEL);
	if (IS_ERR_OR_NULL(pll_res->dfps)) {
@@ -357,12 +389,19 @@ static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev,
		goto addr_err;
	}

	/* memcopy complete dfps structure from physical memory */
	memcpy_fromio(pll_res->dfps, addr, sizeof(struct dfps_info));
	/* memcopy complete dfps structure from kernel virtual memory */
	memcpy_fromio(pll_res->dfps, area->addr, sizeof(struct dfps_info));

addr_err:
	iounmap(addr);

	if (virt_add)
		unmap_kernel_range(virt_add, (unsigned long) size);
ioremap_err:
	if (area)
		vfree(area->addr);
dfps_mem_err:
	/* free the dfps memory here */
	memblock_free(offsets[0], offsets[1]);
	mdss_pll_free_bootmem(offsets[0], offsets[1]);
pnode_err:
	if (pnode)
		of_node_put(pnode);