Hi Matthew,

On 06/08/2016 11:56 PM, mgerlach wrote:
> Hi Everyone,
>
> This discussion of creating device trees especially in the context of
> upgrading linux is extremely relevant.  I have experienced my fair of pain
> debugging device trees during kernel upgrades, and this pain is a frequent 
> topic
> at the various Linux conferences.  It is safe to say, this problem is not
> unique to SOCFGPAs, but the FPGA can make the pain more acute.
>
> As some background, sopc2dts is an Open Source tool that can help make 
> device
> trees based on a FPGA designs described in a "sopcinfo" file produced by
> Altera design tools.  Sopc2dts predates SOCFPGAs and was created by
> Walter Goossen originally for Linux running on Nios-II.  Sopc2dts can
> also be used to make device trees for SOCFPGAs, but as many folks have 
> pointed out, the output of sopc2dts does not always produce suitable 
> device
> trees for every version of the Linux kernel.
>
> The SoC Embedded Development Suite (SoCEDS) includes a snapshot of 
> sopc2dts and
> a set of "board info" files that can be used to create device trees for 
> the
> the reference designs using the kernel version shipped with that version 
> of SoCEDS.  Version 16.0 of SoCEDS shipped with linux-3.10-ltsi.
>
> When upgrading kernels, the process people have described by taking the 
> base
> device tree found in the kernel version's source tree and merging it with
> the FPGA portion of the output to Sopc2dts is a perfectly reasonable work
> flow.  Interestingly, this work flow has similarities to using dynamic
> device tree overlays in the boot flow.  
>
> With dynamic device tree overlays, Linux could boot using the minimum 
> device 
> tree to get to user space. Once in user space, one or more overlays could 
> be 
> applied to the live device tree in order to enable more components on the 
> SoC,
> program the FPGA, and instantiate necessary drivers for components in the 
> FPGA.
> I think such a boot flow would be easier to debug and provide substantial 
> flexibility to manage the overall boot flow.  I would like to hear what 
> other folks think about using dynamic device tree overlays.

I also think overlays are the way to go. I actually posted a patch to
sopc2dts a year ago with initial support for this. I currently have no
active projects in which I can easily try this, but if you or anyone
else has the time to look at it that would be awesome.
I'll attach the patch to this mail as well. I haven't tested it but it
still applies and nothing much has changed in the last year so I think
we should be good.
Let me know what you think!

Walter

> Matthew Gerlach
>

