/*
 * Copyright © 2015 Broadcom Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation (the "GPL").
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * A copy of the GPL is available at
 * http://www.broadcom.com/licenses/GPLv2.php or from the Free Software
 * Foundation at https://www.gnu.org/licenses/ .
 */

#define pr_fmt(fmt) "bmem: " fmt

#include <asm/setup.h>
#include <linux/ctype.h>
#include <linux/device.h>
#include <linux/ioport.h>
#include <linux/memblock.h>
#include <linux/platform_device.h>
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/brcmstb/bmem.h>
#include <linux/brcmstb/memory_api.h>

#if 0
#define DBG pr_info
#else
#define DBG(...) /* */
#endif

#define MAX_BMEM_REGIONS	8

struct bmem_region {
	phys_addr_t		addr;
	phys_addr_t		size;
	bool			valid;
};

static struct bmem_region bmem_regions[MAX_BMEM_REGIONS];
static struct platform_device *brcmstb_pdev;
static unsigned int n_bmem_regions;
static bool bmem_disabled;

/***********************************************************************
 * BMEM (reserved A/V buffer memory) support
 ***********************************************************************/

static int __init __bmem_setup(phys_addr_t addr, phys_addr_t size)
{
	if (n_bmem_regions == MAX_BMEM_REGIONS) {
		pr_warn_once("too many regions, ignoring extras\n");
		return -E2BIG;
	}

	bmem_regions[n_bmem_regions].addr = addr;
	bmem_regions[n_bmem_regions].size = size;
	n_bmem_regions++;
	return 0;
}

/*
 * Parses command line for bmem= options
 */
static int __init bmem_setup(char *str)
{
	phys_addr_t addr = 0, size;
	char *orig_str = str;
	int ret;

	size = memparse(str, &str);
	if (*str == '@')
		addr = memparse(str + 1, &str);

	if ((addr & ~PAGE_MASK) || (size & ~PAGE_MASK)) {
		pr_warn("ignoring invalid range '%s' (is it missing an 'M' suffix?)\n",
				orig_str);
		return 0;
	}

	if (size == 0) {
		pr_info("disabling reserved memory\n");
		bmem_disabled = true;
		return 0;
	}

	ret = __bmem_setup(addr, size);
	if (!ret)
		brcmstb_memory_override_defaults = true;
	return ret;
}
early_param("bmem", bmem_setup);

/*
 * Returns index if the supplied range falls entirely within a bmem region
 */
int bmem_find_region(phys_addr_t addr, phys_addr_t size)
{
	int i, idx = 0;

	for (i = 0; i < n_bmem_regions; i++) {
		if (!bmem_regions[i].valid)
			continue;
		if ((addr >= bmem_regions[i].addr) &&
		    ((addr + size) <=
			(bmem_regions[i].addr + bmem_regions[i].size))) {
			return idx;
		}
		idx++;
	}
	return -ENOENT;
}

/*
 * Finds the IDX'th valid bmem region, and fills in addr/size if it exists.
 * Returns 0 on success, <0 on failure.
 * Can pass in NULL for addr and/or size if you only care about return value.
 */
int bmem_region_info(int idx, phys_addr_t *addr, phys_addr_t *size)
{
	int i;

	for (i = 0; i < n_bmem_regions; i++) {
		if (!bmem_regions[i].valid)
			continue;
		if (!idx) {
			if (addr)
				*addr = bmem_regions[i].addr;
			if (size)
				*size = bmem_regions[i].size;
			return 0;
		}
		idx--;
	}
	return -ENOENT;
}

static void __init bmem_setup_defaults(void)
{
	int iter;

	for_each_bank(iter, &meminfo) {
		phys_addr_t start, size;

		if (n_bmem_regions == MAX_BMEM_REGIONS) {
			pr_warn_once("%s: too many regions, ignoring extras\n",
					__func__);
			return;
		}

		/* fill in start and size */
		if (brcmstb_memory_get_default_reserve(iter, &start, &size))
			continue;

		__bmem_setup(start, size);
	}
}

void __init bmem_reserve(void)
{
	int i;
	int ret;

	if (bmem_disabled) {
		n_bmem_regions = 0;
		return;
	}

	if (brcmstb_default_reserve == BRCMSTB_RESERVE_BMEM &&
			!n_bmem_regions &&
			!brcmstb_memory_override_defaults)
		bmem_setup_defaults();

	for (i = 0; i < n_bmem_regions; ++i) {
		ret = memblock_reserve(bmem_regions[i].addr,
				bmem_regions[i].size);
		if (ret) {
			pr_err("memblock_reserve(%pa, %pa) failed: %d\n",
					&bmem_regions[i].addr,
					&bmem_regions[i].size, ret);
		} else {
			bmem_regions[i].valid = true;
			pr_info("Reserved %lu MiB at %pa\n",
				(unsigned long) bmem_regions[i].size / SZ_1M,
				&bmem_regions[i].addr);
		}
	}
}

/*
 * Create /proc/iomem entries for bmem
 */
static int __init bmem_region_setup(void)
{
	int i, idx = 0;

	for (i = 0; i < n_bmem_regions; i++) {
		struct resource *r;
		char *name;

		if (!bmem_regions[i].valid)
			continue;

		r = kzalloc(sizeof(*r), GFP_KERNEL);
		name = kzalloc(16, GFP_KERNEL);
		if (!r || !name)
			break;

		sprintf(name, "bmem.%d", idx);
		r->start = bmem_regions[i].addr;
		r->end = bmem_regions[i].addr + bmem_regions[i].size - 1;
		r->flags = IORESOURCE_MEM;
		r->name = name;

		insert_resource(&iomem_resource, r);
		idx++;
	}
	return 0;
}
arch_initcall(bmem_region_setup);

static ssize_t show_bmem(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	unsigned long idx = 0;
	phys_addr_t addr = 0, size = 0;
	const char *name = attr->attr.name;
	int ret;

	while (*name != 0) {
		if (isdigit(*name)) {
			ret = kstrtoul(name, 10, &idx);
			if (ret)
				return ret;
			break;
		}
		name++;
	}
	bmem_region_info(idx, &addr, &size);

	return snprintf(buf, PAGE_SIZE, "%pa %pa\n", &addr, &size);
}

static int __init brcm_pdev_init(void)
{
	struct device *dev;
	int i;

	brcmstb_pdev = platform_device_alloc("brcmstb", -1);
	if (brcmstb_pdev == NULL) {
		pr_err("%s: can't allocate device\n", __func__);
		return -ENODEV;
	}
	platform_device_add(brcmstb_pdev);
	dev = &brcmstb_pdev->dev;

	/* create an attribute for each bmem region */
	for (i = 0; ; i++) {
		phys_addr_t addr, size;
		struct device_attribute *attr;
		char *name;

		if (bmem_region_info(i, &addr, &size) < 0)
			break;
		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
		if (attr == NULL)
			break;

		name = kzalloc(16, GFP_KERNEL);
		if (name == NULL)
			break;
		snprintf(name, 16, "bmem.%d", i);

		sysfs_attr_init(&attr->attr);
		attr->attr.name = name;
		attr->attr.mode = 0444;
		attr->show = show_bmem;

		if (device_create_file(dev, attr) != 0)
			WARN(1, "Can't create sysfs file\n");
	}

	return 0;
}
arch_initcall(brcm_pdev_init);
