Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Dec 2007 12:50:20 -0700 (MST)
From:      "M. Warner Losh" <imp@bsdimp.com>
To:        marcelm@juniper.net
Cc:        embedded@freebsd.org
Subject:   Re: ocpbus(4)
Message-ID:  <20071228.125020.-1962668065.imp@bsdimp.com>
In-Reply-To: <B5E9CBD1-0F16-422C-9AFA-CC33D988630C@juniper.net>
References:  <B56F8F3C-7872-47B9-8154-1C08F5BEEA3D@juniper.net> <20071228.114559.-311937481.imp@bsdimp.com> <B5E9CBD1-0F16-422C-9AFA-CC33D988630C@juniper.net>

next in thread | previous in thread | raw e-mail | index | archive | help
In message: <B5E9CBD1-0F16-422C-9AFA-CC33D988630C@juniper.net>
            Marcel Moolenaar <marcelm@juniper.net> writes:
: 
: On Dec 28, 2007, at 10:45 AM, M. Warner Losh wrote:
: 
: > : The main part of the handshake seems to be the means
: > : for a driver to probe/match the hardware. In our
: > : implementation of ocpbus(4), we use an IVAR for the
: > : device type, as in:
: > :
: > :          parent = device_get_parent(dev);
: > :          error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE,
: > : &devtype);
: > :          if (error)
: > :                  return (error);
: > :          if (devtype != OCPBUS_DEVTYPE_PCIB)
: > :                  return (ENXIO);
: > :
: > : Since we only have 1 PCI-host controller driver to
: > : worry about, this is perfectly fine. However, if we
: > : want to generalize, then we probably need to extend
: > : the handshake to support different classes. Take
: > : for example an USB host controller. With EHCI, there's
: > : always at least 1 companion host controller (either
: > : OHCI or UHCI). Thus, checking if OCPBUS_DEVTYPE equals
: > : OCPBUS_DEVTYPE_USB (or something along those lines) is
: > : not enough. We need to know if it's an EHCI, OHCI or
: > : UHCI host controller.
: >
: > This is why I don't think it will work.  The child device shouldn't be
: > checking to see if it is the right type or not.
: 
: But that's how PCI works: the hardware has a vendor
: and device Id and the driver checks for combinations
: that it knows it can work with. Translated into IVARs,
: that means that there's a device tree or device list
: that mentions the existence of some DEVTYPE and DEVCLASS
: which the bus driver makes available through the IVARs
: and the driver checks if it's something it knows it can
: handle and attaches to the device of it does.

Right, but in PCI land the drivers know what devices they support and
the bus has no knowledge of that.  In PCI land each device has
something you can query to find out what it is.  In SoC land, such
luxaries are the exception rather than the rule.  The driver for a
specific SoC would know what hardware is there.

: > : Q1: Do people think it's worthwhile to pursue a generic
: > :      ocpbus(4) definition?
: >
: > Generally, yes.  In fact, I've done a bunch of things with what I've
: > called obio (On Board I/O) that does similar things, but relies
: > entirely on hints to do the job.  Since that's how we do things
: > elsewhere, this seems like a reasonable approach.  If we move to doing
: > things differently, then we can talk about that.
: 
: Hints can be used to implement the device tree or
: device list, but is rather limited. I'd like us to
: implement something richer in the future. For that
: reason I don't want to expose hints to the driver,
: but rather abstract the implementation of the device
: tree or the device list behind IVARs. That makes it
: possible to implement the "bus" in many different
: ways without having to change the device drivers that
: attach to the bus.

But hints aren't exported to the drivers now.  Having the ivars like
you suggest is more invasive into the drivers.  We shouldn't be
designing for future, possible ideas, but rather working in the
current framework.  If you'd like to design a future framework and
implement that then implement this, that would be one thing.

Using the subclassing stuff I talked about, one can actually implement
driver code that is fairly generic.  However, most of the time, the
generic devices are extremely limited.  Usually just a 16550-like
device mapped into the hardware in what usually is a unique way (4
byte aligned registers here, packed registers there, 8 byte aligned
registers over there).

: > I implemented obio as a set of routines rather than as a bus itself,
: > since doing the bus generically is going to be nearly impossible.
: > There's too many fussy bits of logic for this SoC or that SoC that
: > need to be in code.
: 
: An abstract bus is just a means for devices to attach
: to. There's a bus driver component behind it, but that
: can be nexus(4) itself. The main purpose is to allow a
: single bus attachment to be used in various and many
: ways, so as to limit the flurry of single-use and one-off
: bus attachments. A single generic "bus" that does not
: imply anything about the underlying hardware or means
: of enumeration is the most flexible.