diff --git a/Sopc2DTS.java b/Sopc2DTS.java
index da701df..115d328 100644
--- a/Sopc2DTS.java
+++ b/Sopc2DTS.java
@@ -58,6 +58,7 @@ public class Sopc2DTS implements LogListener {
 	protected CLParameter bridgeRemoval = new CLParameter("balanced");
 	protected CLParameter outputFileName = new CLParameter("");
 	protected CLParameter outputType = new CLParameter("dts");
+	protected CLParameter overlayTarget = new CLParameter("");
 	protected CLParameter pov = new CLParameter("");
 	protected CLParameter povType = new CLParameter("cpu");
 	protected CLParameter bootargs = new CLParameter("");
@@ -114,8 +115,9 @@ public class Sopc2DTS implements LogListener {
 		vOptions.add(new CommandLineOption("no-timestamp", null, excludeTimeStamp, false, false, "Don't add a timestamp to generated files", null));
 		vOptions.add(new CommandLineOption("input", 	"i", inputFileName, 	true, true, "The sopcinfo file (optional in gui mode)", "sopcinfo file"));
 		vOptions.add(new CommandLineOption("output",	"o", outputFileName,	true, false,"The output filename","filename"));
+		vOptions.add(new CommandLineOption("overlay-target",null, overlayTarget,true, false,"Target node for dt-overlay","node-label"));
 		vOptions.add(new CommandLineOption("pov", 		"p", pov,		 		true, false,"The point of view to generate from. Defaults to the first cpu found", "component name"));
-		vOptions.add(new CommandLineOption("pov-type", 	null, povType,			true, false,"The point of view device type", "{cpu,pci}"));
+		vOptions.add(new CommandLineOption("pov-type", 	null, povType,			true, false,"The point of view device type", "{cpu,pci,overlay}"));
 		vOptions.add(new CommandLineOption("reset",		null, showReset,		false,false,"Show reset interfaces in graph", null));
 		vOptions.add(new CommandLineOption("sort", 		"s", sort,		 		true, false,"Sort components by", "{none,address,name,label}"));
 		vOptions.add(new CommandLineOption("streaming",	null, showStreaming,	false,false,"Show streaming interfaces in graph", null));
@@ -154,6 +156,7 @@ public class Sopc2DTS implements LogListener {
 			bInfo = new BoardInfo();
 		}
 		SICBridge.setRemovalStrategy(bridgeRemoval.value);
+		bInfo.setOverlayTarget(overlayTarget.value);
 		if(pov.value.length()>0)
 		{
 			bInfo.setPov(pov.value);
diff --git a/sopc2dts/generators/DTGenerator.java b/sopc2dts/generators/DTGenerator.java
index b88450c..70cb599 100644
--- a/sopc2dts/generators/DTGenerator.java
+++ b/sopc2dts/generators/DTGenerator.java
@@ -21,6 +21,7 @@ package sopc2dts.generators;
 
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.Vector;
 
 import sopc2dts.Logger;
@@ -58,73 +59,60 @@ public abstract class DTGenerator extends AbstractSopcGenerator {
 		super(s, isText);
 	}
 
-	protected synchronized DTNode getDTOutput(BoardInfo bi)
+	protected synchronized DTNode getDTOutput(BoardInfo bi) {
+		return getDTOutput(bi, bi.getPovType().equals(PovType.OVERLAY));
+	}
+
+	protected synchronized DTNode getDTOutput(BoardInfo bi, boolean doAddSymbolsNode)
 	{
 		vHandled = new Vector<BasicComponent>();
 		DTNode rootNode = new DTNode("/");
 		BasicComponent povComponent = getPovComponent(bi);
-		DTNode sopcNode;
-		DTNode chosenNode;
-		DTNode clocksNode = null;
 		if(povComponent!=null)
 		{
+			DTNode sopcNode = null;
+			DTNode chosenNode = null;
+			DTNode clocksNode = null;
 			int addrCells = povComponent.getInterfaces(SystemDataType.MEMORY_MAPPED, true).firstElement().getPrimaryWidth();
 			int sizeCells = povComponent.getInterfaces(SystemDataType.MEMORY_MAPPED, true).firstElement().getSecondaryWidth();
-			if(bi.getPovType().equals(PovType.CPU))
-			{
-				DTNode cpuNode = getCpuNodes(bi, povComponent);
-				DTNode memNode = getMemoryNode(bi, povComponent, addrCells, sizeCells);
-				DTNode aliasNode = null;
-				sopcNode = new DTNode("sopc@0", "sopc0");
-				chosenNode = getChosenNode(bi);
-				clocksNode = getClocksNode(bi);
-				rootNode.addProperty(new DTProperty("model","ALTR," + sys.getSystemName()));
-				rootNode.addProperty(new DTProperty("compatible","ALTR," + sys.getSystemName()));
-				rootNode.addProperty(new DTProperty("#address-cells", (long)addrCells));
-				rootNode.addProperty(new DTProperty("#size-cells",(long)sizeCells));
-				Vector<Parameter> vAliases = bi.getAliases();
-				if (vAliases.size() > 0) {
-					aliasNode = new DTNode("aliases");
-					for (Parameter p : vAliases) {
-						aliasNode.addProperty(new DTProperty(p.getName(),p.getValue()));
+			switch(bi.getPovType()) {
+				case CPU: {
+					DTNode cpuNode = getCpuNodes(bi, povComponent);
+					DTNode memNode = getMemoryNode(bi, povComponent, addrCells, sizeCells);
+					sopcNode = new DTNode("sopc@0", "sopc0");
+					DTNode aliasNode = getAliasNode(bi, povComponent,"/" + sopcNode.getName());
+					chosenNode = getChosenNode(bi);
+					clocksNode = getClocksNode(bi);
+					rootNode.addProperty(new DTProperty("model","ALTR," + sys.getSystemName()));
+					rootNode.addProperty(new DTProperty("compatible","ALTR," + sys.getSystemName()));
+					rootNode.addProperty(new DTProperty("#address-cells", (long)addrCells));
+					rootNode.addProperty(new DTProperty("#size-cells",(long)sizeCells));
+					if(aliasNode!=null) {
+					    rootNode.addChild(aliasNode);
 					}
+					rootNode.addChild(cpuNode);
+					rootNode.addChild(memNode);
+					sopcNode.addProperty(new DTProperty("device_type", "soc"));
+				} break;
+				case OVERLAY: {
+					DTNode fragmentNode = new DTNode("fragment@0");
+					fragmentNode.addProperty(new DTProperty("target", new DTPropPHandleVal(bi.getOverlayTarget())));
+					sopcNode = new DTNode("__overlay__");
+					fragmentNode.addChild(sopcNode);
+					rootNode.addChild(fragmentNode);
+				} break;
+				case PCI: {
+					sopcNode = rootNode;
+					DTProperty rangeProp = new DTProperty("ranges");
+					rangeProp.addHexValues(new long[] {
+							0x00000000,
+							0x02000000, 0, 0x90000000,
+							0x10000000,
+					});
+					sopcNode.addProperty(rangeProp);
 				}
-				vAliases = bi.getAliasRefs();
-				if (vAliases.size() > 0) {
-					if(aliasNode==null) {
-						aliasNode = new DTNode("aliases");
-					}
-					for (Parameter p : vAliases) {
-						BasicComponent slave = sys.getComponentByName(p.getValue());
-						if(slave!=null) {
-							Vector<Connection> vConn = sys.getConnectionPath(povComponent, slave,SystemDataType.MEMORY_MAPPED);
-							String path="/" + sopcNode.getName();
-							for(Connection c : vConn) {
-								path += "/" + c.getSlaveModule().getScd().getGroup() + "@" + DTHelper.longArrToHexString(c.getConnValue());
-							}
-							if(path.length()>0) {
-								aliasNode.addProperty(new DTProperty(p.getName(),path));								
-							} else {
-								Logger.logln(this, "Failed to find component '" + p.getValue() +"' path for alias: " + p.getName(), LogLevel.WARNING);
-							}
-						} else {
-							Logger.logln(this, "Failed to find component '" + p.getValue() +"' for alias: " + p.getName(), LogLevel.WARNING);
-						}
-					}
-				}
-				
-				if(aliasNode!=null) {
-				    rootNode.addChild(aliasNode);
-				}
-				rootNode.addChild(cpuNode);
-				rootNode.addChild(memNode);
-				sopcNode.addProperty(new DTProperty("device_type", "soc"));
-			} else {
-				sopcNode = rootNode;
-				chosenNode = null;
 			}
 			sopcNode = getSlavesFor(bi, povComponent, sopcNode);
-			sopcNode.addProperty(new DTProperty("ranges"));
 			sopcNode.addProperty(new DTProperty("#address-cells",(long)addrCells));
 			sopcNode.addProperty(new DTProperty("#size-cells",(long)sizeCells));
 			Vector<String> vCompat = new Vector<String>();
@@ -132,13 +120,21 @@ public abstract class DTGenerator extends AbstractSopcGenerator {
 			vCompat.add("simple-bus");
 			sopcNode.addProperty(new DTProperty("compatible", vCompat.toArray(new String[]{})));
 			sopcNode.addProperty(new DTProperty("bus-frequency", povComponent.getClockRate()));
+			rootNode.addChild(clocksNode);
 			if(bi.getPovType().equals(PovType.CPU))
 			{
-				if(clocksNode!=null) {
-					rootNode.addChild(clocksNode);
-				}
 				rootNode.addChild(sopcNode);
-				rootNode.addChild(chosenNode);
+			}
+			rootNode.addChild(chosenNode);
+			if(doAddSymbolsNode) {
+				HashMap<String,String> symbolMap = getSymbols(bi, rootNode, "");
+				if(!symbolMap.isEmpty()) {
+					DTNode symbolsNode = new DTNode("__symbols__");
+					for(String key : symbolMap.keySet()) {
+						symbolsNode.addProperty(new DTProperty(key, symbolMap.get(key)));
+					}
+					rootNode.addChild(symbolsNode);
+				}
 			}
 		}
 		doDTAppend(rootNode,bi);
@@ -251,6 +247,41 @@ public abstract class DTGenerator extends AbstractSopcGenerator {
 		}
 	}
 
+	DTNode getAliasNode(BoardInfo bi, BasicComponent povComp, String basePath)
+	{
+		DTNode aliasNode = null;
+		Vector<Parameter> vAliases = bi.getAliases();
+		if (vAliases.size() > 0) {
+			aliasNode = new DTNode("aliases");
+			for (Parameter p : vAliases) {
+				aliasNode.addProperty(new DTProperty(p.getName(),p.getValue()));
+			}
+		}
+		vAliases = bi.getAliasRefs();
+		if (vAliases.size() > 0) {
+			if(aliasNode==null) {
+				aliasNode = new DTNode("aliases");
+			}
+			for (Parameter p : vAliases) {
+				BasicComponent slave = sys.getComponentByName(p.getValue());
+				if(slave!=null) {
+					Vector<Connection> vConn = sys.getConnectionPath(povComp, slave,SystemDataType.MEMORY_MAPPED);
+					String path=basePath;
+					for(Connection c : vConn) {
+						path += "/" + c.getSlaveModule().getScd().getGroup() + "@" + DTHelper.longArrToHexString(c.getConnValue());
+					}
+					if(path.length()>0) {
+						aliasNode.addProperty(new DTProperty(p.getName(),path));
+					} else {
+						Logger.logln(this, "Failed to find component '" + p.getValue() +"' path for alias: " + p.getName(), LogLevel.WARNING);
+					}
+				} else {
+					Logger.logln(this, "Failed to find component '" + p.getValue() +"' for alias: " + p.getName(), LogLevel.WARNING);
+				}
+			}
+		}
+		return aliasNode;
+	}
 	DTNode getChosenNode(BoardInfo bi)
 	{
 		DTNode chosenNode = new DTNode("chosen");
@@ -395,7 +426,7 @@ public abstract class DTGenerator extends AbstractSopcGenerator {
 			return memNode;
 		}
 	}
-	
+
 	DTNode getSlavesFor(BoardInfo bi, BasicComponent masterComp, DTNode masterNode)
 	{
 		if(masterComp!=null)
@@ -424,6 +455,19 @@ public abstract class DTGenerator extends AbstractSopcGenerator {
 		}
 		return masterNode;
 	}
+	HashMap<String,String> getSymbols(BoardInfo bi, DTNode rootNode, String basePath)
+	{
+		HashMap<String,String> symbolMap = new HashMap<String, String>();
+		for(DTNode child : rootNode.getChildren()) {
+			if(child.getLabel()!=null) {
+				symbolMap.put(child.getLabel(), basePath + "/" + child.getName());
+			}
+			if(!child.getChildren().isEmpty()) {
+				symbolMap.putAll(getSymbols(bi, child, basePath + "/" + child.getName()));
+			}
+		}
+		return symbolMap;
+	}
 	protected static void sortSlaves(Vector<Connection> vConn, final SortType sort) {
 		if(!sort.equals(SortType.NONE)) {
 			Collections.sort(vConn, new Comparator<Connection>() {
diff --git a/sopc2dts/generators/DTSGenerator2.java b/sopc2dts/generators/DTSGenerator2.java
index aa67ff1..ca53822 100644
--- a/sopc2dts/generators/DTSGenerator2.java
+++ b/sopc2dts/generators/DTSGenerator2.java
@@ -1,7 +1,7 @@
 /*
 sopc2dts - Devicetree generation for Altera systems
 
-Copyright (C) 2012 Walter Goossens <[email protected]>
+Copyright (C) 2012 - 2015 Walter Goossens <[email protected]>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
@@ -21,6 +21,7 @@ package sopc2dts.generators;
 
 import sopc2dts.lib.AvalonSystem;
 import sopc2dts.lib.BoardInfo;
+import sopc2dts.lib.BoardInfo.PovType;
 import sopc2dts.lib.devicetree.DTNode;
 
 public class DTSGenerator2 extends DTGenerator {
@@ -33,6 +34,9 @@ public class DTSGenerator2 extends DTGenerator {
 	public String getTextOutput(BoardInfo bi) {
 		String res = getSmallCopyRightNotice("devicetree", bi.isIncludeTime())
 					+ "/dts-v1/;\n";
+		if(bi.getPovType() == PovType.OVERLAY) {
+			res += "/plugin/;\n";
+		}
 		DTNode rootNode = getDTOutput(bi);
 		res += rootNode.toString();
 		return res;
diff --git a/sopc2dts/lib/BoardInfo.java b/sopc2dts/lib/BoardInfo.java
index 1c5093c..9e054f6 100644
--- a/sopc2dts/lib/BoardInfo.java
+++ b/sopc2dts/lib/BoardInfo.java
@@ -47,7 +47,7 @@ import sopc2dts.lib.components.BasicComponent;
 import sopc2dts.lib.components.base.FlashPartition;
 
 public class BoardInfo implements ContentHandler {
-	public enum PovType { CPU, PCI };
+	public enum PovType { CPU, PCI, OVERLAY };
 	public enum SortType { NONE, ADDRESS, NAME, LABEL };
 	public enum RangesStyle { NONE, FOR_BRIDGE, FOR_EACH_CHILD };
 	public enum AltrStyle { AUTO, FORCE_UPPER, FORCE_LOWER };
@@ -71,6 +71,7 @@ public class BoardInfo implements ContentHandler {
 	String bootArgs;
 	BoardInfoComponent currBic;
 	private AltrStyle altrStyle = AltrStyle.AUTO;
+	private String overlayTarget = "";
 	private String pov = "";
 	private PovType povType = PovType.CPU;
 	private RangesStyle rangesStyle = RangesStyle.FOR_EACH_CHILD;
@@ -352,6 +353,8 @@ public class BoardInfo implements ContentHandler {
 				povTypeName.equalsIgnoreCase("pcie"))
 		{
 			setPovType(PovType.PCI);
+		} else if(povTypeName.equalsIgnoreCase("overlay")) {
+			setPovType(PovType.OVERLAY);
 		}
 	}
 	public void setRangesStyle(RangesStyle rangesStyle) {
@@ -382,6 +385,9 @@ public class BoardInfo implements ContentHandler {
 			setSortType(SortType.NONE);
 		}
 	}
+	public String getOverlayTarget() {
+		return overlayTarget;
+	}
 	public void setPartitionsForchip(String instanceName, Vector<FlashPartition> vParts) {
 		mFlashPartitions.put(instanceName, vParts);
 	}
@@ -541,4 +547,7 @@ public class BoardInfo implements ContentHandler {
 	public void setIncludeTime(boolean includeTime) {
 		this.includeTime = includeTime;
 	}
+	public void setOverlayTarget(String overlayTarget) {
+		this.overlayTarget = overlayTarget;
+	}
 }
_______________________________________________
Rfi mailing list
[email protected]
http://lists.rocketboards.org/cgi-bin/mailman/listinfo/rfi

Reply via email to