ppx4xx support in arch/powerpc is still off in the distance, but here is a proof of concept device tree generator for Xilinx virtex designs. You pass the tool a .mhs file, and it spits out a .dts file. Generated dts output is accepted by the dtc parser. I've tested against the ml403 reference designs and a custom design.
This code can also be viewed at: http://git.secretlab.ca/cgi-bin/gitweb.cgi?p=gen_mhs_devtree.git;a=summary Cheers, g. -- Grant Likely, B.Sc. P.Eng. Secret Lab Technologies Ltd. [EMAIL PROTECTED] (403) 399-0195
#!/usr/bin/env python # # Author: Grant Likely <[EMAIL PROTECTED]> # # Copyright (C) Secret Lab Technologies Ltd. 2006. All rights reserved. # # This source code is licensed under version 2 of the GNU General Public # License, from string import upper, strip from pprint import pprint from sys import argv class mhs_file(object): def __init__(self, filename=None): self.clear() if filename: self.parsefile(filename) def clear(self): self.blocks = [] self.buses = {} self.ports = {} def _add_to_port(self, port, block): port = port.upper() if port not in self.ports: self.ports[port] = [] self.ports[port].append(block) def _add_to_bus(self, bus, block): bus = bus.upper() if bus not in self.buses: self.buses[bus] = [] self.buses[bus].append(block) def _add_property(self, type, key, value): type = type.upper() if type not in self._curr_block: self._curr_block[type] = {} self._curr_block[type][key] = value if type == 'PARAMETER' and key == 'INSTANCE': self._curr_block['name'] = value if type == 'PORT': self._add_to_port(value, self._curr_block) if type == 'BUS_INTERFACE': self._add_to_bus(value, self._curr_block) def parse(self, file): state = "idle" for l in file: toks = l.split('#')[0].strip().split(None, 3) if not toks: continue if state == 'idle': if toks[0].upper() == 'BEGIN': state = 'block' self._curr_block = {'type': toks[1]} elif state == 'block': if toks[0].upper() == 'END': state = 'idle' self.blocks.append(self._curr_block) del self._curr_block continue self._add_property(toks[0], toks[1], toks[3]) def parsefile(self, filename): f = open(filename) self.parse(f) f.close() _cpu_types = ('ppc405_virtex4', 'ppc405_virtex2pro') def find_root_cpu(self, name=None): for block in self.blocks: if block['type'] not in self._cpu_types: continue if name and name != block['name']: continue return block return None def find_root_bus(self): root_cpu = self.find_root_cpu() dplb_name = root_cpu['BUS_INTERFACE']['DPLB'] iplb_name = root_cpu['BUS_INTERFACE']['IPLB'] if (dplb_name != iplb_name): print "seperate instr and data busses, " + \ "I don't know what to do with this" return None dplb_data = self.find_instance(dplb_name) if not dplb_data: print 'Could not find bus \'%s\''%dplb_name return dplb_data def find_instance(self, name): for block in self.blocks: if name == block['name']: return block return None def find_types(self, type): bl = [] for block in self.blocks: if type == block['type']: bl.append(block) return bl def find_port(self, port): bl = [] for block in self.blocks: if 'PORT' not in block: continue for p in block['PORT']: if block['PORT'][p] == port: bl.append(block) break return bl def find_bus_attachments(self, bus): blocks = [] for block in self.blocks: if 'BUS_INTERFACE' not in block: continue for bk in block['BUS_INTERFACE'].keys(): if block['BUS_INTERFACE'][bk] == bus: blocks.append(block) break return blocks def of_add_cpu(of_node, mhs, cpu_data): cpu_node = {'device_type': 'cpu', 'reg': 0, 'd-cache-line-size': 0x20, 'd-cache-size': 0x4000, 'i-cache-line-size': 0x20, 'i-cache-size': 0x4000, '32-bit': None} #cpu_node['.mhs-private-data'] = cpu_data cpu_name = cpu_data['name'] + ',405' of_node[cpu_name + '@%s'%of_node['#cpus']] = cpu_node of_node['#cpus'] = of_node['#cpus'] + 1 def of_add_device(of_node, mhs, dev_data): if 'of_node' in dev_data.keys(): return dev_node = {'device_type': dev_data['type'] } params = dev_data['PARAMETER'] # Construct compatible property compat = [] compat.append(dev_data['type'] + '_' + params['HW_VER']) compat.append(dev_data['type']) if dev_data['type'] in ('opb_uart16550', 'plb_opb_uart16550'): compat.append('ns16550') dev_node['compatible'] = "\\0".join(compat) # Get address ranges for key in params.keys(): if key.upper().endswith('_BASEADDR'): basekey = key if key.upper().endswith('_HIGHADDR'): highkey = key if not basekey or not highkey: pprint(dev_data) return start = int(params[basekey], 16) end = int(params[highkey], 16) if 'ranges' in of_node.keys(): start = start - of_node['ranges'][1] + of_node['ranges'][0] # Hack to only use sane ranges if start > 0 and end > 0 and start < 0x100000000: dev_node['reg'] = (start, end - start + 1) # Add the node if start < 0 or start >= 0x100000000: start = 0 # *HACK* Some node names are too long; don't use the address for now... #of_node[dev_data['name'] + '@%x'%start] = dev_node of_node[dev_data['name']] = dev_node dev_data['of_node'] = dev_node def of_add_opb_bridge(of_node, mhs, bridge_data): if 'of_node' in bridge_data.keys(): return bridge_node = {} # Get translation address ranges params = bridge_data['PARAMETER'] for key in params.keys(): if key.upper().endswith('_BASEADDR'): basekey = key if key.upper().endswith('_HIGHADDR'): highkey = key if not basekey or not highkey: pprint(dev_data) return start = int(params[basekey], 0) end = int(params[highkey], 0) bridge_node['ranges'] = (0, start, end - start + 1) bus_name = bridge_data['BUS_INTERFACE']['MOPB'] bus_data = mhs.find_instance(bus_name) of_node[bridge_data['name'] + '@%x'%start] = bridge_node bridge_data['of_node'] = bridge_node of_add_bus(bridge_node, mhs, bus_data) def of_add_bus(of_node, mhs, bus_data): bus_name = bus_data['name'] for block in mhs.find_bus_attachments(bus_name): if block['type'] in ('ppc405_virtex4', 'ppc405_virtex2pro'): of_add_cpu(of_node['cpus'], mhs, block) elif block['type'] in ('plb2opb_bridge',): of_add_opb_bridge(of_node, mhs, block) else: of_add_device(of_node, mhs, block) def of_link_interrupts(of_node, mhs): phandle = 0x100 for block in mhs.find_types('opb_intc'): phandle = phandle + 1 if 'of_node' not in block: continue block['of_node']['linux,phandle'] = phandle irqnum = 0 for irq_line in block['PORT']['Intr'].split('&'): devices = mhs.find_port(irq_line.strip()) for b in devices: if 'of_node' not in b: continue b['of_node']['interrupt-parent'] = phandle b['of_node']['interrupts'] = (irqnum, 0) irqnum = irqnum + 1 def of_build_tree (mhs, mhs_root_bus): cpus_node = {'#cpus': (0), '#address-cells': (1), '#size-cells': (0)} of_tree = {'#address-cells': (1), '#size-cells': (1), 'cpus': cpus_node} of_add_bus(of_tree, mhs, mhs_root_bus) of_link_interrupts(of_tree, mhs) return of_tree def of_print_tree (of_node, name = '/', indent=0): prefix = '\t'*indent print prefix + name, '{' # Print properties first for key in of_node.keys(): val = of_node[key] if type(val) == str: print prefix + '\t' + key, '= "'+val+'" ;' if type(val) == int: print prefix + '\t' + key, '=', '<%x>;'%val if type(val) == list or type(val) == tuple: print prefix + '\t' + key, '=', '<', for i in val: print '%x'%i, print '>;' # print sub nodes second for key in of_node.keys(): val = of_node[key] if type(val) == dict: of_print_tree(val, key, indent+1) print prefix + '} ;' mhs = mhs_file(argv[1]) root = mhs.find_root_bus() of_tree = of_build_tree(mhs, root) #pprint(of_tree) of_print_tree(of_tree)
_______________________________________________ Linuxppc-embedded mailing list Linuxppc-embedded@ozlabs.org https://ozlabs.org/mailman/listinfo/linuxppc-embedded