From: "Grant Likely" <grant.likely@secretlab.ca>
To: "John Bonesio" <john.bonesio@xilinx.com>,
"Rick Moleres" <rick.moleres@xilinx.com>,
"Peter Ryser" <peter.ryser@xilinx.com>,
"linuxppc-embedded list" <linuxppc-embedded@ozlabs.org>
Subject: Virtex device tree generator proof of concept
Date: Wed, 29 Nov 2006 12:16:24 -0700 [thread overview]
Message-ID: <528646bc0611291116p15c87ff6q3a6e0b266c5a8531@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 548 bytes --]
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.
grant.likely@secretlab.ca
(403) 399-0195
[-- Attachment #2: gen_mhs_devtree.py --]
[-- Type: text/x-python, Size: 7408 bytes --]
#!/usr/bin/env python
#
# Author: Grant Likely <grant.likely@secretlab.ca>
#
# 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)
next reply other threads:[~2006-11-29 19:16 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-11-29 19:16 Grant Likely [this message]
[not found] <977C41F842E66D4CB2E41332313B615002F76196@XSJ-EXCHVS1.xlnx.xilinx.com>
2006-12-06 23:14 ` Virtex device tree generator proof of concept Grant Likely
2006-12-06 23:47 ` David Gibson
-- strict thread matches above, loose matches on Subject: below --
2006-12-07 0:19 Stephen Neuendorffer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=528646bc0611291116p15c87ff6q3a6e0b266c5a8531@mail.gmail.com \
--to=grant.likely@secretlab.ca \
--cc=john.bonesio@xilinx.com \
--cc=linuxppc-embedded@ozlabs.org \
--cc=peter.ryser@xilinx.com \
--cc=rick.moleres@xilinx.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).