Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Dec 2007 16:58:55 -0800
From:      Marcel Moolenaar <marcelm@juniper.net>
To:        "M. Warner Losh" <imp@bsdimp.com>
Cc:        embedded@freebsd.org
Subject:   Re: ocpbus(4)
Message-ID:  <1B0F37B8-D492-4E15-82A8-704243E67E90@juniper.net>
In-Reply-To: <20071228.163257.756911359.imp@bsdimp.com>
References:  <B62C4CEF-F7CE-4388-B57F-288812BD9696@juniper.net> <20071228.150443.-924279995.imp@bsdimp.com> <4FA37AAF-8113-44DE-8FF9-5BB203188912@juniper.net> <20071228.163257.756911359.imp@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help

On Dec 28, 2007, at 3:32 PM, M. Warner Losh wrote:

> The usb driver on atmel needs to manipulate the clock generator when
> it is attached to generate the 48MHz needed for the USB devices.
> However, when the driver isn't present in the kernel, the right thing
> to do is to keep this clock off because it uses power.  How could this
> be done generically?

The first important part here is whether the USB driver needs
to know about the generator. For uart(4) the ocpbus handshake
already includes an IVAR for the clock, so let's reuse that
for USB. When the clock IVAR doesn't exist, the USB driver does
not need to worry about the clock (default). If the clock IVAR
exists, it returns something that tells the USB driver to
program the generator.

What that something is, depends on whether the generator has a
driver attached to it, or whether the clock is more platform
specific than USB host controller specific.

Let's assume the generator has a driver attached to it. The
clock IVAR can then return the device_t of that driver and by
means of a well-defined handshake (say a KOBJ I/F) the USB
driver can tell the CG driver to enable the clock.

If there's no driver attached to the generator, then the
ocpbus attachment can pass resource information to the USB
driver by way of a second RID. This then is used by the
USB driver (ocpbus specific code) to program the generator.

Of course, when the generator is within the USB resource
range, it can be done from within the ocpbus attach function
with the one resource assigned to the device. The IVAR then
simply enables some code or another.

Another way is have a "global" platform function for this
that is called from the ocpbus attach function. That function
can be a stub on platforms that have the same USB driver, but
that do not have the generator.


> On the xscale port, there's support for the compact flash that lives
> on many of them.  There's a number of chip-specific and board-specific
> hacks that must happen in order for the generic driver to work.

This may be done using KOBJ interfaces.

I wrote a CFI driver and you can abstract the differences
using KOBJ methods while still having a single driver.
This is much akin to uart(4).

> On the mips platform there are at least two flavors of 16550-like
> uarts present.  One requires 32-bit access that's shifted 3 and the
> other 64-bit access that's shifted 4.

Register shifting is already present in the uart(4) driver
and information about it comes from the bus attachment. This
does not mean that the uart(4) driver does 32- or 64-bit
I/O. It always does 8-bit I/O. It's probably not a good idea
to add support for 32-bit or 64-bit I/O to uart(4), unless
we handle it as a separate hardware driver (the ns8250 is
defined to use 8-bit I/O, so if that's not possible, it's
not a ns8250 class UART).
It's likely to be a platform or bus property, so it can all
be handled naturally with the bus access functions. (i.e.
implement the 1-byte access functions using 32- or 64-bit
loads/stores).

> The SPI, and MMC drivers need to interact with the chip selects the
> chip offers.  The manner of these interactions varies based on the
> underlying SoC.

Either special drivers or otherwise a KOBJ interface to
abstract it and use the ocpbus' DEVCLASS to select the
KOBJ class (like uart(4)).

> Right now, all of these situations are dealt with by having a bit of
> code in a specific attachment cope.

Right. All these bits of code can be triggered by
information that comes from the bus. The uart(4) register
shift comes from the bus (when uart(4) is a child of
puc(4) or scc(4)) or is hardcoded (sparc64 ebus or sbus).

It's easy to expose that information through a single
ocpbus handshake that includes information about the
clock and register shift for UARTs.

> : > Am I understanding your proposal correctly?  I can't see how  
> else it
> : > would work if this isn't the case, but if you have some clever  
> scheme,
> : > I'd be interested.
> :
> : No, this is more or less the gist of it. The type and id
> : can be chosen in any way we like, including using the type
> : as the id. The abstract bus driver does not need to know
> : anything other than maybe translate a table into a newbus
> : hierarchy and using the type/id combination to flag a
> : child.
>
> How does this abstract driver know about the children to add?  Or
> rather, how were you envisioning it getting the table it needed?

That's not part of the ocpbus definition. It only defines
the handshake between a bus and the bus attachment. In some
cases you can put it all in nexus. In other cases you create
a new bus driver that implements the handshake and has its
own way of enumerating devices.

> : Any newbus node that implements the ocpbus handshake is
> : then automatically an ocpbus driver even though there's
> : no mention of how it obtains the device information. As
> : I said before: it's about avoiding the flurry of bus
> : attachments, not about dictating how devices are
> : enumerated.
>
> I agree that's a noble goal, and maybe we can avoid it in many cases,
> but not in all cases.  I just don't think having a large enumeration
> table to make this work is worth the effort of maintaining it.  When
> you go to add a new ocpbus driver, you need to touch additional places
> than the direct method.

How so?

> Now, apart from enumeration, I think that having a good, well known
> protocol would be good.  I'm still a little unclear how one would
> communicate some of the stuff to the drivers, but I'm doing a p4 sync
> right now to get the e500 branch so I can take a look at what's there.

For uart(4) we currently have:

	static int
	uart_ocp_probe(device_t dev)
	{
		device_t parent;
		struct uart_softc *sc;
		uintptr_t clock, devtype;
		int error;

		parent = device_get_parent(dev);

		error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
		if (error)
			return (error);
		if (devtype != OCPBUS_DEVTYPE_UART)
			return (ENXIO);

		sc = device_get_softc(dev);
		sc->sc_class = &uart_ns8250_class;	/*1*/

		if (BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_CLOCK, &clock))
			clock = 0;
		return (uart_bus_probe(dev, 0, clock, 0, 0));	/*2*/
	}

At /*1*/ we can add support for a DEVCLASS to handle non-ns8250
UARTs and at /*2*/ we can add support for REGSHIFT. All based
on demand and all well-defined so that it's easy to replace an
existing driver with another.

-- 
Marcel Moolenaar
marcelm@juniper.net






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1B0F37B8-D492-4E15-82A8-704243E67E90>