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