Commit 0eef6190 authored by Anton Blanchard's avatar Anton Blanchard

ppc64: LMB fixes from Peter Bergner

parent 2fb93d4f
...@@ -28,8 +28,8 @@ static long lmb_add_region(struct lmb_region *, unsigned long, unsigned long, un ...@@ -28,8 +28,8 @@ static long lmb_add_region(struct lmb_region *, unsigned long, unsigned long, un
struct lmb lmb = { struct lmb lmb = {
0, 0,
{0,0,0,{{0,0,0}}}, {0,0,0,0,{{0,0,0}}},
{0,0,0,{{0,0,0}}} {0,0,0,0,{{0,0,0}}}
}; };
...@@ -92,23 +92,50 @@ void ...@@ -92,23 +92,50 @@ void
lmb_analyze(void) lmb_analyze(void)
{ {
unsigned long i, physbase = 0; unsigned long i, physbase = 0;
unsigned long total_size = 0; unsigned long mem_size = 0;
unsigned long io_size = 0;
unsigned long size_mask = 0; unsigned long size_mask = 0;
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb); struct lmb *_lmb = PTRRELOC(&lmb);
for (i=0; i < _lmb->memory.cnt ;i++) { for (i=0; i < _lmb->memory.cnt ;i++) {
unsigned long lmb_size = _lmb->memory.region[i].size; unsigned long lmb_type = _lmb->memory.region[i].type;
unsigned long lmb_size;
if ( lmb_type != LMB_MEMORY_AREA )
continue;
lmb_size = _lmb->memory.region[i].size;
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
_lmb->memory.region[i].physbase = physbase; _lmb->memory.region[i].physbase = physbase;
physbase += lmb_size; physbase += lmb_size;
#else #else
_lmb->memory.region[i].physbase = _lmb->memory.region[i].base; _lmb->memory.region[i].physbase = _lmb->memory.region[i].base;
#endif #endif
total_size += lmb_size; mem_size += lmb_size;
size_mask |= lmb_size;
}
#ifdef CONFIG_MSCHUNKS
for (i=0; i < _lmb->memory.cnt ;i++) {
unsigned long lmb_type = _lmb->memory.region[i].type;
unsigned long lmb_size;
if ( lmb_type != LMB_IO_AREA )
continue;
lmb_size = _lmb->memory.region[i].size;
_lmb->memory.region[i].physbase = physbase;
physbase += lmb_size;
io_size += lmb_size;
size_mask |= lmb_size; size_mask |= lmb_size;
} }
_lmb->memory.size = total_size; #endif /* CONFIG_MSCHUNKS */
_lmb->memory.size = mem_size;
_lmb->memory.iosize = io_size;
_lmb->memory.lcd_size = (1UL << cnt_trailing_zeros(size_mask)); _lmb->memory.lcd_size = (1UL << cnt_trailing_zeros(size_mask));
} }
...@@ -124,6 +151,7 @@ lmb_add(unsigned long base, unsigned long size) ...@@ -124,6 +151,7 @@ lmb_add(unsigned long base, unsigned long size)
} }
#ifdef CONFIG_MSCHUNKS
/* This routine called with relocation disabled. */ /* This routine called with relocation disabled. */
long long
lmb_add_io(unsigned long base, unsigned long size) lmb_add_io(unsigned long base, unsigned long size)
...@@ -135,6 +163,7 @@ lmb_add_io(unsigned long base, unsigned long size) ...@@ -135,6 +163,7 @@ lmb_add_io(unsigned long base, unsigned long size)
return lmb_add_region(_rgn, base, size, LMB_IO_AREA); return lmb_add_region(_rgn, base, size, LMB_IO_AREA);
} }
#endif /* CONFIG_MSCHUNKS */
long long
lmb_reserve(unsigned long base, unsigned long size) lmb_reserve(unsigned long base, unsigned long size)
...@@ -268,12 +297,16 @@ lmb_phys_mem_size(void) ...@@ -268,12 +297,16 @@ lmb_phys_mem_size(void)
{ {
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb); struct lmb *_lmb = PTRRELOC(&lmb);
#ifdef CONFIG_MSCHUNKS
return _lmb->memory.size;
#else
struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_mem = &(_lmb->memory);
unsigned long idx = _mem->cnt-1; unsigned long idx = _mem->cnt-1;
unsigned long lastbase = _mem->region[idx].physbase; unsigned long lastbase = _mem->region[idx].physbase;
unsigned long lastsize = _mem->region[idx].size; unsigned long lastsize = _mem->region[idx].size;
return (lastbase + lastsize); return (lastbase + lastsize);
#endif /* CONFIG_MSCHUNKS */
} }
unsigned long unsigned long
...@@ -282,22 +315,27 @@ lmb_end_of_DRAM(void) ...@@ -282,22 +315,27 @@ lmb_end_of_DRAM(void)
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb); struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_mem = &(_lmb->memory);
unsigned long idx = _mem->cnt-1; unsigned long idx;
for(idx=_mem->cnt-1; idx >= 0 ;idx--) {
unsigned long lastbase, lastsize;
if ( _mem->region[idx].type != LMB_MEMORY_AREA )
continue;
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
unsigned long lastbase = _mem->region[idx].physbase; return (_mem->region[idx].physbase + _mem->region[idx].size);
#else #else
unsigned long lastbase = _mem->region[idx].base; return (_mem->region[idx].base + _mem->region[idx].size);
#endif /* CONFIG_MSCHUNKS */ #endif /* CONFIG_MSCHUNKS */
unsigned long lastsize = _mem->region[idx].size; }
return (lastbase + lastsize); return 0;
} }
unsigned long unsigned long
lmb_abs_to_phys(unsigned long aa) lmb_abs_to_phys(unsigned long aa)
{ {
unsigned long i, pa = 0; unsigned long i, pa = aa;
unsigned long offset = reloc_offset(); unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb); struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_mem = &(_lmb->memory); struct lmb_region *_mem = &(_lmb->memory);
......
...@@ -204,7 +204,13 @@ static struct device_node *find_phandle(phandle); ...@@ -204,7 +204,13 @@ static struct device_node *find_phandle(phandle);
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
static unsigned long prom_initialize_mschunks(unsigned long); static unsigned long prom_initialize_mschunks(unsigned long);
#ifdef DEBUG_PROM
void prom_dump_mschunks_mapping(void);
#endif /* DEBUG_PROM */
#endif /* CONFIG_MSCHUNKS */ #endif /* CONFIG_MSCHUNKS */
#ifdef DEBUG_PROM
void prom_dump_lmb(void);
#endif
extern unsigned long reloc_offset(void); extern unsigned long reloc_offset(void);
...@@ -536,10 +542,11 @@ prom_initialize_lmb(unsigned long mem) ...@@ -536,10 +542,11 @@ prom_initialize_lmb(unsigned long mem)
unsigned long i, offset = reloc_offset(); unsigned long i, offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom); struct prom_t *_prom = PTRRELOC(&prom);
union lmb_reg_property reg; union lmb_reg_property reg;
unsigned long mem_size, lmb_base, lmb_size; unsigned long lmb_base, lmb_size;
unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8; unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
unsigned long max_addr = 0;
#if 1 #if 1
/* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */ /* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
unsigned long io_base = 3UL<<30; unsigned long io_base = 3UL<<30;
...@@ -550,7 +557,7 @@ prom_initialize_lmb(unsigned long mem) ...@@ -550,7 +557,7 @@ prom_initialize_lmb(unsigned long mem)
unsigned long io_base = <real io base here>; unsigned long io_base = <real io base here>;
unsigned long io_size = <real io size here>; unsigned long io_size = <real io size here>;
#endif #endif
#endif #endif /* CONFIG_MSCHUNKS */
lmb_init(); lmb_init();
...@@ -582,24 +589,32 @@ prom_initialize_lmb(unsigned long mem) ...@@ -582,24 +589,32 @@ prom_initialize_lmb(unsigned long mem)
*/ */
have_630 = 0; have_630 = 0;
} }
#endif #endif /* CONFIG_MSCHUNKS */
if ( lmb_add(lmb_base, lmb_size) < 0 ) if ( lmb_add(lmb_base, lmb_size) < 0 )
prom_print(RELOC("Too many LMB's, discarding this one...\n")); prom_print(RELOC("Too many LMB's, discarding this one...\n"));
else #ifdef CONFIG_MSCHUNKS
mem_size =+ lmb_size; else if ( max_addr < (lmb_base+lmb_size-1) )
max_addr = lmb_base+lmb_size-1;
#endif /* CONFIG_MSCHUNKS */
} }
} }
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
if ( have_630 && lmb_addrs_overlap(0,mem_size,io_base,io_size) ) if ( have_630 && lmb_addrs_overlap(0,max_addr,io_base,io_size) )
lmb_add_io(io_base, io_size); lmb_add_io(io_base, io_size);
#endif #endif /* CONFIG_MSCHUNKS */
lmb_analyze(); lmb_analyze();
#ifdef DEBUG_PROM
prom_dump_lmb();
#endif /* DEBUG_PROM */
#ifdef CONFIG_MSCHUNKS #ifdef CONFIG_MSCHUNKS
mem = prom_initialize_mschunks(mem); mem = prom_initialize_mschunks(mem);
#ifdef DEBUG_PROM
prom_dump_mschunks_mapping();
#endif /* DEBUG_PROM */
#endif /* CONFIG_MSCHUNKS */ #endif /* CONFIG_MSCHUNKS */
return mem; return mem;
...@@ -711,53 +726,152 @@ prom_initialize_mschunks(unsigned long mem) ...@@ -711,53 +726,152 @@ prom_initialize_mschunks(unsigned long mem)
struct lmb *_lmb = PTRRELOC(&lmb); struct lmb *_lmb = PTRRELOC(&lmb);
struct msChunks *_msChunks = PTRRELOC(&msChunks); struct msChunks *_msChunks = PTRRELOC(&msChunks);
unsigned long i, pchunk = 0; unsigned long i, pchunk = 0;
unsigned long mem_size = _lmb->memory.size; unsigned long addr_range = _lmb->memory.size + _lmb->memory.iosize;
unsigned long chunk_size = _lmb->memory.lcd_size; unsigned long chunk_size = _lmb->memory.lcd_size;
#if 1
/* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
unsigned long io_base = 3UL<<30;
unsigned long io_size = 1UL<<30;
mem = msChunks_alloc(mem, addr_range / chunk_size, chunk_size);
/* First create phys -> abs mapping for memory/dram */
for (i=0; i < _lmb->memory.cnt ;i++) { for (i=0; i < _lmb->memory.cnt ;i++) {
unsigned long base = _lmb->memory.region[i].base; unsigned long base = _lmb->memory.region[i].base;
unsigned long size = _lmb->memory.region[i].size; unsigned long size = _lmb->memory.region[i].size;
if ( lmb_addrs_overlap(base,size,io_base,io_size) ) { unsigned long achunk = addr_to_chunk(base);
/* If we really have dram here, then we don't unsigned long end_achunk = addr_to_chunk(base+size);
* have a 630! -Peter
*/
io_base = mem_size;
io_size = 1;
break;
}
}
#else
unsigned long io_base = <real io base here>;
unsigned long io_size = <real io size here>;
#endif
if ( lmb_addrs_overlap(0,mem_size,io_base,io_size) ) { if(_lmb->memory.region[i].type != LMB_MEMORY_AREA)
lmb_add(io_base, io_size); continue;
lmb_reserve(io_base, io_size);
}
mem = msChunks_alloc(mem, mem_size / chunk_size, chunk_size); _lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
for (; achunk < end_achunk ;) {
PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
}
}
#ifdef CONFIG_MSCHUNKS
/* Now create phys -> abs mapping for IO */
for (i=0; i < _lmb->memory.cnt ;i++) { for (i=0; i < _lmb->memory.cnt ;i++) {
unsigned long base = _lmb->memory.region[i].base; unsigned long base = _lmb->memory.region[i].base;
unsigned long size = _lmb->memory.region[i].size; unsigned long size = _lmb->memory.region[i].size;
unsigned long achunk = addr_to_chunk(base); unsigned long achunk = addr_to_chunk(base);
unsigned long end_achunk = addr_to_chunk(base+size); unsigned long end_achunk = addr_to_chunk(base+size);
if(_lmb->memory.region[i].type != LMB_IO_AREA)
continue;
_lmb->memory.region[i].physbase = chunk_to_addr(pchunk); _lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
for (; achunk < end_achunk ;) { for (; achunk < end_achunk ;) {
PTRRELOC(_msChunks->abs)[pchunk++] = achunk++; PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
} }
} }
#endif /* CONFIG_MSCHUNKS */
return mem; return mem;
} }
#ifdef DEBUG_PROM
void
prom_dump_mschunks_mapping(void)
{
unsigned long offset = reloc_offset();
struct msChunks *_msChunks = PTRRELOC(&msChunks);
unsigned long chunk;
prom_print(RELOC("\nprom_dump_mschunks_mapping:\n"));
prom_print(RELOC(" msChunks.num_chunks = 0x"));
prom_print_hex(_msChunks->num_chunks);
prom_print_nl();
prom_print(RELOC(" msChunks.chunk_size = 0x"));
prom_print_hex(_msChunks->chunk_size);
prom_print_nl();
prom_print(RELOC(" msChunks.chunk_shift = 0x"));
prom_print_hex(_msChunks->chunk_shift);
prom_print_nl();
prom_print(RELOC(" msChunks.chunk_mask = 0x"));
prom_print_hex(_msChunks->chunk_mask);
prom_print_nl();
prom_print(RELOC(" msChunks.abs = 0x"));
prom_print_hex(_msChunks->abs);
prom_print_nl();
prom_print(RELOC(" msChunks mapping:\n"));
for(chunk=0; chunk < _msChunks->num_chunks ;chunk++) {
prom_print(RELOC(" phys 0x"));
prom_print_hex(chunk);
prom_print(RELOC(" -> abs 0x"));
prom_print_hex(PTRRELOC(_msChunks->abs)[chunk]);
prom_print_nl();
}
}
#endif /* DEBUG_PROM */
#endif /* CONFIG_MSCHUNKS */ #endif /* CONFIG_MSCHUNKS */
#ifdef DEBUG_PROM
void
prom_dump_lmb(void)
{
unsigned long i;
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
prom_print(RELOC("\nprom_dump_lmb:\n"));
prom_print(RELOC(" memory.cnt = 0x"));
prom_print_hex(_lmb->memory.cnt);
prom_print_nl();
prom_print(RELOC(" memory.size = 0x"));
prom_print_hex(_lmb->memory.size);
prom_print_nl();
prom_print(RELOC(" memory.lcd_size = 0x"));
prom_print_hex(_lmb->memory.lcd_size);
prom_print_nl();
for (i=0; i < _lmb->memory.cnt ;i++) {
prom_print(RELOC(" memory.region[0x"));
prom_print_hex(i);
prom_print(RELOC("].base = 0x"));
prom_print_hex(_lmb->memory.region[i].base);
prom_print_nl();
prom_print(RELOC(" .physbase = 0x"));
prom_print_hex(_lmb->memory.region[i].physbase);
prom_print_nl();
prom_print(RELOC(" .size = 0x"));
prom_print_hex(_lmb->memory.region[i].size);
prom_print_nl();
prom_print(RELOC(" .type = 0x"));
prom_print_hex(_lmb->memory.region[i].type);
prom_print_nl();
}
prom_print_nl();
prom_print(RELOC(" reserved.cnt = 0x"));
prom_print_hex(_lmb->reserved.cnt);
prom_print_nl();
prom_print(RELOC(" reserved.size = 0x"));
prom_print_hex(_lmb->reserved.size);
prom_print_nl();
prom_print(RELOC(" reserved.lcd_size = 0x"));
prom_print_hex(_lmb->reserved.lcd_size);
prom_print_nl();
for (i=0; i < _lmb->reserved.cnt ;i++) {
prom_print(RELOC(" reserved.region[0x"));
prom_print_hex(i);
prom_print(RELOC("].base = 0x"));
prom_print_hex(_lmb->reserved.region[i].base);
prom_print_nl();
prom_print(RELOC(" .physbase = 0x"));
prom_print_hex(_lmb->reserved.region[i].physbase);
prom_print_nl();
prom_print(RELOC(" .size = 0x"));
prom_print_hex(_lmb->reserved.region[i].size);
prom_print_nl();
prom_print(RELOC(" .type = 0x"));
prom_print_hex(_lmb->reserved.region[i].type);
prom_print_nl();
}
}
#endif /* DEBUG_PROM */
void void
prom_initialize_tce_table(void) prom_initialize_tce_table(void)
{ {
......
...@@ -521,8 +521,14 @@ void __init do_init_bootmem(void) ...@@ -521,8 +521,14 @@ void __init do_init_bootmem(void)
/* add all physical memory to the bootmem map */ /* add all physical memory to the bootmem map */
for (i=0; i < lmb.memory.cnt ;i++) { for (i=0; i < lmb.memory.cnt ;i++) {
unsigned long physbase = lmb.memory.region[i].physbase; unsigned long physbase, size;
unsigned long size = lmb.memory.region[i].size; unsigned long type = lmb.memory.region[i].type;
if ( type != LMB_MEMORY_AREA )
continue;
physbase = lmb.memory.region[i].physbase;
size = lmb.memory.region[i].size;
free_bootmem(physbase, size); free_bootmem(physbase, size);
} }
/* reserve the sections we're already using */ /* reserve the sections we're already using */
......
...@@ -103,7 +103,7 @@ absolute_to_phys(unsigned long aa) ...@@ -103,7 +103,7 @@ absolute_to_phys(unsigned long aa)
#define physRpn_to_absRpn(rpn) (rpn) #define physRpn_to_absRpn(rpn) (rpn)
#define absolute_to_phys(aa) (aa) #define absolute_to_phys(aa) (aa)
#endif /* CONFIG_MSCHUNKS */ #endif /* !CONFIG_MSCHUNKS */
static inline unsigned long static inline unsigned long
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
extern unsigned long reloc_offset(void); extern unsigned long reloc_offset(void);
#define MAX_LMB_REGIONS 64 #define MAX_LMB_REGIONS 32
union lmb_reg_property { union lmb_reg_property {
struct reg_property32 addr32[MAX_LMB_REGIONS]; struct reg_property32 addr32[MAX_LMB_REGIONS];
...@@ -37,6 +37,7 @@ struct lmb_property { ...@@ -37,6 +37,7 @@ struct lmb_property {
struct lmb_region { struct lmb_region {
unsigned long cnt; unsigned long cnt;
unsigned long size; unsigned long size;
unsigned long iosize;
unsigned long lcd_size; /* Least Common Denominator */ unsigned long lcd_size; /* Least Common Denominator */
struct lmb_property region[MAX_LMB_REGIONS+1]; struct lmb_property region[MAX_LMB_REGIONS+1];
}; };
...@@ -52,7 +53,9 @@ extern struct lmb lmb; ...@@ -52,7 +53,9 @@ extern struct lmb lmb;
extern void lmb_init(void); extern void lmb_init(void);
extern void lmb_analyze(void); extern void lmb_analyze(void);
extern long lmb_add(unsigned long, unsigned long); extern long lmb_add(unsigned long, unsigned long);
#ifdef CONFIG_MSCHUNKS
extern long lmb_add_io(unsigned long base, unsigned long size); extern long lmb_add_io(unsigned long base, unsigned long size);
#endif /* CONFIG_MSCHUNKS */
extern long lmb_reserve(unsigned long, unsigned long); extern long lmb_reserve(unsigned long, unsigned long);
extern unsigned long lmb_alloc(unsigned long, unsigned long); extern unsigned long lmb_alloc(unsigned long, unsigned long);
extern unsigned long lmb_phys_mem_size(void); extern unsigned long lmb_phys_mem_size(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment