A few questions about SD/MMC drivers

Martin Galvan omgalvan.86 at gmail.com
Sun Oct 5 22:05:18 UTC 2014


Hello everyone! I'm currently working on an SD/MMC host controller
driver for the Allwinner A10 SoC. Looking at some other drivers such
as at91_mci.c and lpc_mmc.c it seems most if not all of them have
roughly the same basic structure, so I thought I'd ask you guys a
couple of questions about them:

1) I noticed most MMC drvers allocate their memory and interrupt
resources using bus_alloc_resource_any by doing something like:

/* Allocate a memory window */
rid = 0;
bus_alloc_resource_any(device, type, &rid, flags);

/* Some code */

/*Allocate an interrupt */
rid = 0;
bus_alloc_resource_any(device, type, &rid, flags);

and on error handling code, they do:

bus_release_resource(device, type, 0, resource);

Looking at the man pages for both functions, it seems we shouldn't be
ignoring the returned value of rid after bus_alloc_resource_any. From
bus_release_resource(9):

"rid is the resource ID of the resource.  The rid value must be the
same as the one returned by bus_alloc_resource(9)."

Is there any reason why we're just passing it a hardcoded 0 instead of
storing the returned rid? Furthermore, why are we passing
bus_alloc_resource_any a value of 0 in the first place? Looking at
bus_alloc_resource(9):

"rid points to a bus specific handle that identifies the resource
being allocated. For ISA this is an index into an array of resources
that have been setup for this device by either the PnP mechanism, or
via the hints mechanism. For PCCARD, this is an index into the array
of resources described by the PC Card's CIS entry. For PCI, the offset
into pci config space which has the BAR to use to access the resource.
The bus methods are free to change the RIDs that they are given as a
parameter.  You must not depend on the value you gave it earlier."

I'm not implying the existing code is wrong, I'm just curious about
why are we using those particular values.

2) The code I'm working on is based off the Linux driver for the same
host, which as of today stands as the only "documentation", so to
speak, on that particular host. According to the Linux driver, we need
to do a phase shift adjustment while setting the clock in the set_ios
function. That involves several steps, one of which is calling
clk_set_rate, which seems to be a function many other Linux drivers
use. As I'm not familiar with Linux kernel internals, so far I haven't
been able to find the equivalent for that function on BSD, so how
should I go about this?

3) Finally, I noticed in the Linux driver they sometimes wrap a
register read operation around a do-while loop waiting on both the
result of that read and a timer, like this:

do {
    read_value = read_a_register(some_register);
} while ((read_value != desired_value) && (time_before(jiffies, expire));

where "expire" is an unsigned long whose value is computed as the sum
of a global called "jiffies" and the result of a call to
msecs_to_jiffies(). This is done so after the loop they can check
whether the register holds the desired value or a timeout occurred. Do
we have something similar on BSD? If not, what would be a safer way to
implement a timeout mechanism than simply decreasing a counter?

Thanks a lot!


More information about the freebsd-drivers mailing list