* Virtex device tree generator proof of concept
@ 2006-11-29 19:16 Grant Likely
0 siblings, 0 replies; 4+ messages in thread
From: Grant Likely @ 2006-11-29 19:16 UTC (permalink / raw)
To: John Bonesio, Rick Moleres, Peter Ryser, linuxppc-embedded list
[-- 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)
^ permalink raw reply [flat|nested] 4+ messages in thread
[parent not found: <977C41F842E66D4CB2E41332313B615002F76196@XSJ-EXCHVS1.xlnx.xilinx.com>]
* Re: Virtex device tree generator proof of concept
[not found] <977C41F842E66D4CB2E41332313B615002F76196@XSJ-EXCHVS1.xlnx.xilinx.com>
@ 2006-12-06 23:14 ` Grant Likely
2006-12-06 23:47 ` David Gibson
0 siblings, 1 reply; 4+ messages in thread
From: Grant Likely @ 2006-12-06 23:14 UTC (permalink / raw)
To: Stephen Neuendorffer, linuxppc-dev list
On 12/6/06, Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> wrote:
>
> Hi Grant,
>
> This looks really cool... I've hacked around in it a bit to generate
> device trees that go more completely through dtc. (I'd be happy
> to push these modifications back to you, if you're interested...)
Yes please, send me your patches.
>
> I'm curious if you've heard of anyone using device trees other than
> at boot time: for instance, using an incomplete device tree blob to
> represent components discovered at runtime? It looks like it should
> be possible to rip out alot of the code from kernel/powerpc/prom.c in
> recent kernels to parse incomplete device trees, too... Any thoughts?
Possible, but there are probably better ways do deal with those; like
just allocating and registering a platform device; or adding nodes to
the existing tree. If you're able to probe a device, then do you need
to describe it with a device tree fragment?
What scenario are you thinking about?
Cheers,
g.
--
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Virtex device tree generator proof of concept
2006-12-06 23:14 ` Grant Likely
@ 2006-12-06 23:47 ` David Gibson
0 siblings, 0 replies; 4+ messages in thread
From: David Gibson @ 2006-12-06 23:47 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev list, Stephen Neuendorffer
Hmm.. I seem to have missed the beginning of this thread, somehow.
On Wed, Dec 06, 2006 at 04:14:33PM -0700, Grant Likely wrote:
> On 12/6/06, Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> wrote:
> >
> > Hi Grant,
> >
> > This looks really cool... I've hacked around in it a bit to generate
> > device trees that go more completely through dtc. (I'd be happy
> > to push these modifications back to you, if you're interested...)
>
> Yes please, send me your patches.
>
> >
> > I'm curious if you've heard of anyone using device trees other than
> > at boot time: for instance, using an incomplete device tree blob to
> > represent components discovered at runtime? It looks like it should
> > be possible to rip out alot of the code from kernel/powerpc/prom.c in
> > recent kernels to parse incomplete device trees, too... Any thoughts?
That reminds me: I was definitely thinking about implementing a
"graft" function in libfdt for merging a tree from one blob into
another.
--
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
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: Virtex device tree generator proof of concept
@ 2006-12-07 0:19 Stephen Neuendorffer
0 siblings, 0 replies; 4+ messages in thread
From: Stephen Neuendorffer @ 2006-12-07 0:19 UTC (permalink / raw)
To: Grant Likely, linuxppc-dev list
> Yes please, send me your patches.
done.
> > I'm curious if you've heard of anyone using device trees=20
> other than at=20
> > boot time: for instance, using an incomplete device tree blob to=20
> > represent components discovered at runtime? It looks like=20
> it should=20
> > be possible to rip out alot of the code from=20
> kernel/powerpc/prom.c in=20
> > recent kernels to parse incomplete device trees, too... =20
> Any thoughts?
>=20
> Possible, but there are probably better ways do deal with=20
> those; like just allocating and registering a platform=20
> device; or adding nodes to the existing tree. If you're able=20
> to probe a device, then do you need to describe it with a=20
> device tree fragment?
>=20
> What scenario are you thinking about?
In an FPGA, even platform-bus devices don't necessarily exist at
processor boot time, and
they might change during the life of a system.
As you suggest, I plan to simply add the correct devices to the platform
bus at the correct time,
and I'm also trying to abstract the code that creates the platform
devices (which probably
should be part of a basic kernel device) from the information about
which devices actually exist.
There are probably other ways of doing this (for instance, automatically
generating the code for
a kernel module which adds devices to the platform bus), but a device
tree fragment=20
doesn't seem like too bad a way of doing it.
Steve
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2006-12-07 1:39 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-29 19:16 Virtex device tree generator proof of concept Grant Likely
[not found] <977C41F842E66D4CB2E41332313B615002F76196@XSJ-EXCHVS1.xlnx.xilinx.com>
2006-12-06 23:14 ` 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
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).