1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* memory.c: Prom routine for acquiring various bits of information |
3 | * about RAM on the machine, both virtual and physical. |
4 | * |
5 | * Copyright (C) 1995, 2008 David S. Miller (davem@davemloft.net) |
6 | * Copyright (C) 1997 Michael A. Griffith (grif@acm.org) |
7 | */ |
8 | |
9 | #include <linux/kernel.h> |
10 | #include <linux/sort.h> |
11 | #include <linux/init.h> |
12 | |
13 | #include <asm/openprom.h> |
14 | #include <asm/oplib.h> |
15 | #include <asm/page.h> |
16 | |
17 | static int __init prom_meminit_v0(void) |
18 | { |
19 | struct linux_mlist_v0 *p; |
20 | int index; |
21 | |
22 | index = 0; |
23 | for (p = *(romvec->pv_v0mem.v0_available); p; p = p->theres_more) { |
24 | sp_banks[index].base_addr = (unsigned long) p->start_adr; |
25 | sp_banks[index].num_bytes = p->num_bytes; |
26 | index++; |
27 | } |
28 | |
29 | return index; |
30 | } |
31 | |
32 | static int __init prom_meminit_v2(void) |
33 | { |
34 | struct linux_prom_registers reg[64]; |
35 | phandle node; |
36 | int size, num_ents, i; |
37 | |
38 | node = prom_searchsiblings(prom_getchild(prom_root_node), "memory" ); |
39 | size = prom_getproperty(node, "available" , (char *) reg, sizeof(reg)); |
40 | num_ents = size / sizeof(struct linux_prom_registers); |
41 | |
42 | for (i = 0; i < num_ents; i++) { |
43 | sp_banks[i].base_addr = reg[i].phys_addr; |
44 | sp_banks[i].num_bytes = reg[i].reg_size; |
45 | } |
46 | |
47 | return num_ents; |
48 | } |
49 | |
50 | static int sp_banks_cmp(const void *a, const void *b) |
51 | { |
52 | const struct sparc_phys_banks *x = a, *y = b; |
53 | |
54 | if (x->base_addr > y->base_addr) |
55 | return 1; |
56 | if (x->base_addr < y->base_addr) |
57 | return -1; |
58 | return 0; |
59 | } |
60 | |
61 | /* Initialize the memory lists based upon the prom version. */ |
62 | void __init prom_meminit(void) |
63 | { |
64 | int i, num_ents = 0; |
65 | |
66 | switch (prom_vers) { |
67 | case PROM_V0: |
68 | num_ents = prom_meminit_v0(); |
69 | break; |
70 | |
71 | case PROM_V2: |
72 | case PROM_V3: |
73 | num_ents = prom_meminit_v2(); |
74 | break; |
75 | |
76 | default: |
77 | break; |
78 | } |
79 | sort(sp_banks, num_ents, sizeof(struct sparc_phys_banks), |
80 | sp_banks_cmp, NULL); |
81 | |
82 | /* Sentinel. */ |
83 | sp_banks[num_ents].base_addr = 0xdeadbeef; |
84 | sp_banks[num_ents].num_bytes = 0; |
85 | |
86 | for (i = 0; i < num_ents; i++) |
87 | sp_banks[i].num_bytes &= PAGE_MASK; |
88 | } |
89 | |