Commit 7090d2f1 authored by Vincent Whitchurch's avatar Vincent Whitchurch Committed by Miquel Raynal
Browse files

mtd: phram: Allow probing via reserved-memory



Allow phram to be probed from the devicetree.  It expects to be in a
reserved-memory node as documented by the bindings.  This allows things
like partitioning to be specified via the devicetree.

Signed-off-by: default avatarVincent Whitchurch <vincent.whitchurch@axis.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20220412135302.1682890-4-vincent.whitchurch@axis.com
parent 4e969459
Loading
Loading
Loading
Loading
+63 −4
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <asm/div64.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/of.h>

struct phram_mtd_list {
	struct mtd_info mtd;
@@ -89,8 +92,10 @@ static void unregister_devices(void)
	}
}

static int register_device(char *name, phys_addr_t start, size_t len, uint32_t erasesize)
static int register_device(struct platform_device *pdev, const char *name,
			   phys_addr_t start, size_t len, uint32_t erasesize)
{
	struct device_node *np = pdev ? pdev->dev.of_node : NULL;
	struct phram_mtd_list *new;
	int ret = -ENOMEM;

@@ -119,13 +124,19 @@ static int register_device(char *name, phys_addr_t start, size_t len, uint32_t e
	new->mtd.erasesize = erasesize;
	new->mtd.writesize = 1;

	mtd_set_of_node(&new->mtd, np);

	ret = -EAGAIN;
	if (mtd_device_register(&new->mtd, NULL, 0)) {
		pr_err("Failed to register new device\n");
		goto out2;
	}

	if (pdev)
		platform_set_drvdata(pdev, new);
	else
		list_add_tail(&new->list, &phram_list);

	return 0;

out2:
@@ -278,7 +289,7 @@ static int phram_setup(const char *val)
		goto error;
	}

	ret = register_device(name, start, len, (uint32_t)erasesize);
	ret = register_device(NULL, name, start, len, (uint32_t)erasesize);
	if (ret)
		goto error;

@@ -325,10 +336,54 @@ static int phram_param_call(const char *val, const struct kernel_param *kp)
module_param_call(phram, phram_param_call, NULL, NULL, 0200);
MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>[,<erasesize>]\"");

#ifdef CONFIG_OF
static const struct of_device_id phram_of_match[] = {
	{ .compatible = "phram" },
	{}
};
MODULE_DEVICE_TABLE(of, phram_of_match);
#endif

static int phram_probe(struct platform_device *pdev)
{
	struct resource *res;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENOMEM;

	/* mtd_set_of_node() reads name from "label" */
	return register_device(pdev, NULL, res->start, resource_size(res),
			       PAGE_SIZE);
}

static int phram_remove(struct platform_device *pdev)
{
	struct phram_mtd_list *phram = platform_get_drvdata(pdev);

	mtd_device_unregister(&phram->mtd);
	iounmap(phram->mtd.priv);
	kfree(phram);

	return 0;
}

static struct platform_driver phram_driver = {
	.probe		= phram_probe,
	.remove		= phram_remove,
	.driver		= {
		.name		= "phram",
		.of_match_table	= of_match_ptr(phram_of_match),
	},
};

static int __init init_phram(void)
{
	int ret = 0;
	int ret;

	ret = platform_driver_register(&phram_driver);
	if (ret)
		return ret;

#ifndef MODULE
	if (phram_paramline[0])
@@ -336,12 +391,16 @@ static int __init init_phram(void)
	phram_init_called = 1;
#endif

	if (ret)
		platform_driver_unregister(&phram_driver);

	return ret;
}

static void __exit cleanup_phram(void)
{
	unregister_devices();
	platform_driver_unregister(&phram_driver);
}

module_init(init_phram);
+1 −0
Original line number Diff line number Diff line
@@ -509,6 +509,7 @@ EXPORT_SYMBOL_GPL(of_platform_default_populate);

#ifndef CONFIG_PPC
static const struct of_device_id reserved_mem_matches[] = {
	{ .compatible = "phram" },
	{ .compatible = "qcom,rmtfs-mem" },
	{ .compatible = "qcom,cmd-db" },
	{ .compatible = "qcom,smem" },