Date: Sun, 5 Oct 2014 19:05:16 -0300 From: Martin Galvan <omgalvan.86@gmail.com> To: freebsd-drivers@freebsd.org Cc: freebsd-embedded@freebsd.org Subject: A few questions about SD/MMC drivers Message-ID: <CAN19L9ENsuAR6_aXwJSRdfDz6UgE6kU%2BrCkGGsdK7tRcUes%2B0w@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
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!
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAN19L9ENsuAR6_aXwJSRdfDz6UgE6kU%2BrCkGGsdK7tRcUes%2B0w>