odroid: remove CONFIG_DM_I2C_COMPAT config
[platform/kernel/u-boot.git] / tools / dtoc / fdt_normal.py
index ca5335b..cce5c06 100644 (file)
@@ -20,6 +20,11 @@ import libfdt
 # This implementation uses a libfdt Python library to access the device tree,
 # so it is fairly efficient.
 
+def CheckErr(errnum, msg):
+    if errnum:
+        raise ValueError('Error %d: %s: %s' %
+            (errnum, libfdt.fdt_strerror(errnum), msg))
+
 class Prop(PropBase):
     """A device tree property
 
@@ -33,52 +38,18 @@ class Prop(PropBase):
         PropBase.__init__(self, node, offset, name)
         self.bytes = bytes
         if not bytes:
-            self.type = fdt_util.TYPE_BOOL
+            self.type = fdt.TYPE_BOOL
             self.value = True
             return
-        self.type, self.value = fdt_util.BytesToValue(bytes)
+        self.type, self.value = self.BytesToValue(bytes)
 
-    def GetPhandle(self):
-        """Get a (single) phandle value from a property
+    def GetOffset(self):
+        """Get the offset of a property
 
-        Gets the phandle valuie from a property and returns it as an integer
-        """
-        return fdt_util.fdt32_to_cpu(self.value[:4])
-
-    def Widen(self, newprop):
-        """Figure out which property type is more general
-
-        Given a current property and a new property, this function returns the
-        one that is less specific as to type. The less specific property will
-        be ble to represent the data in the more specific property. This is
-        used for things like:
-
-            node1 {
-                compatible = "fred";
-                value = <1>;
-            };
-            node1 {
-                compatible = "fred";
-                value = <1 2>;
-            };
-
-        He we want to use an int array for 'value'. The first property
-        suggests that a single int is enough, but the second one shows that
-        it is not. Calling this function with these two propertes would
-        update the current property to be like the second, since it is less
-        specific.
+        Returns:
+            The offset of the property (struct fdt_property) within the file
         """
-        if newprop.type < self.type:
-            self.type = newprop.type
-
-        if type(newprop.value) == list and type(self.value) != list:
-            self.value = [self.value]
-
-        if type(self.value) == list and len(newprop.value) > len(self.value):
-            val = fdt_util.GetEmpty(self.type)
-            while len(self.value) < len(newprop.value):
-                self.value.append(val)
-
+        return self._node._fdt.GetStructOffset(self._offset)
 
 class Node(NodeBase):
     """A device tree node
@@ -95,15 +66,24 @@ class Node(NodeBase):
     def __init__(self, fdt, offset, name, path):
         NodeBase.__init__(self, fdt, offset, name, path)
 
+    def Offset(self):
+        """Returns the offset of a node, after checking the cache
+
+        This should be used instead of self._offset directly, to ensure that
+        the cache does not contain invalid offsets.
+        """
+        self._fdt.CheckCache()
+        return self._offset
+
     def Scan(self):
         """Scan a node's properties and subnodes
 
         This fills in the props and subnodes properties, recursively
         searching into subnodes so that the entire tree is built.
         """
-        self.props = self._fdt.GetProps(self.path)
+        self.props = self._fdt.GetProps(self)
 
-        offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset)
+        offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self.Offset())
         while offset >= 0:
             sep = '' if self.path[-1] == '/' else '/'
             name = libfdt.Name(self._fdt.GetFdt(), offset)
@@ -114,6 +94,34 @@ class Node(NodeBase):
             node.Scan()
             offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
 
+    def Refresh(self, my_offset):
+        """Fix up the _offset for each node, recursively
+
+        Note: This does not take account of property offsets - these will not
+        be updated.
+        """
+        if self._offset != my_offset:
+            #print '%s: %d -> %d\n' % (self.path, self._offset, my_offset)
+            self._offset = my_offset
+        offset = libfdt.fdt_first_subnode(self._fdt.GetFdt(), self._offset)
+        for subnode in self.subnodes:
+            subnode.Refresh(offset)
+            offset = libfdt.fdt_next_subnode(self._fdt.GetFdt(), offset)
+
+    def DeleteProp(self, prop_name):
+        """Delete a property of a node
+
+        The property is deleted and the offset cache is invalidated.
+
+        Args:
+            prop_name: Name of the property to delete
+        Raises:
+            ValueError if the property does not exist
+        """
+        CheckErr(libfdt.fdt_delprop(self._fdt.GetFdt(), self.Offset(), prop_name),
+                 "Node '%s': delete property: '%s'" % (self.path, prop_name))
+        del self.props[prop_name]
+        self._fdt.Invalidate()
 
 class FdtNormal(Fdt):
     """Provides simple access to a flat device tree blob using libfdt.