That sounds like we should implement bio as a baseclass for other
busses to derive from.  That would allow a more generic way for the
simple devices as well as a more complicated way for the more
complicated devices (like ohci implementations, GPIO pings for this or
that, etc).

: > : Q2: Is there a better handshake possible than IVARs?
: >
: > Have the bus say "I have this or that on it" rather than having the
: > drivers themselves try to match.  That way lies madness, I think,
: > since you'll soon wind up with lots of platform specific code
: > infecting the generic device drivers.
: 
: Can you elaborate. I don't quite follow you.

I think that any enumeration of devtype/devclass will likely result in
a situation that's either too generic to be useful, or is so specific
that one might as well just encode the device <-> driver names and be
done with it and not introduce an extra level of indirection.

: > : Q3: For probing, would DEVTYPE and DEVCLASS suffice or
: > :      do we need something more or something else?
: >
: > Is this supposed to be a 'generic' replacement for the product/vendor
: > stuff ala pci or something else?  I'm not sure that we can uniquely do
: > this in a generic enough way.
: 
: Yes, it's akin to the vendor/product pair that PCI uses.
: 
: As for being generic: I don't think we can account for
: every possible hardware upfront. What I think will work
: is something that can be extended. For example, for
: async serial hardware, DEVTYPE equals UART. For the
: various chips, DEVCLASS can be set accordingly. So, for
: standard PC hardware DEVCLASS equals NS8250. Since
: DEVTYPE and DEVCLASS are just numbers, we can add as
: many types and classes as we need. If we need to support
: a new network interface, we add it to DEVCLASS (DEVTYPE
: being NETIF or something).

I don't think there's much value in DEVTYPE in that case.  UART is a
useless designation if you don't know what kind of uart, and if you
are told it is a NS8250, then you know you support it without having
to look at DEVTYPE.  NETIF is similar.  And these busses usually have
lots of other, auxiliary devices hanging off of them.  SPI
controllers, MMC/SD controllers, generic (in the hardware signal
sense) synchronous serial controllers, etc.  There's usually very
little in common between an ATMEL SPI controller and one from Cirrus
Logic.

The DEVTYPE typically would be unused.  And we'd have to have a
seprate DEVCLASS for every type of SoC device.  But we're already
creating drivers for these devices, so why not use the driver name
directly.  There's a very strong coupling between the device and the
driver in the embedded realm (and usually some 'leakage' from other
devices as well, since things aren't quite as orthogonal as in the PC
world).

I'm trying to piece together in my mind how DEVCLASS would work for
one of the Atmel processors I know so well.  In it there's one device
shared with the PC (an ohci that needs to have some things allocated
in a slightly funky way), and then a bunch of devices that exist only
in this SoC and other SoCs from Atmel (ARM7, ARM9 and AVR32): USART,
MCI, TWI, SSC, etc.  The USART driver is implemented using the uart
framework.  The other drivers are fully custom jobs that provide I2C
or MMC/SD hooks for those subsystems (or just a bunch of
ioctls/read/write interfaces).

: Existing drivers that only check DEVTYPE (which I'm sure
: we'll start with) will have to check DEVCLASS as well if
: there's going to be variation within DEVTYPE.

Are there existing drivers right now?

FreeBSD has two models for device enumeration.  One is where the
parent bus decides, by whatever means, and one where the device itself
has enough information to allow the driver to decide.  I think that
trying to shoe-horn the second model into a situation where the first
model is actually better would be a disservice.

We can argue about where/how to create the tables for things, but I
think we'd both agree that we'd have to have some table somewhere for
these devices.  Or some set of tables that gets selected at runtime.

: > : Q4: What is minimally needed if we want to re-implement
: > :      existing embedded busses using ocpbus(4)?
: >
: > The atmel at91 code is moving in this direction in p4, but uses the
: > obio routines I wrote.
: 
: I'll take a look at obio. It seems to overlap in function
: with what I intend to do with ocpbus, so we may be able
: to turn obio into ocpbus or vice versa.

I think so too.  The obio stuff is in the devel-arm branch in p4
(//depot/project/arm) in sys/kern/subr_obio.c  It could be improved,
no doubt, but does handle most of the common cases of resource
allocation that were being duplicated all over the place.  If we
wanted to create a subclassable ocpbus out of it, that might be
worthwhile.

Warner



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20071228.125020.-1962668065.imp>