From: Scott Wood <hidden> Date: 2007-08-20 17:39:28
All cuImage types are ignored, as well as preprocessed .lds files,
and the forthcoming zImage.bin files and embedded planet board images.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/.gitignore | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
From: Scott Wood <hidden> Date: 2007-08-20 17:39:52
This lets udelay() work properly on platforms which use dt_fixup_cpu_clocks.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/devtree.c | 2 ++
arch/powerpc/boot/ops.h | 2 ++
2 files changed, 4 insertions(+), 0 deletions(-)
From: Scott Wood <hidden> Date: 2007-08-20 17:39:54
1. The check whether ranges fits in the buffer was using elements rather
than bytes.
2. Empty ranges were not properly treated as transparent, and missing
ranges were treated as transparent.
3. The loop terminated when translating from the root rather than to. Once
bug #2 was fixed, it failed due to a missing ranges in the root node.
4. In decoding the ranges property, the #size-cells used was that of
the parent, not the child.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/devtree.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
@@ -218,7 +218,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,u32this_addr[MAX_ADDR_CELLS];void*parent;u64ret_addr,ret_size;-u32naddr,nsize,prev_naddr;+u32naddr,nsize,prev_naddr,prev_nsize;intbuflen,offset;parent=get_parent(node);
@@ -233,7 +233,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,offset=(naddr+nsize)*res;if(reglen<offset+naddr+nsize||-sizeof(dt_xlate_buf)<offset+naddr+nsize)+sizeof(dt_xlate_buf)<(offset+naddr+nsize)*4)return0;copy_val(last_addr,dt_xlate_buf+offset,naddr);
@@ -244,20 +244,26 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,ret_size|=dt_xlate_buf[offset+naddr+1];}-while((node=get_parent(node))){+for(;;){prev_naddr=naddr;+prev_nsize=nsize;+node=parent;-get_reg_format(node,&naddr,&nsize);+parent=get_parent(node);+if(!parent)+break;++get_reg_format(parent,&naddr,&nsize);buflen=getprop(node,"ranges",dt_xlate_buf,sizeof(dt_xlate_buf));-if(buflen<0)+if(buflen==0)continue;-if(buflen>sizeof(dt_xlate_buf))+if(buflen<0||buflen>sizeof(dt_xlate_buf))return0;offset=find_range(last_addr,dt_xlate_buf,prev_naddr,-naddr,nsize,buflen/4);+naddr,prev_nsize,buflen/4);if(offset<0)return0;
From: Scott Wood <hidden> Date: 2007-08-20 17:39:56
This can be used rather than doing a simple strcmp, which will fail to
handle multiple compatible entries.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/devtree.c | 48 +++++++++++++++++++++++++++++-------------
arch/powerpc/boot/ops.h | 1 +
2 files changed, 34 insertions(+), 15 deletions(-)
@@ -209,7 +208,7 @@ static int find_range(u32 *reg, u32 *ranges, int nregaddr,*Inparticular,PCIisnotsupported.Also,onlythebeginningofthe*regblockistracked;sizeisignoredexceptinranges.*/-staticu32dt_xlate_buf[MAX_ADDR_CELLS*MAX_RANGES*3];+staticu32prop_buf[MAX_PROP_LEN/4];staticintdt_xlate(void*node,intres,intreglen,unsignedlong*addr,unsignedlong*size)
@@ -233,15 +232,15 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,offset=(naddr+nsize)*res;if(reglen<offset+naddr+nsize||-sizeof(dt_xlate_buf)<(offset+naddr+nsize)*4)+MAX_PROP_LEN<(offset+naddr+nsize)*4)return0;-copy_val(last_addr,dt_xlate_buf+offset,naddr);+copy_val(last_addr,prop_buf+offset,naddr);-ret_size=dt_xlate_buf[offset+naddr];+ret_size=prop_buf[offset+naddr];if(nsize==2){ret_size<<=32;-ret_size|=dt_xlate_buf[offset+naddr+1];+ret_size|=prop_buf[offset+naddr+1];}for(;;){
@@ -255,25 +254,25 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,get_reg_format(parent,&naddr,&nsize);-buflen=getprop(node,"ranges",dt_xlate_buf,-sizeof(dt_xlate_buf));+buflen=getprop(node,"ranges",prop_buf,+sizeof(prop_buf));if(buflen==0)continue;-if(buflen<0||buflen>sizeof(dt_xlate_buf))+if(buflen<0||buflen>sizeof(prop_buf))return0;-offset=find_range(last_addr,dt_xlate_buf,prev_naddr,+offset=find_range(last_addr,prop_buf,prev_naddr,naddr,prev_nsize,buflen/4);if(offset<0)return0;-copy_val(this_addr,dt_xlate_buf+offset,prev_naddr);+copy_val(this_addr,prop_buf+offset,prev_naddr);if(!sub_reg(last_addr,this_addr))return0;-copy_val(this_addr,dt_xlate_buf+offset+prev_naddr,naddr);+copy_val(this_addr,prop_buf+offset+prev_naddr,naddr);if(!add_reg(last_addr,this_addr,naddr))return0;
@@ -300,16 +299,35 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size){intreglen;-reglen=getprop(node,"reg",dt_xlate_buf,sizeof(dt_xlate_buf))/4;+reglen=getprop(node,"reg",prop_buf,sizeof(prop_buf))/4;returndt_xlate(node,res,reglen,addr,size);}intdt_xlate_addr(void*node,u32*buf,intbuflen,unsignedlong*xlated_addr){-if(buflen>sizeof(dt_xlate_buf))+if(buflen>sizeof(prop_buf))return0;-memcpy(dt_xlate_buf,buf,buflen);+memcpy(prop_buf,buf,buflen);returndt_xlate(node,0,buflen/4,xlated_addr,NULL);}++intdt_is_compatible(void*node,constchar*compat)+{+char*buf=(char*)prop_buf;+intlen,pos;++len=getprop(node,"compatible",buf,MAX_PROP_LEN);+if(len<0)+return0;++for(pos=0;pos<len;pos++){+if(!strcmp(buf+pos,compat))+return1;++pos+=strnlen(&buf[pos],len-pos);+}++return0;+}
From: Scott Wood <hidden> Date: 2007-08-20 17:39:57
1. ft_create_node was returning the internal pointer rather than a phandle.
2. ft_find_device_rel was treating a "top" phandle of NULL as an error,
rather than as the root of the tree.
3. Return the node's name when getprop() is called with the "name" property.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/flatdevtree.c | 24 +++++++++++++++++++-----
1 files changed, 19 insertions(+), 5 deletions(-)
From: Scott Wood <hidden> Date: 2007-08-20 17:39:59
Also, include types.h from io.h, so callers don't have to.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/io.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+), 0 deletions(-)
From: Scott Wood <hidden> Date: 2007-08-20 17:40:01
U-boots more recent than when ppcboot.h was forked allow the board config
file to enable additional ethernet ports explicitly, rather than
using a hardcoded list of targets. This allows bootwrapper platform
files to do the same.
Fortunately, nothing after the ethernet addresses is of interest to
cuboot platforms, so the inevitable mismatches won't be too catastrophic.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/ppcboot.h | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
From: Scott Wood <hidden> Date: 2007-08-20 17:40:05
1. Search the entire compatible list for serial devices.
The serial code previously did a simple strcmp on the compatible
node; this fails when the match string is not the first compatible
listed. Use dt_is_compatible() instead.
2. Don't call serial_edit_cmdline if getc isn't defined.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/serial.c | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)
@@ -114,18 +114,14 @@ int serial_console_init(void){void*devp;intrc=-1;-charcompat[MAX_PROP_LEN];devp=serial_get_stdout_devp();if(devp==NULL)gotoerr_out;-if(getprop(devp,"compatible",compat,sizeof(compat))<0)-gotoerr_out;--if(!strcmp(compat,"ns16550"))+if(dt_is_compatible(devp,"ns16550"))rc=ns16550_console_init(devp,&serial_cd);-elseif(!strcmp(compat,"marvell,mpsc"))+elseif(dt_is_compatible(devp,"marvell,mpsc"))rc=mpsc_console_init(devp,&serial_cd);/* Add other serial console driver calls here */
@@ -133,10 +129,12 @@ int serial_console_init(void)if(!rc){console_ops.open=serial_open;console_ops.write=serial_write;-console_ops.edit_cmdline=serial_edit_cmdline;console_ops.close=serial_close;console_ops.data=&serial_cd;+if(serial_cd.getc)+console_ops.edit_cmdline=serial_edit_cmdline;+return0;}err_out:
From: Scott Wood <hidden> Date: 2007-08-20 17:40:14
This serial port is used on all 8xx, many 82xx, and some 85xx chips.
The driver requires that the port has already been set up by the firmware
and/or platform code.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/Makefile | 3 +-
arch/powerpc/boot/cpm-serial.c | 249 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/boot/ops.h | 1 +
arch/powerpc/boot/serial.c | 5 +
4 files changed, 257 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/boot/cpm-serial.c
@@ -0,0 +1,249 @@+/*+*CPMserialconsolesupport.+*+*Copyright2007FreescaleSemiconductor,Inc.+*Author:ScottWood<scottwood@freescale.com>+*+*Itisassumedthatthefirmware(ortheplatformfile)hasalreadyset+*uptheport.+*/++#include"types.h"+#include"io.h"+#include"ops.h"++structcpm_scc{+u32gsmrl;+u32gsmrh;+u16psmr;+u8res1[2];+u16todr;+u16dsr;+u16scce;+u8res2[2];+u16sccm;+u8res3;+u8sccs;+u8res4[8];+};++structcpm_smc{+u8res1[2];+u16smcmr;+u8res2[2];+u8smce;+u8res3[3];+u8smcm;+u8res4[5];+};++structcpm_param{+u16rbase;+u16tbase;+u8rfcr;+u8tfcr;+};++structcpm_bd{+u16sc;/* Status and Control */+u16len;/* Data length in buffer */+u8*addr;/* Buffer address in host memory */+};++staticvoid*cpcr;+staticstructcpm_param*param;+staticstructcpm_smc*smc;+staticstructcpm_scc*scc;+structcpm_bd*tbdf,*rbdf;+staticu32cpm_cmd;+staticu8*dpram_start;++staticvoid(*do_cmd)(intop);+staticvoid(*enable_port)(void);+staticvoid(*disable_port)(void);++#define CPM_CMD_STOP_TX 4+#define CPM_CMD_RESTART_TX 6+#define CPM_CMD_INIT_RX_TX 0++staticvoidcpm1_cmd(intop)+{+while(in_be16(cpcr)&1)+;++out_be16(cpcr,(op<<8)|cpm_cmd|1);++while(in_be16(cpcr)&1)+;+}++staticvoidcpm2_cmd(intop)+{+while(in_be32(cpcr)&0x10000)+;++out_be32(cpcr,op|cpm_cmd|0x10000);++while(in_be32(cpcr)&0x10000)+;+}++staticvoidsmc_disable_port(void)+{+do_cmd(CPM_CMD_STOP_TX);+out_be16(&smc->smcmr,in_be16(&smc->smcmr)&~3);+}++staticvoidscc_disable_port(void)+{+do_cmd(CPM_CMD_STOP_TX);+out_be32(&scc->gsmrl,in_be32(&scc->gsmrl)&~0x30);+}++staticvoidsmc_enable_port(void)+{+out_be16(&smc->smcmr,in_be16(&smc->smcmr)|3);+do_cmd(CPM_CMD_RESTART_TX);+}++staticvoidscc_enable_port(void)+{+out_be32(&scc->gsmrl,in_be32(&scc->gsmrl)|0x30);+do_cmd(CPM_CMD_RESTART_TX);+}++staticintcpm_serial_open(void)+{+intdpaddr=0x800;+disable_port();++out_8(¶m->rfcr,0x10);+out_8(¶m->tfcr,0x10);++rbdf=(structcpm_bd*)(dpram_start+dpaddr);+rbdf->addr=(u8*)(rbdf+2);+rbdf->sc=0xa000;+rbdf->len=1;++tbdf=rbdf+1;+tbdf->addr=(u8*)(rbdf+2)+1;+tbdf->sc=0x2000;+tbdf->len=1;++sync();+out_be16(¶m->rbase,dpaddr);+out_be16(¶m->tbase,dpaddr+sizeof(structcpm_bd));++do_cmd(CPM_CMD_INIT_RX_TX);++enable_port();+return0;+}++staticvoidcpm_serial_putc(unsignedcharc)+{+while(tbdf->sc&0x8000)+barrier();++sync();++tbdf->addr[0]=c;+eieio();+tbdf->sc|=0x8000;+}++staticunsignedcharcpm_serial_tstc(void)+{+barrier();+return!(rbdf->sc&0x8000);+}++staticunsignedcharcpm_serial_getc(void)+{+unsignedcharc;++while(!cpm_serial_tstc())+;++sync();+c=rbdf->addr[0];+eieio();+rbdf->sc|=0x8000;++returnc;+}++intcpm_console_init(void*devp,structserial_console_data*scdp)+{+void*reg_virt[2];+intis_smc=0,is_cpm2=0,n;+unsignedlongreg_phys;+void*parent;++if(dt_is_compatible(devp,"fsl,cpm1-smc-uart")){+is_smc=1;+}elseif(dt_is_compatible(devp,"fsl,cpm2-scc-uart")){+is_cpm2=1;+}elseif(dt_is_compatible(devp,"fsl,cpm2-smc-uart")){+is_cpm2=1;+is_smc=1;+}++if(is_smc){+enable_port=smc_enable_port;+disable_port=smc_disable_port;+}else{+enable_port=scc_enable_port;+disable_port=scc_disable_port;+}++if(is_cpm2)+do_cmd=cpm2_cmd;+else+do_cmd=cpm1_cmd;++n=getprop(devp,"fsl,cpm-command",&cpm_cmd,4);+if(n<4)+return-1;++n=getprop(devp,"virtual-reg",reg_virt,sizeof(reg_virt));+if(n<(int)sizeof(reg_virt)){+for(n=0;n<2;n++){+if(!dt_xlate_reg(devp,n,®_phys,NULL))+return-1;++reg_virt[n]=(void*)reg_phys;+}+}++if(is_smc)+smc=reg_virt[0];+else+scc=reg_virt[0];++param=reg_virt[1];++parent=get_parent(devp);+if(!parent)+return-1;++n=getprop(parent,"virtual-reg",reg_virt,sizeof(reg_virt));+if(n<(int)sizeof(reg_virt)){+for(n=0;n<2;n++){+if(!dt_xlate_reg(parent,n,®_phys,NULL))+return-1;++reg_virt[n]=(void*)reg_phys;+}+}++cpcr=reg_virt[0];+dpram_start=reg_virt[1];++scdp->open=cpm_serial_open;+scdp->putc=cpm_serial_putc;+scdp->getc=cpm_serial_getc;+scdp->tstc=cpm_serial_tstc;++return0;+}
@@ -82,6 +82,7 @@ int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);intserial_console_init(void);intns16550_console_init(void*devp,structserial_console_data*scdp);intmpsc_console_init(void*devp,structserial_console_data*scdp);+intcpm_console_init(void*devp,structserial_console_data*scdp);void*simple_alloc_init(char*base,unsignedlongheap_size,unsignedlonggranularity,unsignedlongmax_allocs);externvoidflush_cache(void*,unsignedlong);
@@ -121,6 +121,11 @@ int serial_console_init(void)rc=ns16550_console_init(devp,&serial_cd);elseif(dt_is_compatible(devp,"marvell,mpsc"))rc=mpsc_console_init(devp,&serial_cd);+elseif(dt_is_compatible(devp,"fsl,cpm1-scc-uart")||+dt_is_compatible(devp,"fsl,cpm1-smc-uart")||+dt_is_compatible(devp,"fsl,cpm2-scc-uart")||+dt_is_compatible(devp,"fsl,cpm2-smc-uart"))+rc=cpm_console_init(devp,&serial_cd);/* Add other serial console driver calls here */
From: Scott Wood <hidden> Date: 2007-08-20 17:40:16
This will be used by the PlanetCore firmware support to construct
a linux,stdout-path from the serial node that it finds.
---
arch/powerpc/boot/devtree.c | 29 +++++++++++++++++++++++++++++
arch/powerpc/boot/ops.h | 1 +
2 files changed, 30 insertions(+), 0 deletions(-)
@@ -331,3 +331,32 @@ int dt_is_compatible(void *node, const char *compat)return0;}++/* Returns the start of the path within the provided buffer, or NULL on+*error.+*/+char*dt_get_path(void*node,char*buf,intlen)+{+char*name=(char*)prop_buf;+char*orig_buf=buf;++buf+=len;+*--buf=0;++while(node){+intlen=getprop(node,"name",name,MAX_PROP_LEN);+if(len<=0)+break;++if(len+1>buf-orig_buf)+returnNULL;++buf-=len+1;+buf[0]='/';+memcpy(buf+1,name,len);++node=get_parent(node);+}++returnbuf;+}
@@ -90,6 +90,7 @@ int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);intdt_xlate_addr(void*node,u32*buf,intbuflen,unsignedlong*xlated_addr);intdt_is_compatible(void*node,constchar*compat);voiddt_get_reg_format(void*node,u32*naddr,u32*nsize);+char*dt_get_path(void*node,char*buf,intlen);staticinlinevoid*finddevice(constchar*name){
From: Scott Wood <hidden> Date: 2007-08-20 17:40:17
This allows booting on legacy, non-device-tree aware versions of U-boot.
It also fixes up the hardware to match the PCI and chipselect information
in the device tree, as u-boot is inconsistent in setting these up
correctly (or at all).
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/Makefile | 3 +-
arch/powerpc/boot/cuboot-pq2.c | 283 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/boot/devtree.c | 6 +-
arch/powerpc/boot/ops.h | 9 ++
arch/powerpc/platforms/Kconfig | 1 +
5 files changed, 298 insertions(+), 4 deletions(-)
create mode 100644 arch/powerpc/boot/cuboot-pq2.c
@@ -0,0 +1,283 @@+/*+*OldU-bootcompatibilityforPowerQUICCII+*(a.k.a.82xxwithCPM,notthe8240familyofchips)+*+*Author:ScottWood<scottwood@freescale.com>+*+*Copyright(c)2007FreescaleSemiconductor,Inc.+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseversion2aspublished+*bytheFreeSoftwareFoundation.+*/++#include"ops.h"+#include"stdio.h"+#include"cuboot.h"+#include"io.h"++#define TARGET_CPM2+#define TARGET_HAS_ETH1+#include"ppcboot.h"++staticbd_tbd;++structcs_range{+u32csnum;+u32base;/* must be zero */+u32addr;+u32size;+};++structpci_range{+u32flags;+u32pci_addr[2];+u32phys_addr;+u32size[2];+};++structcs_rangecs_ranges_buf[MAX_PROP_LEN/sizeof(structcs_range)];+structpci_rangepci_ranges_buf[MAX_PROP_LEN/sizeof(structpci_range)];++/* Different versions of u-boot put the BCSR in different places, and+*somedon'tsetupthePCIPICatall,soweassumethedevicetreeis+*saneandupdatetheBRxregistersappropriately.+*+*Foranynodedefinedascompatiblewithfsl,pq2-chipselect,+*#address/#sizemustbe2/1forchipselectbus,1/1forparentbus,+*andrangesmustbeforwholechipselects.+*/+staticvoidupdate_cs_ranges(void)+{+u32ctrl_ph;+void*ctrl_node,*bus_node,*parent_node;+u32*ctrl_addr;+unsignedlongctrl_size;+u32naddr,nsize;+intlen;+inti;++bus_node=finddevice("/chipselect");+if(!bus_node||!dt_is_compatible(bus_node,"fsl,pq2-chipselect"))+return;++dt_get_reg_format(bus_node,&naddr,&nsize);+if(naddr!=2||nsize!=1)+gotoerr;++parent_node=get_parent(bus_node);+if(!parent_node)+gotoerr;++dt_get_reg_format(parent_node,&naddr,&nsize);+if(naddr!=1||nsize!=1)+gotoerr;++len=getprop(bus_node,"fsl,ctrl",&ctrl_ph,4);+if(len!=4)+gotoerr;++ctrl_node=find_node_by_prop_value(NULL,"linux,phandle",+(char*)&ctrl_ph,4);+if(!ctrl_node)+gotoerr;++if(!dt_is_compatible(ctrl_node,"fsl,pq2-chipselect-ctrl"))+gotoerr;++if(!dt_xlate_reg(ctrl_node,0,(unsignedlong*)&ctrl_addr,+&ctrl_size))+gotoerr;++len=getprop(bus_node,"ranges",cs_ranges_buf,sizeof(cs_ranges_buf));++for(i=0;i<len/sizeof(structcs_range);i++){+u32base,option;+intcs=cs_ranges_buf[i].csnum;+if(cs>=ctrl_size/8)+gotoerr;++if(cs_ranges_buf[i].base!=0)+gotoerr;++base=in_be32(&ctrl_addr[cs*2]);++/* If CS is already valid, use the existing flags.+*Otherwise,guessasanedefault.+*/+if(base&1){+base&=0x7fff;+option=in_be32(&ctrl_addr[cs*2+1])&0x7fff;+}else{+base=0x1801;+option=0x10;+}++out_be32(&ctrl_addr[cs*2],0);+out_be32(&ctrl_addr[cs*2+1],+option|~(cs_ranges_buf[i].size-1));+out_be32(&ctrl_addr[cs*2],base|cs_ranges_buf[i].addr);+}++return;++err:+printf("Bad /chipselect or fsl,pq2-chipselect-ctrl node\r\n");+}++/* Older u-boots don't set PCI up properly. Update the hardware to match+*thedevicetree.Theprefetchmemregionandnon-prefetchmemregion+*mustbecontiguousinthehostbus.AsrequiredbythePCIbinding,+*PCI#addr/#sizemustbe3/2.Theparentbusmustbe1/1.Only+*32-bitPCIissupported.Allthreeregiontypes(prefetchablemem,+*non-prefetchablemem,andI/O)mustbepresent.+*/+staticvoidfixup_pci(void)+{+structpci_range*mem=NULL,*mmio=NULL,+*io=NULL,*mem_base=NULL;+u32*pci_regs[3];+u8*soc_regs;+inti,len;+void*ctrl_node,*bus_node,*parent_node,*soc_node;+u32naddr,nsize,bus_ph,mem_log2;++ctrl_node=finddevice("/soc/pci");+if(!ctrl_node||!dt_is_compatible(ctrl_node,"fsl,pq2-pci"))+return;++soc_node=finddevice("/soc");+if(!soc_node||!dt_is_compatible(soc_node,"fsl,pq2-soc"))+gotoerr;++for(i=0;i<3;i++)+if(!dt_xlate_reg(ctrl_node,i,+(unsignedlong*)&pci_regs[i],NULL))+gotoerr;++if(!dt_xlate_reg(soc_node,0,(unsignedlong*)&soc_regs,NULL))+gotoerr;++len=getprop(ctrl_node,"fsl,bus",&bus_ph,4);+if(len!=4)+gotoerr;++bus_node=find_node_by_prop_value(NULL,"linux,phandle",+(char*)&bus_ph,4);+if(!bus_node)+gotoerr;++dt_get_reg_format(bus_node,&naddr,&nsize);+if(naddr!=3||nsize!=2)+gotoerr;++parent_node=get_parent(bus_node);+if(!parent_node)+gotoerr;++dt_get_reg_format(parent_node,&naddr,&nsize);+if(naddr!=1||nsize!=1)+gotoerr;++len=getprop(bus_node,"ranges",pci_ranges_buf,+sizeof(pci_ranges_buf));++for(i=0;i<len/sizeof(structpci_range);i++){+u32flags=pci_ranges_buf[i].flags&0x43000000;++if(flags==0x42000000)+mem=&pci_ranges_buf[i];+elseif(flags==0x02000000)+mmio=&pci_ranges_buf[i];+elseif(flags==0x01000000)+io=&pci_ranges_buf[i];+}++if(!mem||!mmio||!io)+gotoerr;++if(mem->phys_addr+mem->size[1]==mmio->phys_addr)+mem_base=mem;+elseif(mmio->phys_addr+mmio->size[1]==mem->phys_addr)+mem_base=mmio;+else+gotoerr;++out_be32(&pci_regs[1][0],mem_base->phys_addr|1);+out_be32(&pci_regs[2][0],~(mem->size[1]+mmio->size[1]-1));++out_be32(&pci_regs[1][1],io->phys_addr|1);+out_be32(&pci_regs[2][1],~(io->size[1]-1));++out_le32(&pci_regs[0][0],mem->pci_addr[1]>>12);+out_le32(&pci_regs[0][2],mem->phys_addr>>12);+out_le32(&pci_regs[0][4],(~(mem->size[1]-1)>>12)|0xa0000000);++out_le32(&pci_regs[0][6],mmio->pci_addr[1]>>12);+out_le32(&pci_regs[0][8],mmio->phys_addr>>12);+out_le32(&pci_regs[0][10],(~(mmio->size[1]-1)>>12)|0x80000000);++out_le32(&pci_regs[0][12],io->pci_addr[1]>>12);+out_le32(&pci_regs[0][14],io->phys_addr>>12);+out_le32(&pci_regs[0][16],(~(io->size[1]-1)>>12)|0xc0000000);++/* Inbound translation */+out_le32(&pci_regs[0][58],0);+out_le32(&pci_regs[0][60],0);++mem_log2=1<<(__ilog2_u32(bd.bi_memsize-1)+1);+out_le32(&pci_regs[0][62],0xa0000000|~((1<<(mem_log2-12))-1));++/* If PCI is disabled, drive RST high to enable. */+if(!(in_le32(&pci_regs[0][32])&1)){+/* Tpvrh (Power valid to RST# high) 100 ms */+udelay(100000);++out_le32(&pci_regs[0][32],1);++/* Trhfa (RST# high to first cfg access) 2^25 clocks */+udelay(1020000);+}++/* Enable bus master and memory access */+out_le32(&pci_regs[0][64],0x80000004);+out_le32(&pci_regs[0][65],in_le32(&pci_regs[0][65])|6);++/* Park the bus on PCI, and elevate PCI's arbitration priority,+*asrequiredbysection9.6oftheuser'smanual.+*/+out_8(&soc_regs[0x10028],3);+out_be32((u32*)&soc_regs[0x1002c],0x01236745);++return;++err:+printf("Bad PCI node\r\n");+}++staticvoidpq2_platform_fixups(void)+{+void*node;++dt_fixup_memory(bd.bi_memstart,bd.bi_memsize);+dt_fixup_mac_addresses(bd.bi_enetaddr,bd.bi_enet1addr);+dt_fixup_cpu_clocks(bd.bi_intfreq,bd.bi_busfreq/4,bd.bi_busfreq);++node=finddevice("/soc/cpm");+if(node){+setprop(node,"clock-frequency",&bd.bi_cpmfreq,4);+setprop(node,"fsl,brg-frequency",&bd.bi_brgfreq,4);+}++update_cs_ranges();+fixup_pci();+}++voidplatform_init(unsignedlongr3,unsignedlongr4,unsignedlongr5,+unsignedlongr6,unsignedlongr7)+{+CUBOOT_INIT();+ft_init(_dtb_start,_dtb_end-_dtb_start,32);+serial_console_init();+platform_ops.fixups=pq2_platform_fixups;+}
@@ -224,7 +224,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,if(!parent)return0;-get_reg_format(parent,&naddr,&nsize);+dt_get_reg_format(parent,&naddr,&nsize);if(nsize>2)return0;
@@ -252,7 +252,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr,if(!parent)break;-get_reg_format(parent,&naddr,&nsize);+dt_get_reg_format(parent,&naddr,&nsize);buflen=getprop(node,"ranges",prop_buf,sizeof(prop_buf));
@@ -17,8 +17,6 @@#include"of.h"-externchar_end[];-/* Value picked to match that used by yaboot */#define PROG_START 0x01400000 /* only used on 64-bit systems */#define RAM_END (512<<20) /* Fixme: use OF */
@@ -0,0 +1,41 @@+/*+*stdlibfunctions+*+*Author:ScottWood<scottwood@freescale.com>+*+*Copyright(c)2007FreescaleSemiconductor,Inc.+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseversion2aspublished+*bytheFreeSoftwareFoundation.+*/++#include"stdlib.h"++/* Not currently supported: leading whitespace, sign, 0x prefix, zero base */+unsignedlonglongintstrtoull(constchar*ptr,char**end,intbase)+{+unsignedlonglongret=0;++while(*ptr){+intdigit;++if(*ptr>='0'&&*ptr<='9')+digit=*ptr-'0';+elseif(*ptr>='A'&&*ptr<='Z')+digit=*ptr-'A'+10;+elseif(*ptr>='a'&&*ptr<='z')+digit=*ptr-'a'+10;+else+break;++ret*=base;+ret+=digit;+ptr++;+}++if(end)+*end=(char*)ptr;++returnret;+}
From: Scott Wood <hidden> Date: 2007-08-20 17:40:21
This is a library that board code can use to extract information from the
PlanetCore configuration keys. PlanetCore is used on various boards from
Embedded Planet.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/Makefile | 2 +-
arch/powerpc/boot/planetcore.c | 160 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/boot/planetcore.h | 49 ++++++++++++
3 files changed, 210 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/boot/planetcore.c
create mode 100644 arch/powerpc/boot/planetcore.h
@@ -0,0 +1,49 @@+#ifndef _PPC_BOOT_PLANETCORE_H_+#define _PPC_BOOT_PLANETCORE_H_++#include"types.h"++#define PLANETCORE_KEY_BOARD_TYPE "BO"+#define PLANETCORE_KEY_BOARD_REV "BR"+#define PLANETCORE_KEY_MB_RAM "D1"+#define PLANETCORE_KEY_MAC_ADDR "EA"+#define PLANETCORE_KEY_FLASH_SPEED "FS"+#define PLANETCORE_KEY_IP_ADDR "IP"+#define PLANETCORE_KEY_KB_NVRAM "NV"+#define PLANETCORE_KEY_PROCESSOR "PR"+#define PLANETCORE_KEY_PROC_VARIANT "PV"+#define PLANETCORE_KEY_SERIAL_BAUD "SB"+#define PLANETCORE_KEY_SERIAL_PORT "SP"+#define PLANETCORE_KEY_SWITCH "SW"+#define PLANETCORE_KEY_TEMP_OFFSET "TC"+#define PLANETCORE_KEY_TARGET_IP "TIP"+#define PLANETCORE_KEY_CRYSTAL_HZ "XT"++/* Prepare the table for processing, by turning all newlines+*intoNULLbytes.+*/+voidplanetcore_prepare_table(char*table);++/* Return the value associated with a given key in text,+*decimal,orhexformat.+*+*Returnszero/NULLonfailure,non-zeroonsuccess.+*/+constchar*planetcore_get_key(constchar*table,constchar*key);+intplanetcore_get_decimal(constchar*table,constchar*key,u64*val);+intplanetcore_get_hex(constchar*table,constchar*key,u64*val);++/* Updates the device tree local-mac-address properties based+*ontheEAtag.+*/+voidplanetcore_set_mac_addrs(constchar*table);++/* Sets the linux,stdout-path in the /chosen node. This requires the+*linux,planetcore-labelpropertyineachserialnode.+*/+voidplanetcore_set_stdout_path(constchar*table);++/* Sets the current-speed property in the serial node. */+voidplanetcore_set_serial_speed(constchar*table);++#endif
From: Scott Wood <hidden> Date: 2007-08-20 17:40:21
Some firmwares (such as PlanetCore) only provide a base MAC address, and
expect the kernel to set certain bits to generate the addresses for the
other ports. As such, MAC addresses are generated that may not correspond
to actual hardware.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/devtree.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
From: Scott Wood <hidden> Date: 2007-08-20 17:40:29
This target produces a flat binary rather than an ELF file, and prints
the start address for the user to jump to (since it is unfortunately not
fixed).
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/Makefile | 5 ++++-
arch/powerpc/boot/wrapper | 11 +++++++++++
2 files changed, 15 insertions(+), 1 deletions(-)
From: Scott Wood <hidden> Date: 2007-08-20 17:40:36
fsl_get_immr() is equivalent to the kernel's get_immrbase() function.
mpc885_get_clock() transforms a crystal frequency into a system frequency
according to the PLL register settings.
pq2_get_clocks() does the same as the above for the PowerQUICC II,
except that it produces several different clocks.
Signed-off-by: Scott Wood <redacted>
---
arch/powerpc/boot/Makefile | 2 +-
arch/powerpc/boot/fsl-soc.c | 47 +++++++++++++++++++++++++++
arch/powerpc/boot/fsl-soc.h | 8 ++++
arch/powerpc/boot/mpc8xx.c | 56 ++++++++++++++++++++++++++++++++
arch/powerpc/boot/mpc8xx.h | 8 ++++
arch/powerpc/boot/pq2.c | 75 +++++++++++++++++++++++++++++++++++++++++++
arch/powerpc/boot/pq2.h | 9 +++++
7 files changed, 204 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/boot/fsl-soc.c
create mode 100644 arch/powerpc/boot/fsl-soc.h
create mode 100644 arch/powerpc/boot/mpc8xx.c
create mode 100644 arch/powerpc/boot/mpc8xx.h
create mode 100644 arch/powerpc/boot/pq2.c
create mode 100644 arch/powerpc/boot/pq2.h
@@ -0,0 +1,56 @@+/*+*MPC8xxsupportfunctions+*+*Author:ScottWood<scottwood@freescale.com>+*+*Copyright(c)2007FreescaleSemiconductor,Inc.+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseversion2aspublished+*bytheFreeSoftwareFoundation.+*/++#include"ops.h"+#include"types.h"+#include"fsl-soc.h"+#include"mpc8xx.h"+#include"stdio.h"+#include"io.h"++#define MPC8XX_PLPRCR (0x284/4) /* PLL and Reset Control Register */++/* Return system clock from crystal frequency */+u32mpc885_get_clock(u32crystal)+{+u32*immr;+u32plprcr;+intmfi,mfn,mfd,pdf,div;+u32ret;++immr=fsl_get_immr();+if(!immr){+printf("mpc885_get_clock: Couldn't get IMMR base.\r\n");+return0;+}++plprcr=in_be32(&immr[MPC8XX_PLPRCR]);++mfi=(plprcr>>16)&15;+if(mfi<5){+printf("Warning: PLPRCR[MFI] value of %d out-of-bounds\r\n",+mfi);+mfi=5;+}++pdf=(plprcr>>1)&0xf;+div=(plprcr>>20)&3;+mfd=(plprcr>>22)&0x1f;+mfn=(plprcr>>27)&0x1f;++ret=crystal*mfi;++if(mfn!=0)+ret+=crystal*mfn/(mfd+1);++returnret/(pdf+1);+}
@@ -0,0 +1,75 @@+/*+*PowerQUICCIIsupportfunctions+*+*Author:ScottWood<scottwood@freescale.com>+*+*Copyright(c)2007FreescaleSemiconductor,Inc.+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseversion2aspublished+*bytheFreeSoftwareFoundation.+*/++#include"ops.h"+#include"types.h"+#include"fsl-soc.h"+#include"pq2.h"+#include"stdio.h"+#include"io.h"++#define PQ2_SCCR (0x10c80/4) /* System Clock Configuration Register */+#define PQ2_SCMR (0x10c88/4) /* System Clock Mode Register */++staticintpq2_corecnf_map[]={+3,2,2,2,4,4,5,9,6,11,8,10,3,12,7,-1,+6,5,13,2,14,4,15,9,0,11,8,10,16,12,7,-1+};++/* Get various clocks from crystal frequency.+*Returnszeroonfailureandnon-zeroonsuccess.+*/+intpq2_get_clocks(u32crystal,u32*sysfreq,u32*corefreq,+u32*timebase,u32*brgfreq)+{+u32*immr;+u32sccr,scmr,mainclk,busclk;+intcorecnf,busdf,plldf,pllmf,dfbrg;++immr=fsl_get_immr();+if(!immr){+printf("pq2_get_clocks: Couldn't get IMMR base.\r\n");+return0;+}++sccr=in_be32(&immr[PQ2_SCCR]);+scmr=in_be32(&immr[PQ2_SCMR]);++dfbrg=sccr&3;+corecnf=(scmr>>24)&0x1f;+busdf=(scmr>>20)&0xf;+plldf=(scmr>>12)&1;+pllmf=scmr&0xfff;++mainclk=crystal*(pllmf+1)/(plldf+1);+busclk=mainclk/(busdf+1);++if(sysfreq)+*sysfreq=mainclk/2;+if(timebase)+*timebase=busclk/4;+if(brgfreq)+*brgfreq=mainclk/(1<<((dfbrg+1)*2));++if(corefreq){+intcoremult=pq2_corecnf_map[corecnf];++if(coremult<0)+*corefreq=mainclk/2;+elseif(coremult==0)+return0;+else+*corefreq=busclk*coremult/2;+}++return1;+}
From: David Gibson <hidden> Date: 2007-08-21 01:50:37
On Mon, Aug 20, 2007 at 12:39:20PM -0500, Scott Wood wrote:
All cuImage types are ignored, as well as preprocessed .lds files,
and the forthcoming zImage.bin files and embedded planet board images.
Signed-off-by: Scott Wood <redacted>
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 01:53:09
On Mon, Aug 20, 2007 at 12:39:45PM -0500, Scott Wood wrote:
This lets udelay() work properly on platforms which use dt_fixup_cpu_clocks.
Signed-off-by: Scott Wood <redacted>
Not entirely sure of ops.h is the right place for the definition, but
it's certainly an improvement over what we have, so:
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:01:31
On Mon, Aug 20, 2007 at 12:39:46PM -0500, Scott Wood wrote:
1. The check whether ranges fits in the buffer was using elements rather
than bytes.
2. Empty ranges were not properly treated as transparent, and missing
ranges were treated as transparent.
3. The loop terminated when translating from the root rather than to. Once
bug #2 was fixed, it failed due to a missing ranges in the root node.
4. In decoding the ranges property, the #size-cells used was that of
the parent, not the child.
Signed-off-by: Scott Wood <redacted>
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:28:23
On Mon, Aug 20, 2007 at 12:39:48PM -0500, Scott Wood wrote:
This can be used rather than doing a simple strcmp, which will fail to
handle multiple compatible entries.
Signed-off-by: Scott Wood <redacted>
Not sure if it's the simplest way we could accomplish this, but it
will do. Certainly the strcmp()s we use at the moment are wrong.
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:30:44
On Mon, Aug 20, 2007 at 12:39:49PM -0500, Scott Wood wrote:
1. ft_create_node was returning the internal pointer rather than a phandle.
2. ft_find_device_rel was treating a "top" phandle of NULL as an error,
rather than as the root of the tree.
3. Return the node's name when getprop() is called with the "name"
property.
Hrm. I'm not convinced. (1) certainly needs fixing. (2) is kind of
unclear - there is an ft_find_device() after all for doing root-based
searches. (3) I really dislike; I just don't see the point.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:31:26
On Mon, Aug 20, 2007 at 12:39:51PM -0500, Scott Wood wrote:
Also, include types.h from io.h, so callers don't have to.
Signed-off-by: Scott Wood <redacted>
Seems reasonable.
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:38:24
On Mon, Aug 20, 2007 at 12:39:54PM -0500, Scott Wood wrote:
1. Search the entire compatible list for serial devices.
The serial code previously did a simple strcmp on the compatible
node; this fails when the match string is not the first compatible
listed. Use dt_is_compatible() instead.
2. Don't call serial_edit_cmdline if getc isn't defined.
Signed-off-by: Scott Wood <redacted>
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:39:43
On Mon, Aug 20, 2007 at 12:39:55PM -0500, Scott Wood wrote:
Declarations in various users are removed.
Signed-off-by: Scott Wood <redacted>
Hrm... it should go in a header, certainly, but I wonder if io.h would
be more suitable than the already rather bloated ops.h.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:42:00
On Mon, Aug 20, 2007 at 12:39:57PM -0500, Scott Wood wrote:
This serial port is used on all 8xx, many 82xx, and some 85xx chips.
The driver requires that the port has already been set up by the firmware
and/or platform code.
Signed-off-by: Scott Wood <redacted>
@@ -121,6 +121,11 @@ int serial_console_init(void)rc=ns16550_console_init(devp,&serial_cd);elseif(dt_is_compatible(devp,"marvell,mpsc"))rc=mpsc_console_init(devp,&serial_cd);+elseif(dt_is_compatible(devp,"fsl,cpm1-scc-uart")||+dt_is_compatible(devp,"fsl,cpm1-smc-uart")||+dt_is_compatible(devp,"fsl,cpm2-scc-uart")||+dt_is_compatible(devp,"fsl,cpm2-smc-uart"))+rc=cpm_console_init(devp,&serial_cd);
If all these variants admit a compatible driver, there really should
be defined a compatible value that they all include in the device
tree. But I guess you'd still need all these tests for device trees
which didn't have it.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:43:36
On Mon, Aug 20, 2007 at 12:39:58PM -0500, Scott Wood wrote:
Most of these were previously used by numerous C files and
redeclared in each one.
Signed-off-by: Scott Wood <redacted>
Hrm. I like the idea of putting these into a header, but I don't so
much like putting them in ops.h, which is showing a tendency to become
a pile of random junk, rather than actually related to "ops".
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 02:44:32
On Mon, Aug 20, 2007 at 12:40:01PM -0500, Scott Wood wrote:
This allows booting on legacy, non-device-tree aware versions of
U-boot.
Is this really sufficient for all 8xx platforms?
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
@@ -0,0 +1,41 @@+/*+*stdlibfunctions+*+*Author:ScottWood<scottwood@freescale.com>+*+*Copyright(c)2007FreescaleSemiconductor,Inc.+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseversion2aspublished+*bytheFreeSoftwareFoundation.+*/++#include"stdlib.h"++/* Not currently supported: leading whitespace, sign, 0x prefix, zero base */+unsignedlonglongintstrtoull(constchar*ptr,char**end,intbase)+{+unsignedlonglongret=0;++while(*ptr){+intdigit;++if(*ptr>='0'&&*ptr<='9')+digit=*ptr-'0';+elseif(*ptr>='A'&&*ptr<='Z')+digit=*ptr-'A'+10;+elseif(*ptr>='a'&&*ptr<='z')+digit=*ptr-'a'+10;+else+break;
Hrm... I note this has no sort of error checking if the string has
digits which don't fit in the given base.
quoted hunk
+ ret *= base;
+ ret += digit;
+ ptr++;
+ }
+
+ if (end)
+ *end = (char *)ptr;
+
+ return ret;
+}
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:03:12
On Mon, Aug 20, 2007 at 12:40:05PM -0500, Scott Wood wrote:
This will be used by the PlanetCore firmware support to construct
a linux,stdout-path from the serial node that it finds.
Err... no S-o-b line..
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:06:41
On Mon, Aug 20, 2007 at 12:40:07PM -0500, Scott Wood wrote:
strncmp() will be needed for PlanetCore firmware support.
Signed-off-by: Scott Wood <redacted>
Hmm. They should be moved, but if we are, I'm inclined to implement
them in string.S with the rest of the string functions, rather than as
inlines. Below is a patch I've had in my queue for some time which
does exactly that for strchr().
Move bootwrapper's strchr() from .h to string.S
Currently the bootwrapper has an implementation of strchr(), but it's
done as an inline in flatdevtree_env.h, rather than implemented in
string.S with the rest of the string functions. This patch moves it
to string.S, matching the other string functions.
Signed-off-by: David Gibson <redacted>
Index: working-2.6/arch/powerpc/boot/string.S
===================================================================
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:16:58
On Mon, Aug 20, 2007 at 12:40:08PM -0500, Scott Wood wrote:
This is a library that board code can use to extract information from the
PlanetCore configuration keys. PlanetCore is used on various boards from
Embedded Planet.
Signed-off-by: Scott Wood <redacted>
Some comments describing the Planetcore table format wouldn't go
astray. I vaguely recall it from when I worked with an EP405 years
and years ago, but...
Hrm.. this loop makes my brain hurt. It's correct as far as I can
determine what it's supposed to be doing, but I think there's got to
be a way to make what it's doing a little more obvious.
+ *table = 0;
+}
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:20:24
On Mon, Aug 20, 2007 at 12:40:11PM -0500, Scott Wood wrote:
Some firmwares (such as PlanetCore) only provide a base MAC address, and
expect the kernel to set certain bits to generate the addresses for the
other ports. As such, MAC addresses are generated that may not correspond
to actual hardware.
Signed-off-by: Scott Wood <redacted>
Seems a reasonable idea for robustness.
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:25:46
On Mon, Aug 20, 2007 at 12:40:13PM -0500, Scott Wood wrote:
fsl_get_immr() is equivalent to the kernel's get_immrbase() function.
I notice that this function assumes that P==V. Is that true for all
relevant platforms at this point?
mpc885_get_clock() transforms a crystal frequency into a system frequency
according to the PLL register settings.
pq2_get_clocks() does the same as the above for the PowerQUICC II,
except that it produces several different clocks.
I'd prefer if these functions worked analagously to the
ibm440gp_fixup_clocks() function in ebony.c and fixed up the clock
values in the device tree directly, rather than returning them (where
the caller will presumably poke them into the device tree).
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:27:36
On Mon, Aug 20, 2007 at 12:40:10PM -0500, Scott Wood wrote:
This target produces a flat binary rather than an ELF file, and prints
the start address for the user to jump to (since it is unfortunately not
fixed).
For platforms whose firmware can't take an image format including an
entry point, we shouldn't make the user faff around with the non-fixed
entry point. Instead we should modify the entry sequence for those
platforms so that the entry point *is* fixed.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:30:10
On Mon, Aug 20, 2007 at 12:40:02PM -0500, Scott Wood wrote:
This allows booting on legacy, non-device-tree aware versions of U-boot.
It also fixes up the hardware to match the PCI and chipselect information
in the device tree, as u-boot is inconsistent in setting these up
correctly (or at all).
Signed-off-by: Scott Wood <redacted>
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-21 03:33:06
On Mon, Aug 20, 2007 at 12:39:52PM -0500, Scott Wood wrote:
U-boots more recent than when ppcboot.h was forked allow the board config
file to enable additional ethernet ports explicitly, rather than
using a hardcoded list of targets. This allows bootwrapper platform
files to do the same.
Fortunately, nothing after the ethernet addresses is of interest to
cuboot platforms, so the inevitable mismatches won't be too
catastrophic.
Good grief. Increases my already considerable wonderment at the fact
that anyone ever thought bd_t was an acceptable way of passing data to
the OS.
Signed-off-by: Scott Wood <redacted>
I can't say I'm thrilled at having two basically incompatible ways of
specifying the layout of this vital structure, but bd_t is so fscked
by design anyway, what's one more hack for convenience.
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: Scott Wood <hidden> Date: 2007-08-21 16:09:58
David Gibson wrote:
On Mon, Aug 20, 2007 at 12:39:49PM -0500, Scott Wood wrote:
quoted
1. ft_create_node was returning the internal pointer rather than a phandle.
2. ft_find_device_rel was treating a "top" phandle of NULL as an error,
rather than as the root of the tree.
3. Return the node's name when getprop() is called with the "name"
property.
Hrm. I'm not convinced. (1) certainly needs fixing. (2) is kind of
unclear - there is an ft_find_device() after all for doing root-based
searches.
The point of #2 was as part of the fix to #1 -- otherwise, the same
check for NULL would have to be moved into ft_create_node to
conditionally call ft_find_device or ft_find_device_rel.
The non-relative function should probably be removed, though.
From: Scott Wood <hidden> Date: 2007-08-21 16:12:08
David Gibson wrote:
On Mon, Aug 20, 2007 at 12:39:55PM -0500, Scott Wood wrote:
quoted
Declarations in various users are removed.
Signed-off-by: Scott Wood <redacted>
Hrm... it should go in a header, certainly, but I wonder if io.h would
be more suitable than the already rather bloated ops.h.
It's not really I/O either... Maybe we should make a misc.h to put
stuff in that doesn't fit anywhere else and doesn't really warrant its
own header file?
-Scott
If all these variants admit a compatible driver, there really should
be defined a compatible value that they all include in the device
tree.
That's what I did last time, and several people complained. :-)
The issue was that while there is a lot in common between these
variants, there's no one common subset that can be used to drive the
device without knowledge of what variant it is (or knowledge of where
the firmware placed the descriptors).
But I guess you'd still need all these tests for device trees
which didn't have it.
From: Scott Wood <hidden> Date: 2007-08-21 16:20:21
David Gibson wrote:
On Mon, Aug 20, 2007 at 12:40:01PM -0500, Scott Wood wrote:
quoted
This allows booting on legacy, non-device-tree aware versions of
U-boot.
Is this really sufficient for all 8xx platforms?
It should be enough for all u-boot-based 8xx boards, barring some u-boot
which needs special fixups (as is done in cuboot-pq2.c). If such a need
arises, they can be added to cuboot-8xx.c (if they're generic enough to
work on all boards, even if not actually needed) or to a board-specific
platform file (which can coexist just fine with the generic 8xx one).
-Scott
Hrm.. this loop makes my brain hurt. It's correct as far as I can
determine what it's supposed to be doing, but I think there's got to
be a way to make what it's doing a little more obvious.
How about something like this:
char last = 0;
while (1) {
if (*table == '\n') {
*table = 0;
if (last == *table)
return;
}
last = *table++;
}
-Scott
From: Scott Wood <hidden> Date: 2007-08-21 16:34:45
David Gibson wrote:
On Mon, Aug 20, 2007 at 12:40:13PM -0500, Scott Wood wrote:
quoted
fsl_get_immr() is equivalent to the kernel's get_immrbase() function.
I notice that this function assumes that P==V. Is that true for all
relevant platforms at this point?
Yes. If that ever changes, we'd probably need to add a virtual-immr or
similar.
quoted
mpc885_get_clock() transforms a crystal frequency into a system frequency
according to the PLL register settings.
pq2_get_clocks() does the same as the above for the PowerQUICC II,
except that it produces several different clocks.
I'd prefer if these functions worked analagously to the
ibm440gp_fixup_clocks() function in ebony.c and fixed up the clock
values in the device tree directly, rather than returning them (where
the caller will presumably poke them into the device tree).
I wanted to separate the register interpretation from the knowledge of
where things are in the device tree.
-Scott
From: David Gibson <hidden> Date: 2007-08-22 01:09:07
On Tue, Aug 21, 2007 at 11:09:58AM -0500, Scott Wood wrote:
David Gibson wrote:
quoted
On Mon, Aug 20, 2007 at 12:39:49PM -0500, Scott Wood wrote:
quoted
1. ft_create_node was returning the internal pointer rather than a phandle.
2. ft_find_device_rel was treating a "top" phandle of NULL as an error,
rather than as the root of the tree.
3. Return the node's name when getprop() is called with the "name"
property.
Hrm. I'm not convinced. (1) certainly needs fixing. (2) is kind of
unclear - there is an ft_find_device() after all for doing root-based
searches.
The point of #2 was as part of the fix to #1 -- otherwise, the same
check for NULL would have to be moved into ft_create_node to
conditionally call ft_find_device or ft_find_device_rel.
Um... oh, ok, I hadn't spotted that (1) made ft_create() use
find_device_rel(). That sounds doubly wrong: you have the internal
offset pointer, you should be able to create a phandle using the
phandle allocation stuff, rather than having to refind the node you've
just created from the parent.
The non-relative function should probably be removed, though.
Well, yes, I wouldn't have much problem with just having a relative
version.
Come to that, I don't actually care all that much what happens to
flatdevtree.c, seeing as I intend to replace it with libfdt, just as
soon as I can get enough other things off my plate.
quoted
(3) I really dislike; I just don't see the point.
It's needed by dt_get_path().
No, it isn't. dt_get_path() needs *some* way of getting the name of a
node, but it could be a separate function, which I think would be
preferable rather than folding it into getprop - you don't need to
search for the name, so a getname() function would have quite a
different structure to getprop().
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-22 01:09:46
On Tue, Aug 21, 2007 at 11:12:08AM -0500, Scott Wood wrote:
David Gibson wrote:
quoted
On Mon, Aug 20, 2007 at 12:39:55PM -0500, Scott Wood wrote:
quoted
Declarations in various users are removed.
Signed-off-by: Scott Wood <redacted>
Hrm... it should go in a header, certainly, but I wonder if io.h would
be more suitable than the already rather bloated ops.h.
It's not really I/O either... Maybe we should make a misc.h to put
stuff in that doesn't fit anywhere else and doesn't really warrant its
own header file?
It's not I/O, but I believe it's main intended use is for delays to
get I/O timing correct.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
If all these variants admit a compatible driver, there really should
be defined a compatible value that they all include in the device
tree.
That's what I did last time, and several people complained. :-)
The issue was that while there is a lot in common between these
variants, there's no one common subset that can be used to drive the
device without knowledge of what variant it is (or knowledge of where
the firmware placed the descriptors).
Ah, ok. Fair enough then.
quoted
But I guess you'd still need all these tests for device trees
which didn't have it.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
Hrm.. this loop makes my brain hurt. It's correct as far as I can
determine what it's supposed to be doing, but I think there's got to
be a way to make what it's doing a little more obvious.
How about something like this:
char last = 0;
while (1) {
if (*table == '\n') {
*table = 0;
if (last == *table)
return;
}
last = *table++;
}
*thinks*
How about:
do {
if (*table == '\n')
*table = '\0';
table++;
} while (*(table-1) || (*table != '\n'));
*table = '\0';
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-22 01:30:42
On Tue, Aug 21, 2007 at 11:34:45AM -0500, Scott Wood wrote:
David Gibson wrote:
quoted
On Mon, Aug 20, 2007 at 12:40:13PM -0500, Scott Wood wrote:
quoted
fsl_get_immr() is equivalent to the kernel's get_immrbase() function.
I notice that this function assumes that P==V. Is that true for all
relevant platforms at this point?
Yes. If that ever changes, we'd probably need to add a virtual-immr or
similar.
Ok.
quoted
quoted
mpc885_get_clock() transforms a crystal frequency into a system frequency
according to the PLL register settings.
pq2_get_clocks() does the same as the above for the PowerQUICC II,
except that it produces several different clocks.
I'd prefer if these functions worked analagously to the
ibm440gp_fixup_clocks() function in ebony.c and fixed up the clock
values in the device tree directly, rather than returning them (where
the caller will presumably poke them into the device tree).
I wanted to separate the register interpretation from the knowledge of
where things are in the device tree.
Hrm. I considered that for a while with 44x, before deciding it
wasn't worth the extra hassle of passing a bunch of things around. If
you look at the 44x version, you'll see that the device tree poking
part is just the last few lines of the function and more-or-less
independent from the rest of it. So it should be easy to make the
function separable into hw-logic vs. dt-logic portions if we ever need
to.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: David Gibson <hidden> Date: 2007-08-22 01:47:52
On Tue, Aug 21, 2007 at 11:20:21AM -0500, Scott Wood wrote:
David Gibson wrote:
quoted
On Mon, Aug 20, 2007 at 12:40:01PM -0500, Scott Wood wrote:
quoted
This allows booting on legacy, non-device-tree aware versions of
U-boot.
Is this really sufficient for all 8xx platforms?
It should be enough for all u-boot-based 8xx boards, barring some u-boot
which needs special fixups (as is done in cuboot-pq2.c). If such a need
arises, they can be added to cuboot-8xx.c (if they're generic enough to
work on all boards, even if not actually needed) or to a board-specific
platform file (which can coexist just fine with the generic 8xx
one).
Ok. Presumably our bd_t won't exactly line up for all 8xx (since it
varies from platform to platform, yes?) - but I gather the only bits
we use do match up. That's probably worth a comment, so that someone
doesn't try using some later bd_t field which is only in the right
place for some 8xx systems.
Otherwise,
Acked-by: David Gibson <redacted>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: Scott Wood <hidden> Date: 2007-08-22 17:25:05
On Wed, Aug 22, 2007 at 11:09:07AM +1000, David Gibson wrote:
On Tue, Aug 21, 2007 at 11:09:58AM -0500, Scott Wood wrote:
quoted
The point of #2 was as part of the fix to #1 -- otherwise, the same
check for NULL would have to be moved into ft_create_node to
conditionally call ft_find_device or ft_find_device_rel.
Um... oh, ok, I hadn't spotted that (1) made ft_create() use
find_device_rel(). That sounds doubly wrong: you have the internal
offset pointer, you should be able to create a phandle using the
phandle allocation stuff, rather than having to refind the node you've
just created from the parent.
Yeah, that'd make more sense.
quoted
quoted
(3) I really dislike; I just don't see the point.
It's needed by dt_get_path().
No, it isn't. dt_get_path() needs *some* way of getting the name of a
node, but it could be a separate function, which I think would be
preferable rather than folding it into getprop - you don't need to
search for the name, so a getname() function would have quite a
different structure to getprop().
I'd rather not add a new entry in ops just for that; it's more of an
attribute of the dtb format that name is handled specially. IIUC, on
real OF you'd use the same code for both.
Plus, something might come along that needs to dynamically look for
either name or something else. It's more flexible this way.
-Scott
From: David Gibson <hidden> Date: 2007-08-23 02:01:47
On Wed, Aug 22, 2007 at 12:24:56PM -0500, Scott Wood wrote:
On Wed, Aug 22, 2007 at 11:09:07AM +1000, David Gibson wrote:
quoted
On Tue, Aug 21, 2007 at 11:09:58AM -0500, Scott Wood wrote:
quoted
The point of #2 was as part of the fix to #1 -- otherwise, the same
check for NULL would have to be moved into ft_create_node to
conditionally call ft_find_device or ft_find_device_rel.
Um... oh, ok, I hadn't spotted that (1) made ft_create() use
find_device_rel(). That sounds doubly wrong: you have the internal
offset pointer, you should be able to create a phandle using the
phandle allocation stuff, rather than having to refind the node you've
just created from the parent.
Yeah, that'd make more sense.
quoted
quoted
quoted
(3) I really dislike; I just don't see the point.
It's needed by dt_get_path().
No, it isn't. dt_get_path() needs *some* way of getting the name of a
node, but it could be a separate function, which I think would be
preferable rather than folding it into getprop - you don't need to
search for the name, so a getname() function would have quite a
different structure to getprop().
I'd rather not add a new entry in ops just for that; it's more of an
attribute of the dtb format that name is handled specially. IIUC, on
real OF you'd use the same code for both.
Actually, no - sorry, that's the other problem with this, which I
forgot to mention. On real OF, the "name" property contains the
node's name *without the unit address*; that is, only the portion
before the '@'. So your getprop change does not match real OF
behaviour - and real OF behaviour will not do what you want for
dt_get_path().
Actually, in any case, I don't think we want to implement get_path()
this way for real OF. Better to have get_path() itself as a callback:
on real OF I believe we can directly ask for the full path to a given
phandle, the get name based implementation can then be made specific
to the flat device tree.
Or actually, I think we might be able to come up with a get_path()
implementation for flat tree that's less hideous than repeatedly
calling get_parent() which is an ugly, ugly operation on the flat tree
(and will get worse with libfdt).
Plus, something might come along that needs to dynamically look for
either name or something else. It's more flexible this way.
Hrm... "something might come along" just seems contrived to me.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: Scott Wood <hidden> Date: 2007-08-23 17:48:30
David Gibson wrote:
Actually, no - sorry, that's the other problem with this, which I
forgot to mention. On real OF, the "name" property contains the
node's name *without the unit address*; that is, only the portion
before the '@'. So your getprop change does not match real OF
behaviour - and real OF behaviour will not do what you want for
dt_get_path().
Ah, OK.
Actually, in any case, I don't think we want to implement get_path()
this way for real OF. Better to have get_path() itself as a callback:
on real OF I believe we can directly ask for the full path to a given
phandle, the get name based implementation can then be made specific
to the flat device tree.
Or actually, I think we might be able to come up with a get_path()
implementation for flat tree that's less hideous than repeatedly
calling get_parent() which is an ugly, ugly operation on the flat tree
It's likely to be ugly no matter what, though I'll try to come up with
something slightly nicer. If I were doing this code from scratch, I'd
probably liven the tree first and reflatten it to pass to the kernel.
(and will get worse with libfdt).
Why is that?
quoted
Plus, something might come along that needs to dynamically look for
either name or something else. It's more flexible this way.
Hrm... "something might come along" just seems contrived to me.
Well, I generally prefer doing things the more flexible way in the
absence of a good reason not to. OF returning the bare name is a good
reason not to.
-Scott
Actually, in any case, I don't think we want to implement get_path()
this way for real OF. Better to have get_path() itself as a callback:
on real OF I believe we can directly ask for the full path to a given
phandle,
Yes. "package-to-path" from the client interface.
Segher
From: David Gibson <hidden> Date: 2007-08-24 01:01:22
On Thu, Aug 23, 2007 at 12:48:30PM -0500, Scott Wood wrote:
David Gibson wrote:
quoted
Actually, no - sorry, that's the other problem with this, which I
forgot to mention. On real OF, the "name" property contains the
node's name *without the unit address*; that is, only the portion
before the '@'. So your getprop change does not match real OF
behaviour - and real OF behaviour will not do what you want for
dt_get_path().
Ah, OK.
quoted
Actually, in any case, I don't think we want to implement get_path()
this way for real OF. Better to have get_path() itself as a callback:
on real OF I believe we can directly ask for the full path to a given
phandle, the get name based implementation can then be made specific
to the flat device tree.
Or actually, I think we might be able to come up with a get_path()
implementation for flat tree that's less hideous than repeatedly
calling get_parent() which is an ugly, ugly operation on the flat tree
It's likely to be ugly no matter what, though I'll try to come up with
something slightly nicer. If I were doing this code from scratch, I'd
probably liven the tree first and reflatten it to pass to the kernel.
Eh, probably not worth bothering doing an actual implementation at
this stage - I'll have to redo it for libfdt anyway.
quoted
(and will get worse with libfdt).
Why is that?
flatdevtree uses some of the information it caches in the phandle
context stuff to remember who's the parent of a node. libfdt uses raw
offsets into the structure, so the *only* way to implement
get_parent() is to rescan the dt from the beginning, keeping track of
parents until reaching the given node.
quoted
quoted
Plus, something might come along that needs to dynamically look for
either name or something else. It's more flexible this way.
Hrm... "something might come along" just seems contrived to me.
Well, I generally prefer doing things the more flexible way in the
absence of a good reason not to. OF returning the bare name is a good
reason not to.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
From: Scott Wood <hidden> Date: 2007-08-24 14:48:46
On Fri, Aug 24, 2007 at 11:01:22AM +1000, David Gibson wrote:
On Thu, Aug 23, 2007 at 12:48:30PM -0500, Scott Wood wrote:
quoted
It's likely to be ugly no matter what, though I'll try to come up with
something slightly nicer. If I were doing this code from scratch, I'd
probably liven the tree first and reflatten it to pass to the kernel.
Eh, probably not worth bothering doing an actual implementation at
this stage - I'll have to redo it for libfdt anyway.
Too late, I already wrote it -- it wasn't as bad as I thought it would
be.
flatdevtree uses some of the information it caches in the phandle
context stuff to remember who's the parent of a node. libfdt uses raw
offsets into the structure, so the *only* way to implement
get_parent() is to rescan the dt from the beginning, keeping track of
parents until reaching the given node.
From: David Gibson <hidden> Date: 2007-08-24 22:17:10
On Fri, Aug 24, 2007 at 09:48:37AM -0500, Scott Wood wrote:
On Fri, Aug 24, 2007 at 11:01:22AM +1000, David Gibson wrote:
quoted
On Thu, Aug 23, 2007 at 12:48:30PM -0500, Scott Wood wrote:
quoted
It's likely to be ugly no matter what, though I'll try to come up with
something slightly nicer. If I were doing this code from scratch, I'd
probably liven the tree first and reflatten it to pass to the kernel.
Eh, probably not worth bothering doing an actual implementation at
this stage - I'll have to redo it for libfdt anyway.
Too late, I already wrote it -- it wasn't as bad as I thought it would
be.
Well, there you go.
quoted
flatdevtree uses some of the information it caches in the phandle
context stuff to remember who's the parent of a node. libfdt uses raw
offsets into the structure, so the *only* way to implement
get_parent() is to rescan the dt from the beginning, keeping track of
parents until reaching the given node.
What is the benefit of doing it that way?
Most other operations are simpler like this - no more futzing around
converting between phandles and offsets and back again at the
beginning and end of most functions.
More importantly, it allows libfdt to be "stateless" in the sense that
you can manipulate the device tree without having to maintain any
context or state structure apart from the device tree blob itself.
That's particularly handy for doing read-only accesses really early
with a minimum of fuss.
In particular, it means libfdt does not need malloc(). That can be
rather useful for some that's supposed to be embeddable in a variety
of strange, constrained environments such as bootloaders and
firmwares.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson