1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  linux/arch/arm/mach-mmp/sram.c
4  *
5  *  based on mach-davinci/sram.c - DaVinci simple SRAM allocator
6  *
7  *  Copyright (c) 2011 Marvell Semiconductors Inc.
8  *  All Rights Reserved
9  *
10  *  Add for mmp sram support - Leo Yan <leoy@marvell.com>
11  */
12 
13 #include <linux/module.h>
14 #include <linux/mod_devicetable.h>
15 #include <linux/init.h>
16 #include <linux/platform_device.h>
17 #include <linux/io.h>
18 #include <linux/err.h>
19 #include <linux/slab.h>
20 #include <linux/genalloc.h>
21 
22 #include <linux/platform_data/dma-mmp_tdma.h>
23 
24 struct sram_bank_info {
25 	char *pool_name;
26 	struct gen_pool *gpool;
27 	int granularity;
28 
29 	phys_addr_t sram_phys;
30 	void __iomem *sram_virt;
31 	u32 sram_size;
32 
33 	struct list_head node;
34 };
35 
36 static DEFINE_MUTEX(sram_lock);
37 static LIST_HEAD(sram_bank_list);
38 
sram_get_gpool(char * pool_name)39 struct gen_pool *sram_get_gpool(char *pool_name)
40 {
41 	struct sram_bank_info *info = NULL;
42 
43 	if (!pool_name)
44 		return NULL;
45 
46 	mutex_lock(&sram_lock);
47 
48 	list_for_each_entry(info, &sram_bank_list, node)
49 		if (!strcmp(pool_name, info->pool_name))
50 			break;
51 
52 	mutex_unlock(&sram_lock);
53 
54 	if (&info->node == &sram_bank_list)
55 		return NULL;
56 
57 	return info->gpool;
58 }
59 EXPORT_SYMBOL(sram_get_gpool);
60 
sram_probe(struct platform_device * pdev)61 static int sram_probe(struct platform_device *pdev)
62 {
63 	struct sram_platdata *pdata = pdev->dev.platform_data;
64 	struct sram_bank_info *info;
65 	struct resource *res;
66 	int ret = 0;
67 
68 	if (!pdata || !pdata->pool_name)
69 		return -ENODEV;
70 
71 	info = kzalloc(sizeof(*info), GFP_KERNEL);
72 	if (!info)
73 		return -ENOMEM;
74 
75 	platform_set_drvdata(pdev, info);
76 
77 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
78 	if (res == NULL) {
79 		dev_err(&pdev->dev, "no memory resource defined\n");
80 		ret = -ENODEV;
81 		goto out;
82 	}
83 
84 	if (!resource_size(res))
85 		return 0;
86 
87 	info->sram_phys   = (phys_addr_t)res->start;
88 	info->sram_size   = resource_size(res);
89 	info->sram_virt   = ioremap(info->sram_phys, info->sram_size);
90 	info->pool_name	  = kstrdup(pdata->pool_name, GFP_KERNEL);
91 	info->granularity = pdata->granularity;
92 
93 	info->gpool = gen_pool_create(ilog2(info->granularity), -1);
94 	if (!info->gpool) {
95 		dev_err(&pdev->dev, "create pool failed\n");
96 		ret = -ENOMEM;
97 		goto create_pool_err;
98 	}
99 
100 	ret = gen_pool_add_virt(info->gpool, (unsigned long)info->sram_virt,
101 				info->sram_phys, info->sram_size, -1);
102 	if (ret < 0) {
103 		dev_err(&pdev->dev, "add new chunk failed\n");
104 		ret = -ENOMEM;
105 		goto add_chunk_err;
106 	}
107 
108 	mutex_lock(&sram_lock);
109 	list_add(&info->node, &sram_bank_list);
110 	mutex_unlock(&sram_lock);
111 
112 	dev_info(&pdev->dev, "initialized\n");
113 	return 0;
114 
115 add_chunk_err:
116 	gen_pool_destroy(info->gpool);
117 create_pool_err:
118 	iounmap(info->sram_virt);
119 	kfree(info->pool_name);
120 out:
121 	kfree(info);
122 	return ret;
123 }
124 
sram_remove(struct platform_device * pdev)125 static int sram_remove(struct platform_device *pdev)
126 {
127 	struct sram_bank_info *info;
128 
129 	info = platform_get_drvdata(pdev);
130 
131 	if (info->sram_size) {
132 		mutex_lock(&sram_lock);
133 		list_del(&info->node);
134 		mutex_unlock(&sram_lock);
135 
136 		gen_pool_destroy(info->gpool);
137 		iounmap(info->sram_virt);
138 		kfree(info->pool_name);
139 	}
140 
141 	kfree(info);
142 
143 	return 0;
144 }
145 
146 static const struct platform_device_id sram_id_table[] = {
147 	{ "asram", MMP_ASRAM },
148 	{ "isram", MMP_ISRAM },
149 	{ }
150 };
151 
152 static struct platform_driver sram_driver = {
153 	.probe		= sram_probe,
154 	.remove		= sram_remove,
155 	.driver		= {
156 		.name	= "mmp-sram",
157 	},
158 	.id_table	= sram_id_table,
159 };
160 
sram_init(void)161 static int __init sram_init(void)
162 {
163 	return platform_driver_register(&sram_driver);
164 }
165 core_initcall(sram_init);
166 
167 MODULE_LICENSE("GPL");
168