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
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}}}
};
......@@ -92,23 +92,50 @@ void
lmb_analyze(void)
{
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 offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
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
_lmb->memory.region[i].physbase = physbase;
physbase += lmb_size;
physbase += lmb_size;
#else
_lmb->memory.region[i].physbase = _lmb->memory.region[i].base;
#endif
total_size += lmb_size;
size_mask |= lmb_size;
mem_size += lmb_size;
size_mask |= lmb_size;
}
_lmb->memory.size = total_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;
}
#endif /* CONFIG_MSCHUNKS */
_lmb->memory.size = mem_size;
_lmb->memory.iosize = io_size;
_lmb->memory.lcd_size = (1UL << cnt_trailing_zeros(size_mask));
}
......@@ -124,6 +151,7 @@ lmb_add(unsigned long base, unsigned long size)
}
#ifdef CONFIG_MSCHUNKS
/* This routine called with relocation disabled. */
long
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);
}
#endif /* CONFIG_MSCHUNKS */
long
lmb_reserve(unsigned long base, unsigned long size)
......@@ -268,12 +297,16 @@ lmb_phys_mem_size(void)
{
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
#ifdef CONFIG_MSCHUNKS
return _lmb->memory.size;
#else
struct lmb_region *_mem = &(_lmb->memory);
unsigned long idx = _mem->cnt-1;
unsigned long lastbase = _mem->region[idx].physbase;
unsigned long lastsize = _mem->region[idx].size;
return (lastbase + lastsize);
#endif /* CONFIG_MSCHUNKS */
}
unsigned long
......@@ -282,22 +315,27 @@ lmb_end_of_DRAM(void)
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
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
unsigned long lastbase = _mem->region[idx].physbase;
return (_mem->region[idx].physbase + _mem->region[idx].size);
#else
unsigned long lastbase = _mem->region[idx].base;
return (_mem->region[idx].base + _mem->region[idx].size);
#endif /* CONFIG_MSCHUNKS */
unsigned long lastsize = _mem->region[idx].size;
}
return (lastbase + lastsize);
return 0;
}
unsigned long
lmb_abs_to_phys(unsigned long aa)
{
unsigned long i, pa = 0;
unsigned long i, pa = aa;
unsigned long offset = reloc_offset();
struct lmb *_lmb = PTRRELOC(&lmb);
struct lmb_region *_mem = &(_lmb->memory);
......
......@@ -204,7 +204,13 @@ static struct device_node *find_phandle(phandle);
#ifdef CONFIG_MSCHUNKS
static unsigned long prom_initialize_mschunks(unsigned long);
#ifdef DEBUG_PROM
void prom_dump_mschunks_mapping(void);
#endif /* DEBUG_PROM */
#endif /* CONFIG_MSCHUNKS */
#ifdef DEBUG_PROM
void prom_dump_lmb(void);
#endif
extern unsigned long reloc_offset(void);
......@@ -536,10 +542,11 @@ prom_initialize_lmb(unsigned long mem)
unsigned long i, offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
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;
#ifdef CONFIG_MSCHUNKS
unsigned long max_addr = 0;
#if 1
/* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
unsigned long io_base = 3UL<<30;
......@@ -550,7 +557,7 @@ prom_initialize_lmb(unsigned long mem)
unsigned long io_base = <real io base here>;
unsigned long io_size = <real io size here>;
#endif
#endif
#endif /* CONFIG_MSCHUNKS */
lmb_init();
......@@ -582,24 +589,32 @@ prom_initialize_lmb(unsigned long mem)
*/
have_630 = 0;
}
#endif
#endif /* CONFIG_MSCHUNKS */
if ( lmb_add(lmb_base, lmb_size) < 0 )
prom_print(RELOC("Too many LMB's, discarding this one...\n"));
else
mem_size =+ lmb_size;
#ifdef CONFIG_MSCHUNKS
else if ( max_addr < (lmb_base+lmb_size-1) )
max_addr = lmb_base+lmb_size-1;
#endif /* 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);
#endif
#endif /* CONFIG_MSCHUNKS */
lmb_analyze();
#ifdef DEBUG_PROM
prom_dump_lmb();
#endif /* DEBUG_PROM */
#ifdef CONFIG_MSCHUNKS
mem = prom_initialize_mschunks(mem);
#ifdef DEBUG_PROM
prom_dump_mschunks_mapping();
#endif /* DEBUG_PROM */
#endif /* CONFIG_MSCHUNKS */
return mem;
......@@ -711,53 +726,152 @@ prom_initialize_mschunks(unsigned long mem)
struct lmb *_lmb = PTRRELOC(&lmb);
struct msChunks *_msChunks = PTRRELOC(&msChunks);
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;
#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++) {
unsigned long base = _lmb->memory.region[i].base;
unsigned long size = _lmb->memory.region[i].size;
if ( lmb_addrs_overlap(base,size,io_base,io_size) ) {
/* If we really have dram here, then we don't
* 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
unsigned long achunk = addr_to_chunk(base);
unsigned long end_achunk = addr_to_chunk(base+size);
if ( lmb_addrs_overlap(0,mem_size,io_base,io_size) ) {
lmb_add(io_base, io_size);
lmb_reserve(io_base, io_size);
}
if(_lmb->memory.region[i].type != LMB_MEMORY_AREA)
continue;
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++) {
unsigned long base = _lmb->memory.region[i].base;
unsigned long size = _lmb->memory.region[i].size;
unsigned long achunk = addr_to_chunk(base);
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);
for (; achunk < end_achunk ;) {
PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
}
}
#endif /* CONFIG_MSCHUNKS */
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 */
#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
prom_initialize_tce_table(void)
{
......
......@@ -521,8 +521,14 @@ void __init do_init_bootmem(void)
/* add all physical memory to the bootmem map */
for (i=0; i < lmb.memory.cnt ;i++) {
unsigned long physbase = lmb.memory.region[i].physbase;
unsigned long size = lmb.memory.region[i].size;
unsigned long physbase, 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);
}
/* reserve the sections we're already using */
......
......@@ -103,7 +103,7 @@ absolute_to_phys(unsigned long aa)
#define physRpn_to_absRpn(rpn) (rpn)
#define absolute_to_phys(aa) (aa)
#endif /* CONFIG_MSCHUNKS */
#endif /* !CONFIG_MSCHUNKS */
static inline unsigned long
......
......@@ -17,7 +17,7 @@
extern unsigned long reloc_offset(void);
#define MAX_LMB_REGIONS 64
#define MAX_LMB_REGIONS 32
union lmb_reg_property {
struct reg_property32 addr32[MAX_LMB_REGIONS];
......@@ -37,6 +37,7 @@ struct lmb_property {
struct lmb_region {
unsigned long cnt;
unsigned long size;
unsigned long iosize;
unsigned long lcd_size; /* Least Common Denominator */
struct lmb_property region[MAX_LMB_REGIONS+1];
};
......@@ -52,7 +53,9 @@ extern struct lmb lmb;
extern void lmb_init(void);
extern void lmb_analyze(void);
extern long lmb_add(unsigned long, unsigned long);
#ifdef CONFIG_MSCHUNKS
extern long lmb_add_io(unsigned long base, unsigned long size);
#endif /* CONFIG_MSCHUNKS */
extern long lmb_reserve(unsigned long, unsigned long);
extern unsigned long lmb_alloc(unsigned long, unsigned long);
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