@@ -125,8 +133,12 @@ class FdtNormal(Fdt):
     """
     def __init__(self, fname):
         Fdt.__init__(self, fname)
-        with open(self._fname) as fd:
-            self._fdt = fd.read()
+        self._cached_offsets = False
+        if self._fname:
+            self._fname = fdt_util.EnsureCompiled(self._fname)
+
+            with open(self._fname) as fd:
+                self._fdt = bytearray(fd.read())
 
     def GetFdt(self):
         """Get the contents of the FDT
@@ -136,21 +148,16 @@ class FdtNormal(Fdt):
         """
         return self._fdt
 
-    def Scan(self):
-        """Scan a device tree, building up a tree of Node objects
+    def Flush(self):
+        """Flush device tree changes back to the file"""
+        with open(self._fname, 'wb') as fd:
+            fd.write(self._fdt)
 
-        This fills in the self._root property
-        """
-        self._root = Node(self, 0, '/', '/')
-        self._root.Scan()
-
-    def GetRoot(self):
-        """Get the root Node of the device tree
-
-        Returns:
-            The root Node object
-        """
-        return self._root
+    def Pack(self):
+        """Pack the device tree down to its minimum size"""
+        CheckErr(libfdt.fdt_pack(self._fdt), 'pack')
+        fdt_len = libfdt.fdt_totalsize(self._fdt)
+        del self._fdt[fdt_len:]
 
     def GetProps(self, node):
         """Get all properties from a node.
@@ -165,11 +172,8 @@ class FdtNormal(Fdt):
         Raises:
             ValueError: if the node does not exist.
         """
-        offset = libfdt.fdt_path_offset(self._fdt, node)
-        if offset < 0:
-            libfdt.Raise(offset)
         props_dict = {}
-        poffset = libfdt.fdt_first_property_offset(self._fdt, offset)
+        poffset = libfdt.fdt_first_property_offset(self._fdt, node._offset)
         while poffset >= 0:
             dprop, plen = libfdt.fdt_get_property_by_offset(self._fdt, poffset)
             prop = Prop(node, poffset, libfdt.String(self._fdt, dprop.nameoff),
@@ -179,6 +183,31 @@ class FdtNormal(Fdt):
             poffset = libfdt.fdt_next_property_offset(self._fdt, poffset)
         return props_dict
 
+    def Invalidate(self):
+        """Mark our offset cache as invalid"""
+        self._cached_offsets = False
+
+    def CheckCache(self):
+        """Refresh the offset cache if needed"""
+        if self._cached_offsets:
+            return
+        self.Refresh()
+        self._cached_offsets = True
+
+    def Refresh(self):
+        """Refresh the offset cache"""
+        self._root.Refresh(0)
+
+    def GetStructOffset(self, offset):
+        """Get the file offset of a given struct offset
+
+        Args:
+            offset: Offset within the 'struct' region of the device tree
+        Returns:
+            Position of @offset within the device tree binary
+        """
+        return libfdt.fdt_off_dt_struct(self._fdt) + offset
+
     @classmethod
     def Node(self, fdt, offset, name, path):
         """Create a new node