aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/iseries/dt.c
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2006-05-19 03:04:48 -0400
committerPaul Mackerras <paulus@samba.org>2006-05-24 02:08:57 -0400
commitc4e3ea2553308ba65fea582dc9a42221ef8b49e5 (patch)
treeae8126834cda2638a3f151a6ce24a98a90dbbab6 /arch/powerpc/platforms/iseries/dt.c
parentc81014f603db26e1ed818decebd3b594606e20a6 (diff)
[PATCH] powerpc: make iSeries flattened device tree dynamic
First we capture all the strings from dt.c statically by noting that gcc puts them in a special section of their own. Idea from Michael Ellerman. Then we move the flattened device tree to klimit. Still to come, making the values blob grow as needed. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/iseries/dt.c')
-rw-r--r--arch/powerpc/platforms/iseries/dt.c96
1 files changed, 57 insertions, 39 deletions
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 93d4233e73e5..0371329f82e1 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -30,6 +30,7 @@
30#include <asm/page.h> 30#include <asm/page.h>
31#include <asm/cputable.h> 31#include <asm/cputable.h>
32#include <asm/abs_addr.h> 32#include <asm/abs_addr.h>
33#include <asm/system.h>
33#include <asm/iseries/hv_types.h> 34#include <asm/iseries/hv_types.h>
34#include <asm/iseries/hv_lp_config.h> 35#include <asm/iseries/hv_lp_config.h>
35#include <asm/iseries/hv_call_xm.h> 36#include <asm/iseries/hv_call_xm.h>
@@ -47,6 +48,9 @@
47#define DBG(fmt...) 48#define DBG(fmt...)
48#endif 49#endif
49 50
51extern char __dt_strings_start[];
52extern char __dt_strings_end[];
53
50struct blob { 54struct blob {
51 unsigned char data[PAGE_SIZE * 2]; 55 unsigned char data[PAGE_SIZE * 2];
52 unsigned long next; 56 unsigned long next;
@@ -55,26 +59,34 @@ struct blob {
55struct iseries_flat_dt { 59struct iseries_flat_dt {
56 struct boot_param_header header; 60 struct boot_param_header header;
57 u64 reserve_map[2]; 61 u64 reserve_map[2];
58 struct blob dt; 62 struct blob *dt;
59 struct blob strings;
60}; 63};
61 64
62static struct iseries_flat_dt iseries_dt; 65static struct iseries_flat_dt *iseries_dt;
63 66
64static void __init dt_init(struct iseries_flat_dt *dt) 67static struct iseries_flat_dt * __init dt_init(void)
65{ 68{
69 struct iseries_flat_dt *dt;
70 unsigned long str_len;
71
72 str_len = __dt_strings_end - __dt_strings_start;
73 dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
66 dt->header.off_mem_rsvmap = 74 dt->header.off_mem_rsvmap =
67 offsetof(struct iseries_flat_dt, reserve_map); 75 offsetof(struct iseries_flat_dt, reserve_map);
68 dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); 76 dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
69 dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); 77 dt->header.off_dt_struct = dt->header.off_dt_strings
70 dt->header.totalsize = sizeof(struct iseries_flat_dt); 78 + ALIGN(str_len, 8);
71 dt->header.dt_strings_size = sizeof(struct blob); 79 dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct);
80 klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8);
81 dt->header.totalsize = klimit - (unsigned long)dt;
82 dt->header.dt_strings_size = str_len;
72 83
73 /* There is no notion of hardware cpu id on iSeries */ 84 /* There is no notion of hardware cpu id on iSeries */
74 dt->header.boot_cpuid_phys = smp_processor_id(); 85 dt->header.boot_cpuid_phys = smp_processor_id();
75 86
76 dt->dt.next = (unsigned long)&dt->dt.data; 87 dt->dt->next = (unsigned long)&dt->dt->data;
77 dt->strings.next = (unsigned long)&dt->strings.data; 88 memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
89 str_len);
78 90
79 dt->header.magic = OF_DT_HEADER; 91 dt->header.magic = OF_DT_HEADER;
80 dt->header.version = 0x10; 92 dt->header.version = 0x10;
@@ -82,6 +94,8 @@ static void __init dt_init(struct iseries_flat_dt *dt)
82 94
83 dt->reserve_map[0] = 0; 95 dt->reserve_map[0] = 0;
84 dt->reserve_map[1] = 0; 96 dt->reserve_map[1] = 0;
97
98 return dt;
85} 99}
86 100
87static void __init dt_check_blob(struct blob *b) 101static void __init dt_check_blob(struct blob *b)
@@ -94,19 +108,19 @@ static void __init dt_check_blob(struct blob *b)
94 108
95static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) 109static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
96{ 110{
97 *((u32*)dt->dt.next) = value; 111 *((u32*)dt->dt->next) = value;
98 dt->dt.next += sizeof(u32); 112 dt->dt->next += sizeof(u32);
99 113
100 dt_check_blob(&dt->dt); 114 dt_check_blob(dt->dt);
101} 115}
102 116
103#ifdef notyet 117#ifdef notyet
104static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) 118static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
105{ 119{
106 *((u64*)dt->dt.next) = value; 120 *((u64*)dt->dt->next) = value;
107 dt->dt.next += sizeof(u64); 121 dt->dt->next += sizeof(u64);
108 122
109 dt_check_blob(&dt->dt); 123 dt_check_blob(dt->dt);
110} 124}
111#endif 125#endif
112 126
@@ -125,7 +139,7 @@ static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len
125static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) 139static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
126{ 140{
127 dt_push_u32(dt, OF_DT_BEGIN_NODE); 141 dt_push_u32(dt, OF_DT_BEGIN_NODE);
128 dt_push_bytes(&dt->dt, name, strlen(name) + 1); 142 dt_push_bytes(dt->dt, name, strlen(name) + 1);
129} 143}
130 144
131#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) 145#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
@@ -140,14 +154,13 @@ static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
140 /* Length of the data */ 154 /* Length of the data */
141 dt_push_u32(dt, len); 155 dt_push_u32(dt, len);
142 156
143 /* Put the property name in the string blob. */ 157 offset = name - __dt_strings_start;
144 offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
145 158
146 /* The offset of the properties name in the string blob. */ 159 /* The offset of the properties name in the string blob. */
147 dt_push_u32(dt, (u32)offset); 160 dt_push_u32(dt, (u32)offset);
148 161
149 /* The actual data. */ 162 /* The actual data. */
150 dt_push_bytes(&dt->dt, data, len); 163 dt_push_bytes(dt->dt, data, len);
151} 164}
152 165
153static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, 166static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
@@ -579,40 +592,45 @@ static void __init dt_pci_devices(struct iseries_flat_dt *dt)
579 } 592 }
580} 593}
581 594
595static void dt_finish(struct iseries_flat_dt *dt)
596{
597 dt_push_u32(dt, OF_DT_END);
598}
599
582void * __init build_flat_dt(unsigned long phys_mem_size) 600void * __init build_flat_dt(unsigned long phys_mem_size)
583{ 601{
584 u64 tmp[2]; 602 u64 tmp[2];
585 603
586 dt_init(&iseries_dt); 604 iseries_dt = dt_init();
587 605
588 dt_start_node(&iseries_dt, ""); 606 dt_start_node(iseries_dt, "");
589 607
590 dt_prop_u32(&iseries_dt, "#address-cells", 2); 608 dt_prop_u32(iseries_dt, "#address-cells", 2);
591 dt_prop_u32(&iseries_dt, "#size-cells", 2); 609 dt_prop_u32(iseries_dt, "#size-cells", 2);
592 dt_model(&iseries_dt); 610 dt_model(iseries_dt);
593 611
594 /* /memory */ 612 /* /memory */
595 dt_start_node(&iseries_dt, "memory@0"); 613 dt_start_node(iseries_dt, "memory@0");
596 dt_prop_str(&iseries_dt, "name", "memory"); 614 dt_prop_str(iseries_dt, "name", "memory");
597 dt_prop_str(&iseries_dt, "device_type", "memory"); 615 dt_prop_str(iseries_dt, "device_type", "memory");
598 tmp[0] = 0; 616 tmp[0] = 0;
599 tmp[1] = phys_mem_size; 617 tmp[1] = phys_mem_size;
600 dt_prop_u64_list(&iseries_dt, "reg", tmp, 2); 618 dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
601 dt_end_node(&iseries_dt); 619 dt_end_node(iseries_dt);
602 620
603 /* /chosen */ 621 /* /chosen */
604 dt_start_node(&iseries_dt, "chosen"); 622 dt_start_node(iseries_dt, "chosen");
605 dt_prop_str(&iseries_dt, "bootargs", cmd_line); 623 dt_prop_str(iseries_dt, "bootargs", cmd_line);
606 dt_end_node(&iseries_dt); 624 dt_end_node(iseries_dt);
607 625
608 dt_cpus(&iseries_dt); 626 dt_cpus(iseries_dt);
609 627
610 dt_vdevices(&iseries_dt); 628 dt_vdevices(iseries_dt);
611 dt_pci_devices(&iseries_dt); 629 dt_pci_devices(iseries_dt);
612 630
613 dt_end_node(&iseries_dt); 631 dt_end_node(iseries_dt);
614 632
615 dt_push_u32(&iseries_dt, OF_DT_END); 633 dt_finish(iseries_dt);
616 634
617 return &iseries_dt; 635 return iseries_dt;
618} 636}