1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#include <asm/page.h>
#include <asm/setup.h>
#include <linux/module.h>
#include <linux/of_fdt.h>
#include <mach/mtk_memcfg.h>
#ifdef CONFIG_OF
/* return the actual physical DRAM size */
static u64 kernel_mem_sz;
static u64 phone_dram_sz; /* original phone DRAM size */
static int dt_scan_memory(unsigned long node, const char *uname, int depth, void *data)
{
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
int i;
__be32 *reg, *endp;
unsigned long l;
dram_info_t *dram_info;
/* We are scanning "memory" nodes only */
if (type == NULL) {
/*
* The longtrail doesn't have a device_type on the
* /memory node, so look for the node called /memory@0.
*/
if (depth != 1 || strcmp(uname, "memory@0") != 0)
return 0;
} else if (strcmp(type, "memory") != 0) {
return 0;
}
/*
* Use kernel_mem_sz if phone_dram_sz is not available (workaround)
* Projects use device tree should have orig_dram_info entry in their
* device tree.
* After the porting is done, kernel_mem_sz will be removed.
*/
reg = of_get_flat_dt_prop(node, "reg", &l);
if (reg == NULL)
return 0;
endp = reg + (l / sizeof(__be32));
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
u64 base, size;
base = dt_mem_next_cell(dt_root_addr_cells, ®);
size = dt_mem_next_cell(dt_root_size_cells, ®);
if (size == 0)
continue;
kernel_mem_sz += size;
}
/* orig_dram_info */
dram_info = (dram_info_t *)of_get_flat_dt_prop(node,
"orig_dram_info", NULL);
if (dram_info) {
for (i = 0; i < dram_info->rank_num; i++)
phone_dram_sz += dram_info->rank_info[i].size;
}
return node;
}
static int __init init_get_max_DRAM_size(void)
{
if (!phone_dram_sz && !kernel_mem_sz) {
if (of_scan_flat_dt(dt_scan_memory, NULL)) {
pr_alert("init_get_max_DRAM_size done. phone_dram_sz: 0x%llx, kernel_mem_sz: 0x%llx\n",
(unsigned long long)phone_dram_sz,
(unsigned long long)kernel_mem_sz);
} else {
pr_err("init_get_max_DRAM_size fail\n");
BUG();
}
}
return 0;
}
phys_addr_t get_max_DRAM_size(void)
{
if (!phone_dram_sz && !kernel_mem_sz)
init_get_max_DRAM_size();
return phone_dram_sz ? (phys_addr_t)phone_dram_sz : (phys_addr_t)kernel_mem_sz;
}
early_initcall(init_get_max_DRAM_size);
#else
extern phys_addr_t mtk_get_max_DRAM_size(void);
phys_addr_t get_max_DRAM_size(void)
{
return mtk_get_max_DRAM_size();
}
#endif /* end of CONFIG_OF */
EXPORT_SYMBOL(get_max_DRAM_size);
/*
* Return the DRAM size used by Linux kernel.
* In current stage, use phone DRAM size directly
*/
phys_addr_t get_memory_size(void)
{
return get_max_DRAM_size();
}
EXPORT_SYMBOL(get_memory_size);
phys_addr_t get_phys_offset(void)
{
return PHYS_OFFSET;
}
EXPORT_SYMBOL(get_phys_offset);
|