blob: 6078367c05f542eaa19c2481b20323ec1b06f38f [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/bootmem.h>
15
16#include <linux/vcm.h>
17#include <linux/vcm_alloc.h>
18
19#define MSM_SMI_BASE 0x38000000
20#define MSM_SMI_SIZE 0x04000000
21
22#define SMI_16M 0
23#define SMI_1M 1
24#define SMI_64K 2
25#define SMI_4K 3
26#define EBI_16M 4
27#define EBI_1M 5
28#define EBI_64K 6
29#define EBI_4K 7
30
31static void free_ebi_pools(void);
32
33static struct physmem_region memory[] = {
34 { /* SMI 16M */
35 .addr = MSM_SMI_BASE,
36 .size = SZ_16M,
37 .chunk_size = SZ_16M
38 },
39 { /* SMI 1M */
40 .addr = MSM_SMI_BASE + SZ_16M,
41 .size = SZ_8M,
42 .chunk_size = SZ_1M
43 },
44 { /* SMI 64K */
45 .addr = MSM_SMI_BASE + SZ_16M + SZ_8M,
46 .size = SZ_4M,
47 .chunk_size = SZ_64K
48 },
49 { /* SMI 4K */
50 .addr = MSM_SMI_BASE + SZ_16M + SZ_8M + SZ_4M,
51 .size = SZ_4M,
52 .chunk_size = SZ_4K
53 },
54
55 { /* EBI 16M */
56 .addr = 0,
57 .size = SZ_16M,
58 .chunk_size = SZ_16M
59 },
60 { /* EBI 1M */
61 .addr = 0,
62 .size = SZ_8M,
63 .chunk_size = SZ_1M
64 },
65 { /* EBI 64K */
66 .addr = 0,
67 .size = SZ_4M,
68 .chunk_size = SZ_64K
69 },
70 { /* EBI 4K */
71 .addr = 0,
72 .size = SZ_4M,
73 .chunk_size = SZ_4K
74 }
75};
76
77
78/* The pool priority MUST be in descending order of size */
79static struct vcm_memtype_map mt_map[] __initdata = {
80 {
81 /* MEMTYPE_0 */
82 .pool_id = {SMI_16M, SMI_1M, SMI_64K, SMI_4K},
83 .num_pools = 4,
84 },
85 {
86 /* MEMTYPE_1 */
87 .pool_id = {SMI_16M, SMI_1M, SMI_64K, EBI_4K},
88 .num_pools = 4,
89 },
90 { /* MEMTYPE_2 */
91 .pool_id = {EBI_16M, EBI_1M, EBI_64K, EBI_4K},
92 .num_pools = 4,
93 },
94 {
95 /* MEMTYPE_3 */
96 .pool_id = {SMI_16M, SMI_1M, EBI_1M, SMI_64K, EBI_64K, EBI_4K},
97 .num_pools = 6,
98 }
99};
100
101static int __init msm8x60_vcm_init(void)
102{
103 int ret, i;
104 void *ebi_chunk;
105
106
107 for (i = 0; i < ARRAY_SIZE(memory); i++) {
108 if (memory[i].addr == 0) {
109 ebi_chunk = __alloc_bootmem(memory[i].size,
110 memory[i].size, 0);
111 if (!ebi_chunk) {
112 pr_err("Could not allocate VCM-managed physical"
113 " memory\n");
114 ret = -ENOMEM;
115 goto fail;
116 }
117 memory[i].addr = __pa(ebi_chunk);
118 }
119 }
120
121 ret = vcm_sys_init(memory, ARRAY_SIZE(memory),
122 mt_map, ARRAY_SIZE(mt_map),
123 (void *)MSM_SMI_BASE + MSM_SMI_SIZE - SZ_8M, SZ_8M);
124
125 if (ret != 0) {
126 pr_err("vcm_sys_init() ret %i\n", ret);
127 goto fail;
128 }
129
130 return 0;
131fail:
132 free_ebi_pools();
133 return ret;
134};
135
136static void free_ebi_pools(void)
137{
138 int i;
139 phys_addr_t r;
140 for (i = 0; i < ARRAY_SIZE(memory); i++) {
141 r = memory[i].addr;
142 if (r > MSM_SMI_BASE + MSM_SMI_SIZE)
143 free_bootmem((unsigned long)__va(r), memory[i].size);
144 }
145}
146
147
148/* Useful for testing, and if VCM is ever unloaded */
149static void __exit msm8x60_vcm_exit(void)
150{
151 int ret;
152
153 ret = vcm_sys_destroy();
154 if (ret != 0) {
155 pr_err("vcm_sys_destroy() ret %i\n", ret);
156 goto fail;
157 }
158 free_ebi_pools();
159fail:
160 return;
161}
162
163
164subsys_initcall(msm8x60_vcm_init);
165module_exit(msm8x60_vcm_exit);
166
167MODULE_LICENSE("GPL v2");
168MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");