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