linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* 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
* 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

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 --
     [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
2006-12-07  0:19 Stephen Neuendorffer
  -- strict thread matches above, loose matches on Subject: below --
2006-11-29 19:16 Grant Likely

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).