Re: Handling of modular boards
On Fri, May 4, 2012 at 10:44 PM, Mark Brown wrote: > On Fri, May 04, 2012 at 01:50:01PM -0600, Stephen Warren wrote: > >> b) Doesn't integrate well with hotplug; the DT for the board >> configuration is static at boot. What if a board can be unplugged and >> another plugged in; a reboot or similar would be needed to adjust the >> kernel to this. > > This is another issue - a similar set of problems does apply to some PCI > type cards where the PCI device is essentially a bridge to a typical > embedded system - though practically speaking it's much less severe. I think Alessandro is working on a board like that right now, so looping in Ale to this discussion to get his attention... Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Handling of modular boards
On Fri, May 4, 2012 at 9:34 PM, Arnd Bergmann wrote: > Thanks for getting the discussion started. I've seen the same issue come > up for arch/arm/mach-ux500/board-mop500*uib.c and for the beaglebone. > I'm sure there are many more, but we should make sure that everyone > of these can live with whatever we come up with. The same issue sort of comes up with any system that uses the idiom to have a few GPIO lines indicate in a binary code what version of the board we're dealing with and what devices are thus on it, right? We have this issue for the U9540 reference design and potentially on the Snowball as well. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] RFC: AMBA bus discardable probe() function
[Greg] > [Me] > > + spin_lock(&amba_bustype.p->klist_drivers.k_lock); > > Ick, nope, you can't do this, sorry. That's a "private" structure for > a reason. Yeah I get it, but in the platform bus case what's that traversal of the klists actually for? I didn't get it, and was guessing that it was considering the case where devices spawn new devices. > So what's the real driving force here, just saving a few hundred bytes > after booting? Or something else? A few thousand actually according to Russells measurements. And no I don't think it's worth it unless someone else challenge this... Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] RFC: AMBA bus discardable probe() function
[Russell] > which gives a total of 5188 bytes for all the above probe functions. > However, in order to free this, we're adding 184 bytes of code and > literal pool to achieve this: > (...) > The overall kernel size is 3877020 bytes, which means we're potentially > allowing for 0.13% of the kernel to be freed at run time - which may > equate to one or at most two additional pages. We have the PL022 as well, and the PL08x is being added but it will likely stay in that ballpark figure. But overall that does not seem to be worth it, so let's drop it for the time being. CC:ing the linux-embedded folks that often worry about footprint size to see if someone oppose. Also CC Viresh who works on a platform for e.g. set-top boxes using these PrimeCells which I think may be memory-constrained. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 0/2] u_char.c and mtp.c patches
2010/4/21 Roger Quadros : [MTP device with PTP class and MTP extension code] > On Linux (Ubuntu 9.04) it works as PTP device. If you have libmtp 1.0.1 or later it should work as MTP with some client program like Rhythmbox or Amarok or Banshee, unless some PTP handler hogs it first. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 0/2] u_char.c and mtp.c patches
2010/4/20 Roger Quadros : >> http://libmtp.cvs.sourceforge.net/viewvc/*checkout*/libmtp/libmtp/src/libusb-glue.c?revision=1.284 > > Do you know if these older Windows OSes request the OS descriptor when the > device uses a standard USB class code? I haven't tested, but I think Windows will attempt to always use the OS descriptor first and foremost. > AFAIK the MTP device device should use PTP Class, Subclass and protocol > codes (i.e. 6:1:1). In this case Windows XP treats it as a PTP device (even > if the device implements OS descriptors). > > I'm sure all MTP devices in the market that implement OS descriptors use > Vendor Specific class (i.e. 0xff:0:0) which is not the right thing to do > after MTP has been standardized by usb.if. Yes they should, but still very few devices, if any, use the PTP class code. The reason behind, and the reason to why they use the OS descriptor at all, if I understood correctly, was that Microsoft actually *wanted* to use the PTP class for MTP devices, but to do that the MTP extensions had to pass through the USB IF standardization process which took some three years or so. In the meantime USB IF forbade them to use the PTP class code for something that was not officially a PTP extension. So these devices all are class 0xff "vendor specific" or 0x00 "defined at interface level". (One device mistakedly use class code 111 decimal!) I haven't however looked at what they're using as bInterfaceClass really, perhaps there are MTP devices out there that define themselves as PTP, I've never heard of one, other than the experimental device that was used to implement the proper detection algorithm in libmtp. I think Windows only knows they are MTP devices by either probing the OS descriptor or having a built-in table of MTP-compliant vendor/device ID pairs. Probably both, because some of the very earliest "PMC" (Portable Media Center) models didn't even have OS descriptors. I guess Felipe may have first-hand experience with using the PTP class code only? Maybe this works in the latest Windowses, post-USB IF standardization? No idea. Maybe tagging a device with the PTP class and subclass 0x01 will make it always fall back to PTP mode only under Windows, MTP features disabled, this would not surprise me one bit. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 0/2] u_char.c and mtp.c patches
2010/4/19 Steve Calfee : > For 6 months, a while ago, I was working on virtual USB stuff for a > company. I did analyser traces of many devices including many MS > devices (mice, webcam, keyboard, joystick), and never found any device > from MS or anyone that supported that command. All devices that I saw > just replied (properly) with a STALL - and Winxp would just continue > on and handle the device. I don't think they add it to that kind of devices. Only MTP players for what I've seen. Maybe some weirdo RNDIS stuff use it too? But as you see Windows issues this command to absolutely everything you plug in, I've been thinking about how we could emulate the same behaviour in Linux but actually I think it's a bit insane and only take extra time to send that command to whatever you plug in. Still it would be nice to know directly from userspace if a device that was plugged in was MTP or not, especially we need this for udev rules (or HAL, DeviceKit etc, whatever) that want to make the device read/writable for the console user when it's plugged in. > When you say "older windowses", which one; the only earlier ones with > USB was 98 and descendants and somewhat 95. Especially the Win98 and Win2000 stuff that comes with the Windows Media Player has to respond to it. Actually Windows probably has some internal list of devices and specific quirks it has to use for them to work properly, but I'm not sure. (I asked them about it I think, but didn't get any replies.) > Also have you found a device that actually responds to the "get > osdescriptor" request? Almost all MTP devices out there does, check the logs here: http://libmtp.cvs.sourceforge.net/viewvc/libmtp/libmtp/logs/ If the device responds with something sane for command 0xee the MTP stack will go on to issue special commands, you can find our code for this here: http://libmtp.cvs.sourceforge.net/viewvc/*checkout*/libmtp/libmtp/src/libusb-glue.c?revision=1.284 Basically it's a simple libusb command we issue: /* Read the special descriptor */ ret = usb_get_descriptor(devh, 0x03, 0xee, buf, sizeof(buf)); // Dump it, if requested if (dumpfile != NULL && ret > 0) { fprintf(dumpfile, "Microsoft device descriptor 0xee:\n"); data_dump_ascii(dumpfile, buf, ret, 16); } It typically looks like this: Microsoft device descriptor 0xee: : 1203 4d00 5300 4600 5400 3100 3000 3000 ..M.S.F.T.1.0.0. 0010: 1c00 .. Microsoft device response to control message 1, CMD 0x1c: : 2800 0001 0400 0100 (... 0010: 0001 4d54 5000 3030 ..MTP.00 0020: Potential MTP Device with VendorID:22b8 and ProductID:6415 responded to control message 2 with a response that was too short. Problems may arrise but continuing Device info: But Ziilabs Egg actually reply properly to the second control message: Microsoft device descriptor 0xee: : 1203 4d00 5300 4600 5400 3100 3000 3000 ..M.S.F.T.1.0.0. 0010: 0100 .. Microsoft device response to control message 1, CMD 0x01: : 2800 0001 0400 0100 (... 0010: 0001 4d54 5000 ..MTP... 0020: Microsoft device response to control message 2, CMD 0x01: : 0c00 0001 0500 A special oddity is devices that *require* you to probe the device descriptor and won't even work if you don't: ZiiLabs Egg, several SanDisk Sansas, and some LGE phones display this behaviour. Since the devices are only ever tested with Windows nobody notice that they don't work properly without the probing... There are some more generic USB misbehaviour displayed by these devices I can list if you're interested. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 0/2] u_char.c and mtp.c patches
2010/4/19 Felipe Balbi : >> 2010/4/18 Linus Walleij : >> Further comments: there is apparently a driver floating around this list >> for supporting PTP through the gadgetfs. How does this work relate >> to that, and why can't you use gadgetfs? > > dude, can't you read ? gadgetfs prevents us from combining into a composite > gadget. We went throught that already. Please follow the thread before > commenting. Yeah sorry, I'm trying to catch up and miss some pieces here and there. I'm mainly reading it from the MTP side of things. >> Second: after looking at this, I think that atleast the part of >> functionality >> called "OS descriptor" should be in the kernel and not in userspace, >> is the OS descriptor the reason to why you want to expose EP0 to >> userspace, or are you using this for other things in the MTP stack? > > OS descriptor is MS specific crap, it's not on the USB-IF mtp spec and most > like MS has some patent on that. ...so I read you like it's not going to be supported with the proposed solution? I think that if you want you gadget to work with older Windowses, you simply have to support this. Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 0/2] u_char.c and mtp.c patches
2010/4/18 Linus Walleij : > The following two patches are RFC because we still have > a few open questions regarding them. Further comments: there is apparently a driver floating around this list for supporting PTP through the gadgetfs. How does this work relate to that, and why can't you use gadgetfs? Second: after looking at this, I think that atleast the part of functionality called "OS descriptor" should be in the kernel and not in userspace, is the OS descriptor the reason to why you want to expose EP0 to userspace, or are you using this for other things in the MTP stack? Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC/PATCH 0/2] u_char.c and mtp.c patches
Hi Felipe, > The following two patches are RFC because we still have > a few open questions regarding them. sorry for responding so late on this patch set. I've been working on MTP for some years from the host side of the MTP pipe, with the initiator library libmtp. I would appreciate if future patch sets are CC:ed to libmtp-disc...@lists.sourceforge.net where we have an MTP initiator community, thanks. The patch has some small basic problems due to it's actual paradigm/use model not being described, and that should be part of the patch so as to open up for a wider discussion. The intention of this patch is not to provide any MTP or PTP gadget drivers at all really, it is about creating a stub driver for MTP that can be used from userspace, where the actual protocol implementation is supposed to reside. So this is the PTP/MTP equivalent of TAP or TUN. This should be clear from the description of the patch and go in the comments of the file itself as well so as not to confuse anyone. The actual background to the driver being a stub is that vendors are deploying the (proprietary) MTP stack implementation from Microsoft in userspace on top of a driver like this. (This exact same work has been duplicated in a few places across the device manufacturer world.) This rationale should also be clear from the patch and the files. It is of course possible to implement a *real* MTP gadget driver in kernelspace, directly accessing the file system etc, not needing to involve userspace for any MTP transfers at all. There is an official USB IF specification for MTP which can be used to that end. Some day somebody will come along and do just that, I've been sort of hoping that some company like Google could jump in and actually do that. I know this is all absolutely crystal clear to you, but it's not going to be for everyone else in the world, that why all the words... Naming the function driver f_mtp.c is confusing since it does not implement MTP, it should be named f_mtpstub.c (and mtpstub.c) so that when someone one day really want to implement the protocol in the kernel, they can use f_mtp.c. Has the driver been designed with PTP in mind as well? There are several cameras running PTP on Linux in this world, for example the stuff from SONY. They have a userspace PTP stack in the same fashion I believe. I think it would just work with PTP as well after a quick review, but please give it a second thought. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Project Proposal: add sleeping spinlocks to mainline kernel
2009/12/16 Tim Bird : > Summary: add sleeping spinlocks to the mainline kernel If realtime performance overall is a big deal for CELF I would suggest adding "Kill-the-BKL" to the suggested projects. There are still some RTOS people using the BKL as an argument to flak the Linux kernel, c.f. http://www.freescale.com/files/32bit/doc/ref_manual/EMBMCRM.pdf (section 5.2) Another item could be to go through some common embedded arch drivers and switch them from request_irq() to request_threaded_irq() just based on the observation that almost nobody actually use that in the mainline kernel, though I'm sure they should, if realtime is a desired feature. (The wm8350-core driver is an excellent example of a situation where it is used properly.) NB: I'm not a member of the CE Linux Forum and nor is my company so I'm just talking freely here. (linux-embedded is public, hehe.) Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [POWER] battery calibration parameters from sysfs
Thanks for all the great attention Mark! [Mark wrote] > On Sat, Dec 05, 2009 at 02:08:11PM +0100, Linus Walleij wrote: > > (...) > > That's an easy solution of course, but then the sysfs files > > specified by the power subsystem, i.e. all "charge_*", > > "energy_*", "capacity" and "time_to_*" loose their meaning > > and must be ignored by userspace. > > These files should only be present if we have data for them. > Userspace can't be reliant on them at present since relatively few > systems seem to implement them, for example none of my laptops > have time_to, energy_ or capacity attributes. Well, yeah, we're not exactly in the laptop business. (But my HP laptop nc2400 has the "charge_*" attributes, 499 uAh in "charge_now" and this corresponds to what is shown in g-p-m converted over to Wh, but I don't know exactly where it's getting it from...) One of the things we're facing is Android, which has its userspace in plain Java JNI at the end of this link: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=s ervices/jni/com_android_server_BatteryService.cpp;h=8e7cadc6b680fc420d34 1faa094c71922946fdab;hb=HEAD If you browse down to line 275 you can see it parse the sysfs attribute "capacity", then this propagates up to the battery status indicator on *all* Android phones out there. So if you want to run Android unmodified, this is what you need to provide. They are effectively using the power sysfs as their hardware abstraction layer in this case. Note: I'm not claiming that Android is doing it right or that we can't modify this code or so, it's just that this is the way a few million Android devices out there are actually doing it. > > We have other odd code. Actually we have full software- > > controlled CC/CV charging in our driver, and that > > would *definately* go in such a library if it was > > to end up in kernelspace. We have actually > > pushed that to userspace, while I still tend to think > > that the kernel (with right parameters) should be able > > to charge a battery. But, well. > > As was previously discussed (in another thread) I do think there needs > to be at least some in kernel part to charger code like this > in order to > ensure that we're robust against userspace failure and cope well with > suspend and resume. There's the potential for serious hardware damage > if the battery is mistreated. You're right of course. In our case we have a hardware watchdog protecting against overcharging etc, and charging will halt when the watchdog is not periodically fed. So actually we're on the safe side here. (I think!) > There's other kernel filesystems that might be more > approprite for this > sort of stuff, trying to fit this into sysfs really does feel like far > too much pain to be right. You're right GKH already pointed me to configfs so that's where it's going to sit if we do this thing. We'd better write up some code to show how this would work instead so I'll be back with that sooner or later. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [POWER] battery calibration parameters from sysfs
Thanks Mark, prompt answers as always. [Mark Brown] > [Linus Walleij] > > In our code we have a number of (x,y) pair tables like this: > > > /* Vbat mV to Battery capacity % */ > > struct voltage_vs_capacity { > > int voltage; > > int capacity; > > }; > > Isn't the standard thing here to handle this voltage to > capacity mapping in userspace if we're just extrapolating > from experimental results? That's an easy solution of course, but then the sysfs files specified by the power subsystem, i.e. all "charge_*", "energy_*", "capacity" and "time_to_*" loose their meaning and must be ignored by userspace. Also this was just an example, we have similar calibration for the temperature sensor, and thus the "temp" sysfs file also loose its meaning. Since there is a plethora of userspace apps that just interface these files directly (gnome-power-manager and the Android stack come to mind) all these will have to be patches to accept a calibrated value from somewhere else if we shall use them with our hardware. But as you say: > Even with the "smart" batteries in PCs there are some > accuracy concerns and obviously the performance of the > battery will change over time. > ... > Actually, one further thing here - if this functionality > is implemented in kernel then shouldn't it be a generic > feature rather than part of the driver? The idea of > mapping battery voltages to capacity percentages isn't > specific to a given charger and will apply to all > batteries using the same technology. Surely, we'd be happy to do it that way if desired. What about drivers/power/battery_lib.c? (And getting algorithms in place for gradually adjusting the capacity levels as compared to factory settings for PC batteries would perhaps end up in the same place then.) We have other odd code. Actually we have full software- controlled CC/CV charging in our driver, and that would *definately* go in such a library if it was to end up in kernelspace. We have actually pushed that to userspace, while I still tend to think that the kernel (with right parameters) should be able to charge a battery. But, well. As for the calibration format, after reading up on the latest sysfs doc I saw: Documentation/filesystems/sysfs.txt: "Attributes should be ASCII text files, preferably with only one value per file. It is noted that it may not be efficient to contain only one value per file, so it is socially acceptable to express an array of values of the same type." This is close to that, an array of two types (x,y)(x,y) voltage,capacity,voltage,capacity etc. Pushing them in two files /sys/.../v_vs_cap_v /sys/.../v_vs_cap_cap and then make sure we write as many values to each array is uglier IMHO. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[POWER] battery calibration parameters from sysfs
Hi, we're working on battery charging support for ST-Ericsson MFD ASICs like AB3100 and later series. I have this issue about battery calibration parameters that I need advice on, and more specifically on how to use sysfs to get that data in. Most devices of this kind does not need the stuff we're doing so we're the odd bird here. Other batteries are "smart" (contain factory calibration inside of them) or get calibration from some BIOS or such. In our code we have a number of (x,y) pair tables like this: /* Vbat mV to Battery capacity % */ struct voltage_vs_capacity { int voltage; int capacity; }; /* * Default calibration table for voltage vs battery capacity. * Voltage in millivolts, capacity given in permil. */ struct voltage_vs_capacity voltage_to_battery_capacity_init[] = { { 4177, 1000 }, { 4070, 900 }, { 3988, 800 }, { 3834, 570 }, { 3797, 470 }, { 3768, 320 }, { 3721, 190 }, { 3633, 60 }, { 3523, 30 }, { 3200,0 }, }; We then interpolate between two subsequent (xn,yn),(xn+1,yn+1) pairs to get a calibrated capacity value from the voltage level measured. This is all good as long as you compile the calibration into the kernel like this. However we want to override the default table with one fed in though e.g. sysfs, so calibration data for the battery can reside in the file system. NOTE: this table is NOT of fixed length, i.e. we don't know how many (x,y) pairs will be passed in. Whereas the rule for sysfs is one value per file, creating an arbitrary large hirarchy like this: /sys/.../v_vs_cap/x0 /sys/.../v_vs_cap/y0 /sys/.../v_vs_cap/x1 /sys/.../v_vs_cap/y2 ... /sys/.../v_vs_cap/xN /sys/.../v_vs_cap/yN Is probably not very elegant. (Or is it?) Would it be permissible to pass in a table like: cat >/sys/.../v_vs_cap
Re: New fast(?)-boot results on ARM
2009/8/14 Robert Schwebel : > On Fri, Aug 14, 2009 at 12:19:48PM -0600, Zan Lynx wrote: >> > That's factor 70 away from the 110 ms boot time Tim has talked about >> > some days ago (and he measured on an ARM cpu which had almost half >> > the speed of this one), and I'm wondering what we can do to improve >> > the boot time. >> >> 2.4s in uncompression? That seems like an obvious target for >> improvement. > > Indeed, we'll check that. We got rid of uncompression on a flash-based system vastly improving boot time. The reason is that compressed kernels are faster only when the throughput to the persistent storage is lower than the decompression throughput, and on typical embedded systems with DMA the throughput to memory outperforms the CPU-based decompression. Of course it depends on a lot of stuff like performance of flash controller, kernel storage filesystem performance, DMA controller performance, cache architecture etc so it's individual per-system. Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] MMC Agressive clocking framework v4
2009/7/14 Linus Walleij : > 2009/6/21 Linus Walleij : > >> This patch modified the MMC core code to optionally call the >> set_ios() operation on the driver with the clock frequency set >> to 0 > > Ping on this. It's soon been a month since the last version and > I know we're in vacation times but... Aw sorry now I saw you mail about being unable to continue doing MMC maintenance. I will proceed to send the patch to Andrew if noone picks up the rôle, OK. Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] MMC Agressive clocking framework v4
2009/6/21 Linus Walleij : > This patch modified the MMC core code to optionally call the > set_ios() operation on the driver with the clock frequency set > to 0 Ping on this. It's soon been a month since the last version and I know we're in vacation times but... Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] transcendent memory for Linux
2009/6/20 Dan Magenheimer : > We call this latter class "transcendent memory" and it > provides an interesting opportunity to more efficiently > utilize RAM in a virtualized environment. However this > "memory but not really memory" may also have applications > in NON-virtualized environments, such as hotplug-memory > deletion, SSDs, and page cache compression. Others have > suggested ideas such as allowing use of highmem memory > without a highmem kernel, or use of spare video memory. Here is what I consider may be a use case from the embedded world: we have to save power as much as possible, so we need to shut off entire banks of memory. Currently people do things like put memory into self-refresh and then sleep, but for long lapses of time you would want to compress memory towards lower addresses and turn as many banks as possible off. So we have something like 4x16MB banks of RAM = 64MB RAM, and the most necessary stuff easily fits in one of them. If we can shut down 3x16MB we save 3 x power supply of the RAMs. However in embedded we don't have any swap, so we'd need some call that would attempt to remove a memory by paging out code and data that has been demand-paged in from the FS but no dirty pages, these should instead be moved down to memory which will be retained, and the call should fail if we didn't succeed to migrate all dirty pages. Would this be possible with transcendent memory? Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] MMC Agressive clocking framework v4
This patch modified the MMC core code to optionally call the set_ios() operation on the driver with the clock frequency set to 0 to gate the hardware block clock (and thus the MCI clock) for an MMC host controller after a grace period of at least 8 MCLK cycles. It is inspired by existing clock gating code found in the OMAP and Atmel drivers and brings this up to the host abstraction. Gating is performed before and after any MMC request. It exemplifies by implementing this for the MMCI/PL180 MMC/SD host controller, but it should be simple to switch OMAP and Atmel over to using this instead. Signed-off-by: Linus Walleij ChangeLog v3->v4: Fixed a single spelling error. --- drivers/mmc/core/Kconfig | 11 +++ drivers/mmc/core/core.c| 35 + drivers/mmc/core/core.h|2 + drivers/mmc/core/debugfs.c | 10 ++- drivers/mmc/core/host.c| 165 +++- drivers/mmc/core/host.h|3 + include/linux/mmc/host.h |9 +++ 7 files changed, 232 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index ab37a6d..5372fc9 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -14,3 +14,14 @@ config MMC_UNSAFE_RESUME This option is usually just for embedded systems which use a MMC/SD card for rootfs. Most people should say N here. +config MMC_CLKGATE + bool "MMC host clock gaing (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This will attempt to agressively gate the clock to the MMC host, + which typically also will gate the MCI clock to the card. This + is done to save power due to gating off the logic and bus noise + when MMC is not in use. Your host driver has to support this in + order for it to be of any use. + + If unsure, say N. diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2649117..e9093b6 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -113,6 +113,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) if (mrq->done) mrq->done(mrq); + + mmc_clk_disable(host); } } @@ -173,6 +175,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mrq->stop->mrq = mrq; } } + mmc_clk_enable(host); host->ops->request(host, mrq); } @@ -447,6 +450,38 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz) mmc_set_ios(host); } +#ifdef CONFIG_MMC_CLKGATE +/* + * This gates the clock by setting it to 0 Hz. + */ +void mmc_gate_clock(struct mmc_host *host) +{ + host->clk_old = host->ios.clock; + host->ios.clock = 0; + mmc_set_ios(host); +} + +/* + * This restores the clock from gating by using the cached + * clock value. + */ +void mmc_ungate_clock(struct mmc_host *host) +{ + /* +* We should previously have gated the clock, so the clock +* shall be 0 here! +* The clock may however be 0 during intialization, +* when some request operations are performed before setting +* the frequency. When ungate is requested in that situation +* we just ignore the call. +*/ + if (host->clk_old) { + BUG_ON(host->ios.clock); + mmc_set_clock(host, host->clk_old); + } +} +#endif + /* * Change the bus mode (open drain/push-pull) of a host. */ diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index c819eff..ee27f81 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -27,6 +27,8 @@ void mmc_detach_bus(struct mmc_host *host); void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); +void mmc_gate_clock(struct mmc_host *host); +void mmc_ungate_clock(struct mmc_host *host); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 610dbd1..1a969bd 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -149,11 +149,17 @@ void mmc_add_host_debugfs(struct mmc_host *host) host->debugfs_root = root; if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) - goto err_ios; + goto err_remove_files; + +#ifdef CONFIG_MMC_CLKGATE + if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR), + root, &host->clk_delay)) + goto err_remove_files; +#endif return; -err_ios: +err_remove_files: debugfs_remove_recursive(root); host->debugfs_root = NULL; err_root: diff -
[PATCH 2/2] Modify MMCI/PL180 to handle agressive clocking v4
This adds a few clk_enable()/clk_disable() calls to the MMCI driver so as to handle an set_ios() request with clock frequency set to 0 as an instruction to gate the block clock. This also breaks out the clock setting code into its own function to simplify the set_ios() function a bit. Signed-off-by: Linus Walleij --- drivers/mmc/host/mmci.c | 78 ++ 1 files changed, 57 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 36875dc..d9f5c9a 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -37,8 +37,34 @@ static unsigned int fmax = 515633; +/* + * This must be called with host->lock held + */ +static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) +{ + u32 clk = 0; + + if (desired) { + if (desired >= host->mclk) { + clk = MCI_CLK_BYPASS; + host->cclk = host->mclk; + DBG(host, "MMCI: bypass clock divider, cclk = %u Hz\n", host->cclk); + } else { + clk = host->mclk / (2 * desired) - 1; + if (clk >= 256) + clk = 255; + host->cclk = host->mclk / (2 * (clk + 1)); + DBG(host, "MMCI: divide cclk to %u Hz (divide %u by %u)\n", host->cclk, host->mclk, clk); + } + if (host->hw_designer == 0x80) + clk |= MCI_FCEN; /* Bug fix in ST IP block */ + clk |= MCI_CLK_ENABLE; + } + writel(clk, host->base + MMCICLOCK); +} + static void -mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) + mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) { writel(0, host->base + MMCICOMMAND); @@ -418,22 +444,7 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mmci_host *host = mmc_priv(mmc); - u32 clk = 0, pwr = 0; - - if (ios->clock) { - if (ios->clock >= host->mclk) { - clk = MCI_CLK_BYPASS; - host->cclk = host->mclk; - } else { - clk = host->mclk / (2 * ios->clock) - 1; - if (clk >= 256) - clk = 255; - host->cclk = host->mclk / (2 * (clk + 1)); - } - if (host->hw_designer == 0x80) - clk |= MCI_FCEN; /* Bug fix in ST IP block */ - clk |= MCI_CLK_ENABLE; - } + u32 pwr = 0; if (host->plat->translate_vdd) pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); @@ -464,12 +475,23 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } - writel(clk, host->base + MMCICLOCK); + spin_lock(&host->lock); + + if (ios->clock == 0) { + clk_disable(host->clk); + } else { + clk_enable(host->clk); + mmci_set_clkreg(host, ios->clock); + } if (host->pwr != pwr) { host->pwr = pwr; + clk_enable(host->clk); writel(pwr, host->base + MMCIPOWER); + clk_disable(host->clk); } + + spin_unlock(&host->lock); } static const struct mmc_host_ops mmci_ops = { @@ -615,6 +637,8 @@ static int __devinit mmci_probe(struct amba_device *dev, void *id) host->timer.expires = jiffies + HZ; add_timer(&host->timer); + /* The first IOS will turn the clock on again */ + clk_disable(host->clk); return 0; irq0_free: @@ -646,17 +670,22 @@ static int __devexit mmci_remove(struct amba_device *dev) mmc_remove_host(mmc); + /* framework may have gated the block clock */ + clk_enable(host->clk); + writel(0, host->base + MMCIMASK0); writel(0, host->base + MMCIMASK1); writel(0, host->base + MMCICOMMAND); writel(0, host->base + MMCIDATACTRL); + clk_disable(host->clk); + free_irq(dev->irq[0], host); free_irq(dev->irq[1], host); iounmap(host->base); - clk_disable(host->clk); + clk_put(host->clk); mmc_free_host(mmc); @@ -677,8 +706,11 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) struct mmci_host *host = mmc_priv(mmc); ret = mmc_suspend_host(mmc, state); - if (ret == 0) + if (ret
Re: [PATCH 1/2] MMC Agressive clocking framework v3
2009/6/18 Linus Walleij : > diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig >(...) > + Of unsure, say N. However the rest of the patch is as I intended. I'll send a V4 pronto if you want that for the current merge window. Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] MMC Agressive clocking framework v3
This patch modified the MMC core code to optionally call the set_ios() operation on the driver with the clock frequency set to 0 to gate the hardware block clock (and thus the MCI clock) for an MMC host controller after a grace period of at least 8 MCLK cycles. It is inspired by existing clock gating code found in the OMAP and Atmel drivers and brings this up to the host abstraction. Gating is performed before and after any MMC request. It exemplifies by implementing this for the MMCI/PL180 MMC/SD host controller, but it should be simple to switch OMAP and Atmel over to using this instead. Signed-off-by: Linus Walleij ChangeLog v2->v3: * Swapped alloc*/remove* pair for init*/exit* in the clocking functions. * Remove mmc_clk_enable/disable pair in the mmc_rescan(). It's not needed here. * Rename struct member .clk_users to .clk_requests so as to reflect what this is actually counting. It counts the number of current requests that need to have the MCI clk enabled. * Save and restore flags on all spinlocks, the code can be called in different contexts according to lockdep. * Spelling mistakes fixed. --- drivers/mmc/core/Kconfig | 11 +++ drivers/mmc/core/core.c| 35 + drivers/mmc/core/core.h|2 + drivers/mmc/core/debugfs.c | 10 ++- drivers/mmc/core/host.c| 165 +++- drivers/mmc/core/host.h|3 + include/linux/mmc/host.h |9 +++ 7 files changed, 232 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index ab37a6d..6ae2156 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -14,3 +14,14 @@ config MMC_UNSAFE_RESUME This option is usually just for embedded systems which use a MMC/SD card for rootfs. Most people should say N here. +config MMC_CLKGATE + bool "MMC host clock gaing (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This will attempt to agressively gate the clock to the MMC host, + which typically also will gate the MCI clock to the card. This + is done to save power due to gating off the logic and bus noise + when MMC is not in use. Your host driver has to support this in + order for it to be of any use. + + Of unsure, say N. diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2649117..e9093b6 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -113,6 +113,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) if (mrq->done) mrq->done(mrq); + + mmc_clk_disable(host); } } @@ -173,6 +175,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mrq->stop->mrq = mrq; } } + mmc_clk_enable(host); host->ops->request(host, mrq); } @@ -447,6 +450,38 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz) mmc_set_ios(host); } +#ifdef CONFIG_MMC_CLKGATE +/* + * This gates the clock by setting it to 0 Hz. + */ +void mmc_gate_clock(struct mmc_host *host) +{ + host->clk_old = host->ios.clock; + host->ios.clock = 0; + mmc_set_ios(host); +} + +/* + * This restores the clock from gating by using the cached + * clock value. + */ +void mmc_ungate_clock(struct mmc_host *host) +{ + /* +* We should previously have gated the clock, so the clock +* shall be 0 here! +* The clock may however be 0 during intialization, +* when some request operations are performed before setting +* the frequency. When ungate is requested in that situation +* we just ignore the call. +*/ + if (host->clk_old) { + BUG_ON(host->ios.clock); + mmc_set_clock(host, host->clk_old); + } +} +#endif + /* * Change the bus mode (open drain/push-pull) of a host. */ diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index c819eff..ee27f81 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -27,6 +27,8 @@ void mmc_detach_bus(struct mmc_host *host); void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); +void mmc_gate_clock(struct mmc_host *host); +void mmc_ungate_clock(struct mmc_host *host); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 610dbd1..1a969bd 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -149,11 +149,17 @@ void mmc_add_host_debugfs(struct mmc_host *host) host->debugfs_root = root; if (!debugfs_create_file("ios"
[PATCH 2/2] Modify MMCI/PL180 to handle agressive clocking v3
This adds a few clk_enable()/clk_disable() calls to the MMCI driver so as to handle an set_ios() request with clock frequency set to 0 as an instruction to gate the block clock. This also breaks out the clock setting code into its own function to simplify the set_ios() function a bit. Signed-off-by: Linus Walleij --- drivers/mmc/host/mmci.c | 78 ++ 1 files changed, 57 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 36875dc..d9f5c9a 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -37,8 +37,34 @@ static unsigned int fmax = 515633; +/* + * This must be called with host->lock held + */ +static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) +{ + u32 clk = 0; + + if (desired) { + if (desired >= host->mclk) { + clk = MCI_CLK_BYPASS; + host->cclk = host->mclk; + DBG(host, "MMCI: bypass clock divider, cclk = %u Hz\n", host->cclk); + } else { + clk = host->mclk / (2 * desired) - 1; + if (clk >= 256) + clk = 255; + host->cclk = host->mclk / (2 * (clk + 1)); + DBG(host, "MMCI: divide cclk to %u Hz (divide %u by %u)\n", host->cclk, host->mclk, clk); + } + if (host->hw_designer == 0x80) + clk |= MCI_FCEN; /* Bug fix in ST IP block */ + clk |= MCI_CLK_ENABLE; + } + writel(clk, host->base + MMCICLOCK); +} + static void -mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) + mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) { writel(0, host->base + MMCICOMMAND); @@ -418,22 +444,7 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mmci_host *host = mmc_priv(mmc); - u32 clk = 0, pwr = 0; - - if (ios->clock) { - if (ios->clock >= host->mclk) { - clk = MCI_CLK_BYPASS; - host->cclk = host->mclk; - } else { - clk = host->mclk / (2 * ios->clock) - 1; - if (clk >= 256) - clk = 255; - host->cclk = host->mclk / (2 * (clk + 1)); - } - if (host->hw_designer == 0x80) - clk |= MCI_FCEN; /* Bug fix in ST IP block */ - clk |= MCI_CLK_ENABLE; - } + u32 pwr = 0; if (host->plat->translate_vdd) pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); @@ -464,12 +475,23 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } - writel(clk, host->base + MMCICLOCK); + spin_lock(&host->lock); + + if (ios->clock == 0) { + clk_disable(host->clk); + } else { + clk_enable(host->clk); + mmci_set_clkreg(host, ios->clock); + } if (host->pwr != pwr) { host->pwr = pwr; + clk_enable(host->clk); writel(pwr, host->base + MMCIPOWER); + clk_disable(host->clk); } + + spin_unlock(&host->lock); } static const struct mmc_host_ops mmci_ops = { @@ -615,6 +637,8 @@ static int __devinit mmci_probe(struct amba_device *dev, void *id) host->timer.expires = jiffies + HZ; add_timer(&host->timer); + /* The first IOS will turn the clock on again */ + clk_disable(host->clk); return 0; irq0_free: @@ -646,17 +670,22 @@ static int __devexit mmci_remove(struct amba_device *dev) mmc_remove_host(mmc); + /* framework may have gated the block clock */ + clk_enable(host->clk); + writel(0, host->base + MMCIMASK0); writel(0, host->base + MMCIMASK1); writel(0, host->base + MMCICOMMAND); writel(0, host->base + MMCIDATACTRL); + clk_disable(host->clk); + free_irq(dev->irq[0], host); free_irq(dev->irq[1], host); iounmap(host->base); - clk_disable(host->clk); + clk_put(host->clk); mmc_free_host(mmc); @@ -677,8 +706,11 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) struct mmci_host *host = mmc_priv(mmc); ret = mmc_suspend_host(mmc, state); - if (ret == 0) + if (ret
Re: [PATCH 1/2] MMC Agressive clocking framework v2
2009/6/15 Pierre Ossman : > On Tue, 2 Jun 2009 14:36:28 +0200 > Linus Walleij wrote: > >> This patch modified the MMC core code to optionally call the >> set_ios() operation on the driver with the clock frequency set >> to 0 to gate the hardware block clock (and thus the MCI clock) >> for an MMC host controller after a grace period of at least 8 >> MCLK cycles. It is inspired by existing clock gating code found >> in the OMAP and Atmel drivers and brings this up to the host >> abstraction. Gating is performed before and after any MMC request >> or IOS operation, the other optional host operations will not >> ungate/gate the clock since they do not necessary touch the >> actual host controller hardware. >> >> It exemplifies by implementing this for the MMCI/PL180 MMC/SD >> host controller, but it should be simple to switch OMAP and >> Atmel over to using this instead. >> >> Signed-off-by: Linus Walleij >> --- > > This looks pretty good. We might want to make it more runtime > configurable in the future, but this lays a nice groundwork. It's also > nicely commented to boot. :) > > The only thing that concerns me is the locking and reference counting. > Wouldn't it be sufficient to enable the clock around requests? Actually that's all it does now, I had it also in mmc_rescan() but don't think that's necessary (will do some more deep testing before sending the updated patch). > Or > when the host lock is grabbed? Either version would remove the need for > both clk_users and clk_lock. I think it would also remove a lot of the > special logic you have. I have renamed clk_users to clk_requests because that's what it counts now. Its still needed however: the problem here is that we need to keep the clock running a number of cycles after the last request, so we solve it by increasing .clk_requests by one for every request, then decreasing by one for every request that ends. Of course requests are serialized, but the request counter is used for the disablement work to know if any new request came in when we were delaying for the clk_disable() call, this work will actually not be scheduled until after a few requests end and provides the necessary hysteresis. The requests count would not be needed unless we were splitting of a separate work, but we have to do that in order to have a burst of requests serviced without waiting 8 MCI clocks inbetween each of them. The idea here is just to delay set_ios() with freq = 0 until we know for sure that the current burst of requests is ended. When I put in some prints I see that there are lots of requests coming in bursts so this forms a nice "clock on" window around them. >> diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig >> index ab37a6d..6ae2156 100644 >> --- a/drivers/mmc/core/Kconfig >> +++ b/drivers/mmc/core/Kconfig >> @@ -14,3 +14,14 @@ config MMC_UNSAFE_RESUME >> This option is usually just for embedded systems which use >> a MMC/SD card for rootfs. Most people should say N here. >> >> +config MMC_CLKGATE >> + bool "MMC host clock gaing (EXPERIMENTAL)" >> + depends on EXPERIMENTAL >> + help >> + This will attempt to agressively gate the clock to the MMC host, >> + which typically also will gate the MCI clock to the card. This >> + is done to save power due to gating off the logic and bus noise >> + when MMC is not in use. Your host driver has to support this in >> + order for it to be of any use. > > The last sense isn't true anymore, is it? I rewrote it a bit: all drivers that want to perform clock gating still have to handle the freq field being set to 0 and take apropriate action. This is not the case when you don't enable clock gating, you get a few requests with freq set to 0 in the initialization code but once it's set to something it never goes to 0 again. Most drivers aren't written to handle frequency 0, some will probably even get a division by 0 error if you try it (just a guess). >> + >> + Of unsure, say N. > > "If" :) > >> +/* >> + * Internal work. Work to disable the clock at some later point. >> + */ >> +static void mmc_clk_disable_work(struct work_struct *work) >> +{ >> + struct mmc_host *host = container_of(work, struct mmc_host, >> + clk_disable_work); >> + >> + mmc_clk_disable_delayed(host); >> +} > > I think I did a bad job explaining my comments about this the last > time. What I was trying to say was that why have this > mmc_clk_disable_work() when you could give mmc_clk_disable_delayed()
Re: [PATCH 1/2] MMC Agressive clocking framework v2
2009/6/2 Linus Walleij : > This patch modified the MMC core code to optionally call the > set_ios() operation on the driver with the clock frequency set > to 0 to gate the hardware block clock (and thus the MCI clock) have you had a chance to look at this for the current merge window Pierre? Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] Modify MMCI/PL180 to handle agressive clocking v2
This adds a few clk_enable()/clk_disable() calls to the MMCI driver so as to handle an set_ios() request with clock frequency set to 0 as an instruction to gate the block clock. This also breaks out the clock setting code into its own function to simplify the set_ios() function a bit. Signed-off-by: Linus Walleij --- drivers/mmc/host/mmci.c | 78 ++ 1 files changed, 57 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 36875dc..d9f5c9a 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -37,8 +37,34 @@ static unsigned int fmax = 515633; +/* + * This must be called with host->lock held + */ +static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) +{ + u32 clk = 0; + + if (desired) { + if (desired >= host->mclk) { + clk = MCI_CLK_BYPASS; + host->cclk = host->mclk; + DBG(host, "MMCI: bypass clock divider, cclk = %u Hz\n", host->cclk); + } else { + clk = host->mclk / (2 * desired) - 1; + if (clk >= 256) + clk = 255; + host->cclk = host->mclk / (2 * (clk + 1)); + DBG(host, "MMCI: divide cclk to %u Hz (divide %u by %u)\n", host->cclk, host->mclk, clk); + } + if (host->hw_designer == 0x80) + clk |= MCI_FCEN; /* Bug fix in ST IP block */ + clk |= MCI_CLK_ENABLE; + } + writel(clk, host->base + MMCICLOCK); +} + static void -mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) + mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) { writel(0, host->base + MMCICOMMAND); @@ -418,22 +444,7 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mmci_host *host = mmc_priv(mmc); - u32 clk = 0, pwr = 0; - - if (ios->clock) { - if (ios->clock >= host->mclk) { - clk = MCI_CLK_BYPASS; - host->cclk = host->mclk; - } else { - clk = host->mclk / (2 * ios->clock) - 1; - if (clk >= 256) - clk = 255; - host->cclk = host->mclk / (2 * (clk + 1)); - } - if (host->hw_designer == 0x80) - clk |= MCI_FCEN; /* Bug fix in ST IP block */ - clk |= MCI_CLK_ENABLE; - } + u32 pwr = 0; if (host->plat->translate_vdd) pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); @@ -464,12 +475,23 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } - writel(clk, host->base + MMCICLOCK); + spin_lock(&host->lock); + + if (ios->clock == 0) { + clk_disable(host->clk); + } else { + clk_enable(host->clk); + mmci_set_clkreg(host, ios->clock); + } if (host->pwr != pwr) { host->pwr = pwr; + clk_enable(host->clk); writel(pwr, host->base + MMCIPOWER); + clk_disable(host->clk); } + + spin_unlock(&host->lock); } static const struct mmc_host_ops mmci_ops = { @@ -615,6 +637,8 @@ static int __devinit mmci_probe(struct amba_device *dev, void *id) host->timer.expires = jiffies + HZ; add_timer(&host->timer); + /* The first IOS will turn the clock on again */ + clk_disable(host->clk); return 0; irq0_free: @@ -646,17 +670,22 @@ static int __devexit mmci_remove(struct amba_device *dev) mmc_remove_host(mmc); + /* framework may have gated the block clock */ + clk_enable(host->clk); + writel(0, host->base + MMCIMASK0); writel(0, host->base + MMCIMASK1); writel(0, host->base + MMCICOMMAND); writel(0, host->base + MMCIDATACTRL); + clk_disable(host->clk); + free_irq(dev->irq[0], host); free_irq(dev->irq[1], host); iounmap(host->base); - clk_disable(host->clk); + clk_put(host->clk); mmc_free_host(mmc); @@ -677,8 +706,11 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) struct mmci_host *host = mmc_priv(mmc); ret = mmc_suspend_host(mmc, state); - if (ret == 0) + if (ret == 0) { +
[PATCH 1/2] MMC Agressive clocking framework v2
This patch modified the MMC core code to optionally call the set_ios() operation on the driver with the clock frequency set to 0 to gate the hardware block clock (and thus the MCI clock) for an MMC host controller after a grace period of at least 8 MCLK cycles. It is inspired by existing clock gating code found in the OMAP and Atmel drivers and brings this up to the host abstraction. Gating is performed before and after any MMC request or IOS operation, the other optional host operations will not ungate/gate the clock since they do not necessary touch the actual host controller hardware. It exemplifies by implementing this for the MMCI/PL180 MMC/SD host controller, but it should be simple to switch OMAP and Atmel over to using this instead. Signed-off-by: Linus Walleij --- drivers/mmc/core/Kconfig | 11 +++ drivers/mmc/core/core.c| 38 +++ drivers/mmc/core/core.h|2 + drivers/mmc/core/debugfs.c | 10 ++- drivers/mmc/core/host.c| 160 +++- drivers/mmc/core/host.h|3 + include/linux/mmc/host.h |9 +++ 7 files changed, 230 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index ab37a6d..6ae2156 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -14,3 +14,14 @@ config MMC_UNSAFE_RESUME This option is usually just for embedded systems which use a MMC/SD card for rootfs. Most people should say N here. +config MMC_CLKGATE + bool "MMC host clock gaing (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This will attempt to agressively gate the clock to the MMC host, + which typically also will gate the MCI clock to the card. This + is done to save power due to gating off the logic and bus noise + when MMC is not in use. Your host driver has to support this in + order for it to be of any use. + + Of unsure, say N. diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2649117..c64dfe2 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -113,6 +113,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) if (mrq->done) mrq->done(mrq); + + mmc_clk_disable(host); } } @@ -173,6 +175,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) mrq->stop->mrq = mrq; } } + mmc_clk_enable(host); host->ops->request(host, mrq); } @@ -447,6 +450,39 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz) mmc_set_ios(host); } +#ifdef CONFIG_MMC_CLKGATE +/* + * This gates the clock by setting it to 0 Hz. + */ +void mmc_gate_clock(struct mmc_host *host) +{ + host->clk_old = host->ios.clock; + host->ios.clock = 0; + mmc_set_ios(host); +} + +/* + * This restores the clock from gating by using the cached + * clock value. + */ +void mmc_ungate_clock(struct mmc_host *host) +{ + /* +* We have gated previously so the clock +* shall be 0 here! +*/ + BUG_ON(host->ios.clock); + /* +* The clock may however be 0 during intialization, +* when some request operations are performed before setting +* the frequency. When ungate is requested in that situation +* we just ignore the call. +*/ + if (host->clk_old) + mmc_set_clock(host, host->clk_old); +} +#endif + /* * Change the bus mode (open drain/push-pull) of a host. */ @@ -861,6 +897,7 @@ void mmc_rescan(struct work_struct *work) * release the lock here. */ mmc_bus_put(host); + mmc_clk_enable(host); if (host->ops->get_cd && host->ops->get_cd(host) == 0) goto out; @@ -911,6 +948,7 @@ void mmc_rescan(struct work_struct *work) mmc_bus_put(host); } out: + mmc_clk_disable(host); if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); } diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index c819eff..ee27f81 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -27,6 +27,8 @@ void mmc_detach_bus(struct mmc_host *host); void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); +void mmc_gate_clock(struct mmc_host *host); +void mmc_ungate_clock(struct mmc_host *host); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 610dbd1..1a969bd 100644 --- a/driver
[PATCH 0/2] MMC Agressive clocking framework v2
ChangeLog v1->v2: * Switch the gating mechanism from using an additional callback to setting the "clock" field in the ios structure to 0 and storing away the current value to ungate the clock later on. * Remove the mmc_clk_enable/disable around the ios() operations as a result, if you use clock gating you have to take the gating into account in your set_ios() code. * Keep the nesting code (use count) this is used so that quick bursts of requests can be handled properly while the disable work is idling in the background and appears quite solid. Tried my best to clarify why this code look as it does. * Removed unnecessary depend on MMC!=n in the Kconfig, explicit (EXPERIMENTAL) in option description. * Updates MMCI reference implementation to reflect the new use of the clock field. * Remove unnecessary #include * Added a debugfs file appearing in /mmcN/clk_delay that can be used to trim the delay cycle count to test what happens with different values. * Works fine on my system. Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: conceptual map of the kernel source (Interactive Linux kernel map)
2008/7/31 Constantine Shulyupin <[EMAIL PROTECTED]>: > I am updating the kernel map: http://www.makelinux.net/kernel_map > It is conceptual map consisting of more than 200 most important kernel > functions. I was very impressed once I saw this map first, which was through your (?) contributions to the Linux entries in Wikipedia. Keep up the good work! > Could you please have a look and suggest fixes and updates. The embedded systems will be interested in most things not asm-i386 and arch-i386. For example you show a lot of PCI and such things in the lowest layers, I wonder if it'd be worth the effort to make arch-specific views of the lowermost parts (but probably not). Another this is that flash drivers MTD, doesn't fit into the picture, instead harddisk is uses as example. Linus -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: building Rootfs
2008/7/7 Robert Schwebel <[EMAIL PROTECTED]>: > On Mon, Jul 07, 2008 at 10:34:11PM +0200, Linus Walleij wrote: >> Robert, can you brief us of how ptxdist fits together with >> OpenEmbedded? What does these two projects actually share? Where do >> they do similar things in parallel for example? > > They are both build systems for userlands, or whole embedded linux > systems. I cannot speak for OE as I don't really know it in detail. Anyone have experience with both? I'd really like to have them contrasted and, well you know, cross-firtualized. > The idea behind ptxdist is executable documentation. I really like ptxdist, especially it is beautiful that you have based it around just bash and make plus some crosscompiler of choice. I just have some trouble getting it to do what I want. I'll hopefully get there. This is not meant as any generic complaining. I'm trying to figure out if ptxdist or openembedded is the best starting point. I have a situation where the build system would be on top of some SCM like git, CVS or whatever and packages being checked out and worked on by several people daily. This seems to clash with ptxdist design goals, for example: ptxdist seems * hardcoded to run in a users home directory with projects in $HOME/foo (stopped me right now, perhaps it can easily be fixed or is already part of ptxdist 2?) * assume only one person builds rootfs. So it doesn't really want the project tree to be used or modified by more than one person at the time. (Same as first more or less.) * not store source code, patches and config plus my local additions in one place. For most other package systems e.g. RPM there is /foo/foo.spec /foo/foo-1.0.tar.gz /foo/foo-patch1.diff /foo/foo-patch2.diff /foo/my-foo-config.file In ptxdist these seem to be spread out, some in the installation of ptxdist itself in say /usr/lib/ptxdist/patches, /usr/lib/ptxdist/... then in my project space $HOME/project/... etc. I believe at archivicing time everything including ptxdist itself is zipped up and archived on one storage media. But I need to keep all files relating to a package in one place while developing, and living like that for a long time. Since /usr/lib/ptxdist isn't even being backed up normally, only NFS mounts like /home, I then need to move the entire ptxdist into the SCM, which it clearly doesn't like without a lot of hacking, plus, how would I upgrade it? OK this is a bit picky. And perhaps I can fix it all and merge back. Just trying to decide. Linus -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: building Rootfs
2008/7/8 Wolfgang Denk <[EMAIL PROTECTED]>: >> 3. Getting files into the filesystem when the development >> system does not allow root access. > 3. is a non-issue for most common file systems. The only one thing I ever ran into trouble with was device nodes, these cannot be reproduced any way, not even with fakeroot environments, just in scratchbox, which in turn needs you to be root. initramfs etc can handle it with special description files. But if you want to cook up say a .tar file of your rootfs, you're pretty much lost AFAIK. The good thing is that you don't need the device nodes if you have udev, I think the kernel wants /dev/console and a few more at boot but actually it survives just fine without them. The rest is possible to create with fakeroot and clever scripting if I'm not mistaken. If you know some way of sneaking a device node into a .tar file created ENTIRELY running as a regular user, tell me! Linus -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: building Rootfs
OK Robert wrote this on ARM-Linux mailinglist but the discussion belongs on linux-embedded, so I'm moving it there, the suggested ptxdist ML seems inapropriate for the entire embedded community. 2008/7/7 Robert Schwebel <[EMAIL PROTECTED]>: > On Mon, Jul 07, 2008 at 06:01:51PM +0800, Eric Miao wrote: >> or start from buildroot, scratchbox and openembedded as a tool, you've >> really got a lot to learn :-) > > Or ptxdist, or course :-) Robert, can you brief us of how ptxdist fits together with OpenEmbedded? What does these two projects actually share? Where do they do similar things in parallel for example? I'm trying - real hard - to get an idea of how people out there prefer to build their root filesystems in cross-compiled environments. Rob Landley recently wrote up a small blurb on why native compilation is the way to go, and a small roadmap on how he intended to get there using e.g. Qemu and Firmware Linux, c.f: http://www.landley.net/code/firmware/about.html which finally won me over to that line of thinking. Debian and friends obviously go this way now. However, when it comes to the widespread and much fragmented ways of cross-compiling a rootfs, including the stuff put together by MontaVista, WR and all those animals in the forest, obviously based on RPM (build systems I haven't put my hands inside, since they are proprietary) there seems to be very little consensus. ptxdist stands out but do you get a lot of outside contributions for it? As it looks it seems you're running it yourself. (Beware: I haven't looked close.) What else is there out there for rootfs, really? A hack from every embedded company there is? I'm more after what people actually *use* and what is community driven here, not so much opinions on what is best (which will probably be the unwanted side effect of this mail anyway...) Linus -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: modules.dep and depmod.pl
2008/6/14 Matthieu castet <[EMAIL PROTECTED]>: > What's wrong with using your host depmod to build it. > When I build a crosscompilation kernel, and I do make module_install, > modules.dep are generated. Well I do believe that works for you because you're lucky to have a host with a recent kernel and module-init-tools. However I believe that creates an unsound relation between the host depmod and any cross compilation. Currently I try to cross-compile a 2.6.25 kernel on an old good workhorse with a 2.4.x kernel & likewise antique depmod. It just won't work. I tried to cross-compile all module-init-tools with --build=i386, --host=i386, --target=arm-linux, but that still fails: it checks what version of the kernel it's working on, and determines that since that is a 2.4.x version it needs to execute depmod.old instead :-P (Perhaps this is bug?) I'd _really_ prefer cross-compilation to use the cross compiler and in-kernel tools only, and currently I think it is actually only depmod that deviates from that. (OK some scripts may need a recent version of perl or so, that was just discussed in another thread.) Do you think an attempt to patch busybox:s depmod.pl into scripts/ for the benefit of cross-compilation would be frowned upon? Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: modules.dep and depmod.pl
2008/6/14 Dave Hylands <[EMAIL PROTECTED]>: > When we were using 1.01 I think I had to patch the kernel Makefile. I > think I had to undo my patch when we upgraded to the 1.10 version of > busybox. OK I'll see if there is a newer version which is good for this. > You can also run the busybox depmod.pl after you've built the kernel, > but before you make the file system. Yeah that's what I do currently Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html
modules.dep and depmod.pl
Hi, what are other embedded developers experience with using the script "depmod.pl" from BusyBox to create installdir/lib/modules//modules.dep during compile-time? (It's this beast: http://busybox.net/cgi-bin/viewcvs.cgi/trunk/busybox/examples/depmod.pl?rev=20447&view=markup I tried this thing to be able to modprobe off a read-only flash rootfilesystem and it "sort of" works, actually. However there is no way you will pass this to the kernel DEPMOD parameter, I only ever get this to work when doing it after compilation, as a separate step. Is there anyone beside me who would like to see this integrated into scripts/ in the kernel to get some default modules.dep for a read-only rootfs also when doing cross compilation, or am I totally going down the wrong lane here? Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-embedded" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html