Message ID | 200902081037.06645.david-b@pacbell.net (mailing list archive) |
---|---|
State | Awaiting Upstream, archived |
Headers | show |
On Sun, Feb 08, 2009 at 10:37:06AM -0800, David Brownell wrote: > +/* > + * We list regulators here if systems need some level of > + * software control over them after boot. > + */ > +static struct twlreg_info twl4030_regs[] = { > + /* > + TWL_ADJUSTABLE_LDO(VPLL1, 0x2f, 7), > + TWL_ADJUSTABLE_LDO(VPLL2, 0x33, 8), > + */ Minor nit, but I guess the comment would be a bit more accurate if the comment said that the regulators that aren't likely to be changed have been commented out (it required that little extra bit of thinking). > + /* Constrain board-specific capabilities according to what > + * this driver and the chip itself can actually do. > + */ > + c = &initdata->constraints; > + if (!c->min_uV || c->min_uV < min_uV) > + c->min_uV = min_uV; If we're going to do this I think it'd be better to push it into the core and let the regulators pass in a set of constraints so that the behaviour will be consistent between drivers. I'd also expect to have the registration fail or at least issue a warning if the code kicks in since that indicates that the board constraints have been set up incorrectly. There's a reasonable chance that the fixed up constraints will still need to be changed for the board to be configured properly and things may end up being driven out of spec, potentially causing damage. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sunday 08 February 2009, Mark Brown wrote: > > +Â Â Â Â Â /* Constrain board-specific capabilities according to what > > +Â Â Â Â Â * this driver and the chip itself can actually do. > > +Â Â Â Â Â */ > > +Â Â Â Â Â c = &initdata->constraints; > > +Â Â Â Â Â if (!c->min_uV || c->min_uV < min_uV) > > +Â Â Â Â Â Â Â Â Â Â Â Â Â c->min_uV = min_uV; > > If we're going to do this I think it'd be better to push it into the > core and let the regulators pass in a set of constraints so that the > behaviour will be consistent between drivers. Maybe, but there is no such mechanism right yet. When it's created, then this could switch over. > I'd also expect to have the registration fail or at least issue a > warning if the code kicks in since that indicates that the board > constraints have been set up incorrectly. A warning might make sense in some cases ... that's something I would expect to see from the regulator core, though. Example, I see no "max < min" checks triggering registration errors. > There's a reasonable chance > that the fixed up constraints will still need to be changed for the > board to be configured properly and things may end up being driven out > of spec, potentially causing damage. I don't see that happening ... all that code does is tighten existing constraints to match what the hardware can do. The result is just a subset of the range the board already said was OK. If no valid subset exists, that's a board design bug ... albeit one the regulator core could detect. (E.g. those "max < min" checks that don't currently exist.) I can easily imagine having things partially set up, and not really caring whether, on a particular board, those initial constraints are really the most specific ones applicable. One component tolerates a range of 1V8..3V6 maybe, but on any given board it can be hooked up to any supply that's even partially in-range. If I hook such a component up to a supply supporting 1V2 through 2V5, it's really no worry that the 1V2..1V8 part of that range won't be used; or if 2V5..3V6 could also work. Those options really don't matter at all. The only significant part is that only the 1V8..2V5 will be software-accessible on that board. - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, Feb 08, 2009 at 04:04:29PM -0800, David Brownell wrote: > On Sunday 08 February 2009, Mark Brown wrote: > > If we're going to do this I think it'd be better to push it into the > > core and let the regulators pass in a set of constraints so that the > > behaviour will be consistent between drivers. > Maybe, but there is no such mechanism right yet. > When it's created, then this could switch over. Since you appear to be writing the code already... :) > > I'd also expect to have the registration fail or at least issue a > > warning if the code kicks in since that indicates that the board > > constraints have been set up incorrectly. > A warning might make sense in some cases ... that's > something I would expect to see from the regulator > core, though. That's what I'm suggesting should happen - that things like this should be implemented in the core so that the behaviour of the API remains consistent for users moving between platforms and everyone benefits from new features. > Example, I see no "max < min" checks > triggering registration errors. Not a bad idea, though. The core currently doesn't do much checking of the constraints but that's as much because nobody spent the time on it as anything else. To the extent it's a deliberate design decision it's because the constraints and consumer lists are where the information about what's possible on a given system comes from and so the checking that can be done by software is relatively minor. > > There's a reasonable chance > > that the fixed up constraints will still need to be changed for the > > board to be configured properly and things may end up being driven out > > of spec, potentially causing damage. > I don't see that happening ... all that code does is > tighten existing constraints to match what the hardware > can do. The result is just a subset of the range the > board already said was OK. If no valid subset exists, The trouble is that this code should only do anything if the board code provided a configuration that can't be supported by the hardware, which is a bit of a red flag. I'd expect it'd end up catching things like the user typing extra digits by mistake (this has definitely happened when writing consumer drivers). Your current patch does also set constraints for the voltages if they weren't there previously (though this shouldn't matter since voltage setting shouldn't be enabled without voltage value constraints). > I can easily imagine having things partially set up, and > not really caring whether, on a particular board, those > initial constraints are really the most specific ones > applicable. One component tolerates a range of 1V8..3V6 > maybe, but on any given board it can be hooked up to any > supply that's even partially in-range. The pattern you're describing is very much that for consumer and regulator drivers. They should work with as wide a set of constraints as possible to allow them to be used on different systems with different capabilities and needs - allowing this is essential for the API to be usable since so many chips are flexible about the supplies they can use. It's different for the machine constraints since they are by definition specific to a given system. While it's expected that users (especially those sensitive to power consumption) may want to optimise the configuration of their system during development to get the best performance out of it there is also an expectation that users will be making decisions based on knowledge of the hardware design. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Monday 09 February 2009, Mark Brown wrote: > On Sun, Feb 08, 2009 at 04:04:29PM -0800, David Brownell wrote: > > On Sunday 08 February 2009, Mark Brown wrote: > > > > If we're going to do this I think it'd be better to push it into the > > > core and let the regulators pass in a set of constraints so that the > > > behaviour will be consistent between drivers. > > > Maybe, but there is no such mechanism right yet. > > When it's created, then this could switch over. > > Since you appear to be writing the code already... :) Not for the regulator core, though. Switching from a simplistic constraint engine to one that starts to handle a more realistic "union of constraints" model would be doable, but is a bit more off-topic work than I'd want to sign up for just now. > > > I'd also expect to have the registration fail or at least issue a > > > warning if the code kicks in since that indicates that the board > > > constraints have been set up incorrectly. > > > A warning might make sense in some cases ... that's > > something I would expect to see from the regulator > > core, though. > > That's what I'm suggesting should happen - that things like this should > be implemented in the core so that the behaviour of the API remains > consistent for users moving between platforms and everyone benefits from > new features. > > > Example, I see no "max < min" checks > > triggering registration errors. > > Not a bad idea, though. The core currently doesn't do much checking of > the constraints but that's as much because nobody spent the time on it > as anything else. To the extent it's a deliberate design decision it's > because the constraints and consumer lists are where the information > about what's possible on a given system comes from and so the checking > that can be done by software is relatively minor. Or as I put it earlier: the current constraint model is a bit simplistic. Such things can *EASILY* be over-done; starting under-done isn't a bad model. Better to collect a few real examples of how/why "under-done" needs to be improved, than overdesign from the start. (And I've seen some power "constraint" frameworks that seemed way overdone.) > > > There's a reasonable chance > > > that the fixed up constraints will still need to be changed for the > > > board to be configured properly and things may end up being driven out > > > of spec, potentially causing damage. > > > I don't see that happening ... all that code does is > > tighten existing constraints to match what the hardware > > can do. The result is just a subset of the range the > > board already said was OK. If no valid subset exists, > > The trouble is that this code should only do anything if the board code > provided a configuration that can't be supported by the hardware, which > is a bit of a red flag. I'd expect it'd end up catching things like the > user typing extra digits by mistake (this has definitely happened when > writing consumer drivers). The model you're working with doesn't do a good job of component-izing things ... "board" may be "board stack", where notions like "the" hardware are fluid. And in particular, "can't be supported" was NOT an issue in the scenarios I gave. The same mainboard could easily support two regulators with different selections of output voltages. The problem was the model where the constraints from the mainboard would be specific to one regulator, instead of just to the mainboard. > Your current patch does also set constraints for the voltages if they > weren't there previously I was thinking that boards which don't need constraints shouldn't need to create any ... they could just pass on the capabilities of the underlying regulator. > > I can easily imagine having things partially set up, and > > not really caring whether, on a particular board, those > > initial constraints are really the most specific ones > > applicable. One component tolerates a range of 1V8..3V6 > > maybe, but on any given board it can be hooked up to any > > supply that's even partially in-range. > > The pattern you're describing is very much that for consumer and > regulator drivers. They should work with as wide a set of constraints > as possible to allow them to be used on different systems with different > capabilities and needs - allowing this is essential for the API to be > usable since so many chips are flexible about the supplies they can use. > > It's different for the machine constraints since they are by definition > specific to a given system. Only when that "system" is componentized that way. Not all are. Modular systems can have plug-in regulator boards; constraints on a mainboard would necessarily overlap with supported regulator boards ... but the regulators themselves would naturally have different constraints. One way to view this: what you're calling "regulator" constraints are really coming from the "machine". Those few lines of code that seem to bother you are only recognizing that they are, in fact, two very different entities. Without changing the regulator core, the only way to handle contstraints which come from the actual regulators is to force the machine constraints to be in-range with respect to whatever regulator driver ends up using them. - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Feb 09, 2009 at 04:24:01PM -0800, David Brownell wrote: > On Monday 09 February 2009, Mark Brown wrote: > > > Maybe, but there is no such mechanism right yet. > > > When it's created, then this could switch over. > > Since you appear to be writing the code already... :) > Not for the regulator core, though. Switching from > a simplistic constraint engine to one that starts to There's nothing specific to the driver in this code - it's just doing basic comparisons of two sets of constraints and acting on them and would work just as well if it were pushed into the core. You're going to need this in multiple drivers to use it in a system anyway (it'll need to be in at least the drivers which might be used on that system). > handle a more realistic "union of constraints" model > would be doable, but is a bit more off-topic work than > I'd want to sign up for just now. Solving all possible problems is, obviously, a bigger task but I don't think we need to solve everything in order to avoid having this be driver specific. What I would suggest that you do for this is submit a patch allowing the regulators to supply a set of constraints when they register (but not doing anything with them), another with a TWL4030 driver using that API and a third patch making the core do something with that data. This would result in something which maintains consistent behaviour over all regulator drivers, which is my main concern here, and avoids tying up the TWL4030 driver merge with any debate about how to use information about the capabilities of the regulator. I have some regulator API patches I need to test (should be sometime this week) so I may be inspired to do at least the first patch myself. I don't think there's any doubt that the core can do something useful with the information. > The model you're working with doesn't do a good job of > component-izing things ... "board" may be "board stack", > where notions like "the" hardware are fluid. Most of the development work for the regulator API has been done on reference platforms with many pluggable boards (often including the PMIC board) so thought has been given as to how to handle these systems. For daughtercards other than the primary PMIC (which are vastly more common in production systems) one approach has been to represent the daughtercards as a device that gets whatever supplies the daughtercard has. The distribution of power within the daughtercard is then be done by adding child regulators. > > Your current patch does also set constraints for the voltages if they > > weren't there previously > I was thinking that boards which don't need constraints > shouldn't need to create any ... they could just pass on > the capabilities of the underlying regulator. For safety the regulator API won't do anything without being explicitly told that it's OK to do so - if we were to do this we'd need to have an explicit flag in the constraints which says that this is what to do. Constraints are also permission grants. > Only when that "system" is componentized that way. > Not all are. > Modular systems can have plug-in regulator boards; > constraints on a mainboard would necessarily overlap > with supported regulator boards ... but the regulators > themselves would naturally have different constraints. Indeed. Like I say, a very large proportion of the development of the regulator API has been done on reference designs which are built in this fashion, including both pluggable PMIC boards and other daughtercards. Normally the primary PMIC cards are handled with conditional code in the machine file (either compile time or run time) or by registering drivers for all the PMICs and allowing failed device probes to sort everything out. So far handling things this way hasn't been a big deal - there are usually relatively few PMIC boards out there for a given platform and the PMIC itself is rarely a major restriction. This conditional code would normally do the setup that is specific to each PMIC board, including matching the regulators on the PMIC board with the rest of the system and any devices on the PMIC board itself that require supplies. A lot of the time there is a one to many mapping between regulators on the PMIC board and power domains in the base system and there are often additional devices on the PMIC board in addition to the base board. It's not unknown for the contraints applied to not be straight combinations of supply constraints (normally due to a lack of desire for runtime flexibility on supplies). At the end of the day board code is still always going to have to at some point know what regulators are fitted and how they are connected up. There are some things we could do to make handling runtime decisions on this easier, like allowing multiple sets of constraints and supplies to be supplied so the machine drivers can set up the various combinations of supplies more easily when that's possible (which is I think what you were getting at above), but they don't remove the need for board code to know what's there. > One way to view this: what you're calling "regulator" > constraints are really coming from the "machine". Yes, of course. The constraints are applied to the regulator by the core, they are constraints for the regulator not constraints imposed by the regulator. > Those few lines of code that seem to bother you are > only recognizing that they are, in fact, two very > different entities. What's really bothering me is the *location* of the code. As I've said, my primary concern is that this introduces what are effectively API changes which will mean that this driver behaves differently to other drivers. Other concerns about precisely what we do with any information from the regulator driver are very much less important. > Without changing the regulator core, the only way > to handle contstraints which come from the actual > regulators is to force the machine constraints > to be in-range with respect to whatever regulator > driver ends up using them. Modifying the core is, of course, an option. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tuesday 10 February 2009, Mark Brown wrote: > What I would suggest that you do for this is submit a patch allowing the > regulators to supply a set of constraints when they register (but not > doing anything with them), That pretty much needs to allow a list of discrete voltages, not just be a range ... and have a way for clients to retrieve that list. Else I have a very hard time imagining how to plug in MMC supplies without writing the type of regulator-specific code that this framework is intended to supplant. > another with a TWL4030 driver using that API > and a third patch making the core do something with that data. Best IMO to switch the last two around. Effectively there'd be one patch "add new features to regulator core", followed by the first of a set of "implement those new features in the driver for regulator X". And in fact that's what I've done with the two patches I'll be sending in a moment. > This > would result in something which maintains consistent behaviour over all > regulator drivers, It's already consistent, even without such patches!! There is no driver which pays attention to regulator(_dev) constraints that does it any differently than this one. > > > Your current patch does also set constraints for the voltages if they > > > weren't there previously > > > I was thinking that boards which don't need constraints > > shouldn't need to create any ... they could just pass on > > the capabilities of the underlying regulator. > > For safety the regulator API won't do anything without being explicitly > told that it's OK to do so - if we were to do this we'd need to have an > explicit flag in the constraints which says that this is what to do. > Constraints are also permission grants. I like to avoid flags unless they're absolutely required. In this case my initial reaction is to say that hooking up the components in the first place was the permission grant. > > Only when that "system" is componentized that way. > > Not all are. > > > Modular systems can have plug-in regulator boards; > > constraints on a mainboard would necessarily overlap > > with supported regulator boards ... but the regulators > > themselves would naturally have different constraints. > > Indeed. Like I say, a very large proportion of the development of the > regulator API has been done on reference designs which are built in this > fashion, including both pluggable PMIC boards and other daughtercards. That doesn't seem to have escaped its development cage yet. ;) > Normally the primary PMIC cards are handled with conditional code in the > machine file (either compile time or run time) or by registering drivers > for all the PMICs and allowing failed device probes to sort everything > out. So far handling things this way hasn't been a big deal - there are > usually relatively few PMIC boards out there for a given platform and > the PMIC itself is rarely a major restriction. Fair enough. I'd de-emphasize "conditional", since that sounds way too much like #ifdeffing. The source code should just call something like is_pmic_cardX(), and not care how that works. > > One way to view this: what you're calling "regulator" > > constraints are really coming from the "machine". > > Yes, of course. The constraints are applied to the regulator by the > core, they are constraints for the regulator not constraints imposed by > the regulator. Then what would you call constraints by/from the regulator? I suggest updating your terminology. "machine constraints" would be much more clear for what's there now: they relate to the machine. Other constraints (regulator, consumer) relate to the other components ... the ones for which they are an adjective. > > Those few lines of code that seem to bother you are > > only recognizing that they are, in fact, two very > > different entities. > > What's really bothering me is the *location* of the code. As I've said, > my primary concern is that this introduces what are effectively API > changes which will mean that this driver behaves differently to other > drivers. Other concerns about precisely what we do with any information > from the regulator driver are very much less important. I don't mind moving it ... later, after the regulator core has proper support for decoupling machine-specific constraints from regulator-specific ones. I view that code as a workaround for a current limitation of that core, so like all such workarounds it should vanish when it's no longer relevant. - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Feb 23, 2009 at 12:45:44PM -0800, David Brownell wrote: > > another with a TWL4030 driver using that API > > and a third patch making the core do something with that data. > Best IMO to switch the last two around. Effectively > there'd be one patch "add new features to regulator > core", followed by the first of a set of "implement > those new features in the driver for regulator X". > And in fact that's what I've done with the two patches > I'll be sending in a moment. The reason I'm suggesting splitting things up the way I am is that it separates out the TWL4030 driver (which looks very mergable to me right now) from the behaviour changes. Ordering things that way makes it clear what the dependency is. Another way of splitting it out would be to remove the new API from the TWL4030, make that the first patch, then have further patches adding the new API and the TWL4030 code to use it. I don't see any reason why the TWL4030 regulator support needs to be blocked on adding the new API and it makes review easier to keep them separate. > > This > > would result in something which maintains consistent behaviour over all > > regulator drivers, > It's already consistent, even without such patches!! > There is no driver which pays attention to regulator(_dev) > constraints that does it any differently than this one. That's because nobody's doing it at all; once we add a custom implementation in one driver we then need to police each driver individually for consistency with the new interface. If the logic is factored out then that problem doesn't exist and drivers don't need to reimplement any of it. > > > > Your current patch does also set constraints for the voltages if they > > > > weren't there previously > > > I was thinking that boards which don't need constraints > > > shouldn't need to create any ... they could just pass on > > > the capabilities of the underlying regulator. > > For safety the regulator API won't do anything without being explicitly > > told that it's OK to do so - if we were to do this we'd need to have an > > explicit flag in the constraints which says that this is what to do. > > Constraints are also permission grants. > I like to avoid flags unless they're absolutely required. > In this case my initial reaction is to say that hooking up > the components in the first place was the permission grant. The trouble is we don't know what's connected to the regulator without being told - even if some of the components hanging off the supply are visible to software that's no guarantee that all of them are. Keeping the responsibility in the hands of the machine driver helps ensure that users have made a concious decision that their settings are OK for their design. > > Indeed. Like I say, a very large proportion of the development of the > > regulator API has been done on reference designs which are built in this > > fashion, including both pluggable PMIC boards and other daughtercards. > That doesn't seem to have escaped its development cage yet. ;) There's a couple on their way to mainline right now, should make it in the next merge window hopefully. Unfortunately they're for systems that aren't very completely supported in mainline right now which makes them less useful as examples than they might be. There's also none of them where there's any immediate prospect of more than one of the PMIC board options going into mainline. > > Normally the primary PMIC cards are handled with conditional code in the > > machine file (either compile time or run time) or by registering drivers > Fair enough. I'd de-emphasize "conditional", since that sounds > way too much like #ifdeffing. The source code should just call > something like is_pmic_cardX(), and not care how that works. It's normally a combination of the two - normally you don't get any form of board ID readback and you get things like mutually exclusive options for I2C or SPI control due to shared multi function pin setup that can't be autoprobed entirely safely, for example. Once you've decided on the control bus it's normally safe to do autoprobing, though. > Then what would you call constraints by/from the regulator? They're subsumed within the constraints supplied by the machine driver at the minute. > I suggest updating your terminology. "machine constraints" > would be much more clear for what's there now: they relate > to the machine. Other constraints (regulator, consumer) > relate to the other components ... the ones for which they > are an adjective. Yeah, I kind of agree. To avoid confusion from changing the names I'd be tempted to go for something like "regulator driver constraints" but it's not desparately nice. > I don't mind moving it ... later, after the regulator > core has proper support for decoupling machine-specific > constraints from regulator-specific ones. I view that > code as a workaround for a current limitation of that > core, so like all such workarounds it should vanish > when it's no longer relevant. I'd strongly suggest that if you're adding workarounds like this it's worth at least calling them out in the changelog. To be honest I'm not 100% clear why this new feature is essential to supporting the TWL4030 - I can see that it could be useful but I'm not clear on what makes it essential for this driver. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Monday 23 February 2009, Mark Brown wrote: > On Mon, Feb 23, 2009 at 12:45:44PM -0800, David Brownell wrote: > > > > another with a TWL4030 driver using that API > > > and a third patch making the core do something with that data. > > > Best IMO to switch the last two around. Effectively > > there'd be one patch "add new features to regulator > > core", followed by the first of a set of "implement > > those new features in the driver for regulator X". > > > And in fact that's what I've done with the two patches > > I'll be sending in a moment. > > The reason I'm suggesting splitting things up the way I am is that it > separates out the TWL4030 driver (which looks very mergable to me right > now) from the behaviour changes. Ordering things that way makes it > clear what the dependency is. Another way of splitting it out would be > to remove the new API from the TWL4030, make that the first patch, then > have further patches adding the new API and the TWL4030 code to use it. > > I don't see any reason why the TWL4030 regulator support needs to be > blocked on adding the new API and it makes review easier to keep them > separate. I think we're talking past each other. I agree the twl4030 driver is very mergeable right now; that's why it was submitted. You could do so, and then apply the two patches on top ... very clear what the dependency is, and as I understand it the result would be more or less to your liking. My comment was more along the lines of "avoid adding unused hooks, just merge the create-hook and use-hook patches". Having "create" separate from "use" is often troublesome. > > Then what would you call constraints by/from the regulator? > > They're subsumed within the constraints supplied by the machine driver > at the minute. That is, they are not named. :) > > I suggest updating your terminology. "machine constraints" > > would be much more clear for what's there now: they relate > > to the machine. Other constraints (regulator, consumer) > > relate to the other components ... the ones for which they > > are an adjective. > > Yeah, I kind of agree. To avoid confusion from changing the names I'd > be tempted to go for something like "regulator driver constraints" but > it's not desparately nice. Hence my suggestion: {regulator,machine,consumer} constraints, going from bottom up. They aren't driver constraints; they are hardware constraints: regulators can't supply arbitrary voltages. > To be honest I'm not > 100% clear why this new feature is essential to supporting the TWL4030 - > I can see that it could be useful but I'm not clear on what makes it > essential for this driver. I never said it was "essential". However it does simplify the core driver code a lot by moving a lot of error checks to the init code; the checks need to live someplace. You're the one asking for them to be packaged as a new framework feature. - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Feb 23, 2009 at 02:43:16PM -0800, David Brownell wrote: > On Monday 23 February 2009, Mark Brown wrote: > > Yeah, I kind of agree. To avoid confusion from changing the names I'd > > be tempted to go for something like "regulator driver constraints" but > > it's not desparately nice. > Hence my suggestion: {regulator,machine,consumer} constraints, > going from bottom up. They aren't driver constraints; they > are hardware constraints: regulators can't supply arbitrary > voltages. Trouble is that the term regulator gets very overloaded and causes confusion. There's also fun and games to be had with accuracy once you start looking too closely at the discrete voltages. > > To be honest I'm not > > 100% clear why this new feature is essential to supporting the TWL4030 - > > I can see that it could be useful but I'm not clear on what makes it > > essential for this driver. > I never said it was "essential". However it does simplify Apologies, you didn't actually say that, no - I was reading between the lines there. > the core driver code a lot by moving a lot of error checks > to the init code; the checks need to live someplace. You're I'm not sure I see that for the constraint tightening, and indeed the TWL4030 set_voltage() operation does have a range check in it. Unless I'm missing something if the tightened constraint is usable then it should flop out of the range based requests with the constraints left unmodified. The reason the TWL4030 driver still has the range check in the set_voltage() operation is that it is checking to make sure that the requests that come in can be satisfied from the discrete values the regulator is able to produce which is a good thing to do. > the one asking for them to be packaged as a new framework > feature. The change to add voltage range constraints if none were supplied is a noticable policy change from the existing framework standard - it allows machines to enable voltage changes without specifying what the valid values are. I'm not convinced that this is a good idea in the first place and it will result in the opposite behaviour to the current core code (which should end up erroring out in constraint checking at runtime). -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Monday 23 February 2009, Mark Brown wrote: > The change to add voltage range constraints if none were supplied is a > noticable policy change from the existing framework standard - it allows > machines to enable voltage changes without specifying what the valid > values are. "Whatever the hardware handles" *is* a specification. And there's no more assurance it's right than any other specification would be ... except that, as a rule, hardware designers like to avoid assemblies subject to trivial misconfiguration mistakes (like firing up a 2.5V-max rail at 5V). > I'm not convinced that this is a good idea in the first > place and it will result in the opposite behaviour to the current core > code (which should end up erroring out in constraint checking at runtime). Well, if you really dislike it so much, that can easily be removed. Got any comments on the framework patch I sent? I'll take that as the first one, even though it's a different thread. - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Monday 23 February 2009, Mark Brown wrote: > > > Yeah, I kind of agree. Â To avoid confusion from changing the names I'd > > > be tempted to go for something like "regulator driver constraints" but > > > it's not desparately nice. > > > Hence my suggestion: Â {regulator,machine,consumer} constraints, > > going from bottom up. Â They aren't driver constraints; they > > are hardware constraints: Â regulators can't supply arbitrary > > voltages. > > Trouble is that the term regulator gets very overloaded and causes > confusion. That's why one of the *first* jobs in architecture is to ensure the terminology doesn't easily overload ... there's always trouble when it isn't. Despite early groans from peanut galleries about "language lawyering" and "wanting to code in C not English", etc. ;) Thing is, there's already overloading here. Two types of regulator -- "struct regulator_dev" wrapping hardware, and the "struct regulator" is a client/consumer handle. (And thus confusing to me, since it sounds like the more fundamental concept, but instead it's a few layers up.) If you're concerned about overloading terminology, then best to address it sooner than later. I've noticed you using the "consumer", "machine", and "regulator" terms more or less like I suggested, and those make sense; but the current struct names don't encourage that usage. It's possible to adjust usage before changing names in "C". Thankfully, in Linux global name struct changes are not rejected out of hand. > There's also fun and games to be had with accuracy once you > start looking too closely at the discrete voltages. Yes; the patch I sent is explicitly making those available. But I ignored issues like "+/- 3% accurate output" for LDOs (or switchers) ... if anyone really needs to address them, patches will be needed. For now I only care that a 3.1 Volt output can match both MMC_VDD_30_31 and MMC_VDD_31_32! ;) - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, Feb 23, 2009 at 06:03:49PM -0800, David Brownell wrote: > On Monday 23 February 2009, Mark Brown wrote: > > The change to add voltage range constraints if none were supplied is a > > noticable policy change from the existing framework standard - it allows > > machines to enable voltage changes without specifying what the valid > > values are. > "Whatever the hardware handles" *is* a specification. > And there's no more assurance it's right than any > other specification would be ... except that, as a You're right that we can't guarantee that users get everything correct, the goal is more to ensure that some machine specific checks have been done and that the regulator API won't go off by itself and start doing things since it has no idea at all what's supportable. > rule, hardware designers like to avoid assemblies > subject to trivial misconfiguration mistakes (like > firing up a 2.5V-max rail at 5V). The issue is what happens when software starts changing the configuration, for static configurations it doesn't make any difference. > > I'm not convinced that this is a good idea in the first > > place and it will result in the opposite behaviour to the current core > > code (which should end up erroring out in constraint checking at runtime). > Well, if you really dislike it so much, that can > easily be removed. Got any comments on the > framework patch I sent? I'll take that as the > first one, even though it's a different thread. Yes, I wanted to sleep on it. I'll reply at some point today. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, 2009-02-08 at 10:37 -0800, David Brownell wrote: > From: David Brownell <dbrownell@users.sourceforge.net> > > Support most of the LDO regulators in the twl4030 family chips. > In the case of LDOs supporting MMC/SD, the voltage controls are > used; but in most other cases, the regulator framework is only > used to enable/disable a supplies, conserving power when a given > voltage rail is not needed. > > The drivers/mfd/twl4030-core.c code already sets up the various > regulators according to board-specific configuration, and knows > that some chips don't provide the full set of voltage rails. > > The omitted regulators are intended to be under hardware control, > such as during the hardware-mediated system powerup, powerdown, > and suspend states. Unless/until software hooks are known to > be safe, they won't be exported here. > > These regulators implement the new get_status() operation, but > can't realistically implement get_mode(); the status output is > effectively the result of a vote, with the relevant hardware > inputs not exposed. > > Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Applied. Thanks Liam -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
--- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -52,6 +52,13 @@ config REGULATOR_BQ24022 charging select between 100 mA and 500 mA charging current limit. +config REGULATOR_TWL4030 + bool "TI TWL4030/TWL5030/TPS695x0 PMIC" + depends on TWL4030_CORE + help + This driver supports the voltage regulators provided by + this family of companion chips. + config REGULATOR_WM8350 tristate "Wolfson Microelectroncis WM8350 AudioPlus PMIC" depends on MFD_WM8350 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_BQ24022) += bq24022.o +obj-$(CONFIG_REGULATOR_TWL4030) += twl4030-regulator.o obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o --- /dev/null +++ b/drivers/regulator/twl4030-regulator.c @@ -0,0 +1,511 @@ +/* + * twl4030-regulator.c -- support regulators in twl4030 family chips + * + * Copyright (C) 2008 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/i2c/twl4030.h> + + +/* + * The TWL4030/TW5030/TPS659x0 family chips include power management, a + * USB OTG transceiver, an RTC, ADC, PWM, and lots more. Some versions + * include an audio codec, battery charger, and more voltage regulators. + * These chips are often used in OMAP-based systems. + * + * This driver implements software-based resource control for various + * voltage regulators. This is usually augmented with state machine + * based control. + */ + +struct twlreg_info { + /* start of regulator's PM_RECEIVER control register bank */ + u8 base; + + /* twl4030 resource ID, for resource control state machine */ + u8 id; + + /* voltage in mV = table[VSEL]; table_len must be a power-of-two */ + u8 table_len; + const u16 *table; + + /* chip constraints on regulator behavior */ + u16 min_mV; + u16 max_mV; + + /* used by regulator core */ + struct regulator_desc desc; +}; + + +/* LDO control registers ... offset is from the base of its register bank. + * The first three registers of all power resource banks help hardware to + * manage the various resource groups. + */ +#define VREG_GRP 0 +#define VREG_TYPE 1 +#define VREG_REMAP 2 +#define VREG_DEDICATED 3 /* LDO control */ + + +static inline int +twl4030reg_read(struct twlreg_info *info, unsigned offset) +{ + u8 value; + int status; + + status = twl4030_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, + &value, info->base + offset); + return (status < 0) ? status : value; +} + +static inline int +twl4030reg_write(struct twlreg_info *info, unsigned offset, u8 value) +{ + return twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + value, info->base + offset); +} + +/*----------------------------------------------------------------------*/ + +/* generic power resource operations, which work on all regulators */ + +static int twl4030reg_grp(struct regulator_dev *rdev) +{ + return twl4030reg_read(rdev_get_drvdata(rdev), VREG_GRP); +} + +/* + * Enable/disable regulators by joining/leaving the P1 (processor) group. + * We assume nobody else is updating the DEV_GRP registers. + */ + +#define P3_GRP BIT(7) /* "peripherals" */ +#define P2_GRP BIT(6) /* secondary processor, modem, etc */ +#define P1_GRP BIT(5) /* CPU/Linux */ + +static int twl4030reg_is_enabled(struct regulator_dev *rdev) +{ + int state = twl4030reg_grp(rdev); + + if (state < 0) + return state; + + return (state & P1_GRP) != 0; +} + +static int twl4030reg_enable(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int grp; + + grp = twl4030reg_read(info, VREG_GRP); + if (grp < 0) + return grp; + + grp |= P1_GRP; + return twl4030reg_write(info, VREG_GRP, grp); +} + +static int twl4030reg_disable(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int grp; + + grp = twl4030reg_read(info, VREG_GRP); + if (grp < 0) + return grp; + + grp &= ~P1_GRP; + return twl4030reg_write(info, VREG_GRP, grp); +} + +static int twl4030reg_get_status(struct regulator_dev *rdev) +{ + int state = twl4030reg_grp(rdev); + + if (state < 0) + return state; + state &= 0x0f; + + /* assume state != WARM_RESET; we'd not be running... */ + if (!state) + return REGULATOR_STATUS_OFF; + return (state & BIT(3)) + ? REGULATOR_STATUS_NORMAL + : REGULATOR_STATUS_STANDBY; +} + +static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + unsigned message; + int status; + + /* We can only set the mode through state machine commands... */ + switch (mode) { + case REGULATOR_MODE_NORMAL: + message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_ACTIVE); + break; + case REGULATOR_MODE_STANDBY: + message = MSG_SINGULAR(DEV_GRP_P1, info->id, RES_STATE_SLEEP); + break; + default: + return -EINVAL; + } + + /* Ensure the resource is associated with some group */ + status = twl4030reg_grp(rdev); + if (status < 0) + return status; + if (!(status & (P3_GRP | P2_GRP | P1_GRP))) + return -EACCES; + + status = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, + message >> 8, 0x15 /* PB_WORD_MSB */ ); + if (status >= 0) + return status; + + return twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, + message, 0x16 /* PB_WORD_LSB */ ); +} + +/*----------------------------------------------------------------------*/ + +/* + * Support for adjustable-voltage LDOs uses a four bit (or less) voltage + * select field in its control register. We use tables indexed by VSEL + * to record voltages in milliVolts. (Accuracy is about three percent.) + * + * Note that VSEL values for VAUX2 changed in twl5030 and newer silicon; + * currently handled by listing two slightly different VAUX2 regulators, + * only one of which will be configured. + * + * VSEL values documented as "TI cannot support these values" are flagged + * in these tables as UNSUP() values; we normally won't assign them. + */ +#ifdef CONFIG_TWL4030_ALLOW_UNSUPPORTED +#define UNSUP_MASK 0x0000 +#else +#define UNSUP_MASK 0x8000 +#endif + +#define UNSUP(x) (UNSUP_MASK | (x)) +#define IS_UNSUP(x) (UNSUP_MASK & (x)) +#define LDO_MV(x) (~UNSUP_MASK & (x)) + + +static const u16 VAUX1_VSEL_table[] = { + UNSUP(1500), UNSUP(1800), 2500, 2800, + 3000, 3000, 3000, 3000, +}; +static const u16 VAUX2_4030_VSEL_table[] = { + UNSUP(1000), UNSUP(1000), UNSUP(1200), 1300, + 1500, 1800, UNSUP(1850), 2500, + UNSUP(2600), 2800, UNSUP(2850), UNSUP(3000), + UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150), +}; +static const u16 VAUX2_VSEL_table[] = { + 1700, 1700, 1900, 1300, + 1500, 1800, 2000, 2500, + 2100, 2800, 2200, 2300, + 2400, 2400, 2400, 2400, +}; +static const u16 VAUX3_VSEL_table[] = { + 1500, 1800, 2500, 2800, + UNSUP(3000), UNSUP(3000), UNSUP(3000), UNSUP(3000), +}; +static const u16 VAUX4_VSEL_table[] = { + 700, 1000, 1200, UNSUP(1300), + 1500, 1800, UNSUP(1850), 2500, +}; +static const u16 VMMC1_VSEL_table[] = { + 1850, 2850, 3000, 3150, +}; +static const u16 VMMC2_VSEL_table[] = { + UNSUP(1000), UNSUP(1000), UNSUP(1200), UNSUP(1300), + UNSUP(1500), UNSUP(1800), 1850, UNSUP(2500), + 2600, 2800, 2850, 3000, + 3150, 3150, 3150, 3150, +}; +static const u16 VPLL1_VSEL_table[] = { + 1000, 1200, 1300, 1800, + UNSUP(2800), UNSUP(3000), UNSUP(3000), UNSUP(3000), +}; +static const u16 VPLL2_VSEL_table[] = { + 700, 1000, 1200, 1300, + UNSUP(1500), 1800, UNSUP(1850), UNSUP(2500), + UNSUP(2600), UNSUP(2800), UNSUP(2850), UNSUP(3000), + UNSUP(3150), UNSUP(3150), UNSUP(3150), UNSUP(3150), +}; +static const u16 VSIM_VSEL_table[] = { + UNSUP(1000), UNSUP(1200), UNSUP(1300), 1800, + 2800, 3000, 3000, 3000, +}; +static const u16 VDAC_VSEL_table[] = { + 1200, 1300, 1800, 1800, +}; + + +static int +twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel; + + for (vsel = 0; vsel < info->table_len; vsel++) { + int mV = info->table[vsel]; + int uV; + + if (IS_UNSUP(mV)) + continue; + uV = LDO_MV(mV) * 1000; + + /* use the first in-range value */ + if (min_uV <= uV && uV <= max_uV) + return twl4030reg_write(info, VREG_DEDICATED, vsel); + } + + return -EDOM; +} + +static int twl4030ldo_get_voltage(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + int vsel = twl4030reg_read(info, VREG_DEDICATED); + + if (vsel < 0) + return vsel; + + vsel &= info->table_len - 1; + return LDO_MV(info->table[vsel]) * 1000; +} + +static struct regulator_ops twl4030ldo_ops = { + .set_voltage = twl4030ldo_set_voltage, + .get_voltage = twl4030ldo_get_voltage, + + .enable = twl4030reg_enable, + .disable = twl4030reg_disable, + .is_enabled = twl4030reg_is_enabled, + + .set_mode = twl4030reg_set_mode, + + .get_status = twl4030reg_get_status, +}; + +/*----------------------------------------------------------------------*/ + +/* + * Fixed voltage LDOs don't have a VSEL field to update. + */ +static int twl4030fixed_get_voltage(struct regulator_dev *rdev) +{ + struct twlreg_info *info = rdev_get_drvdata(rdev); + + return info->min_mV * 1000; +} + +static struct regulator_ops twl4030fixed_ops = { + .get_voltage = twl4030fixed_get_voltage, + + .enable = twl4030reg_enable, + .disable = twl4030reg_disable, + .is_enabled = twl4030reg_is_enabled, + + .set_mode = twl4030reg_set_mode, + + .get_status = twl4030reg_get_status, +}; + +/*----------------------------------------------------------------------*/ + +#define TWL_ADJUSTABLE_LDO(label, offset, num) { \ + .base = offset, \ + .id = num, \ + .table_len = ARRAY_SIZE(label##_VSEL_table), \ + .table = label##_VSEL_table, \ + .desc = { \ + .name = #label, \ + .id = TWL4030_REG_##label, \ + .ops = &twl4030ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ + } + +#define TWL_FIXED_LDO(label, offset, mVolts, num) { \ + .base = offset, \ + .id = num, \ + .min_mV = mVolts, \ + .max_mV = mVolts, \ + .desc = { \ + .name = #label, \ + .id = TWL4030_REG_##label, \ + .ops = &twl4030fixed_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + }, \ + } + +/* + * We list regulators here if systems need some level of + * software control over them after boot. + */ +static struct twlreg_info twl4030_regs[] = { + TWL_ADJUSTABLE_LDO(VAUX1, 0x17, 1), + TWL_ADJUSTABLE_LDO(VAUX2_4030, 0x1b, 2), + TWL_ADJUSTABLE_LDO(VAUX2, 0x1b, 2), + TWL_ADJUSTABLE_LDO(VAUX3, 0x1f, 3), + TWL_ADJUSTABLE_LDO(VAUX4, 0x23, 4), + TWL_ADJUSTABLE_LDO(VMMC1, 0x27, 5), + TWL_ADJUSTABLE_LDO(VMMC2, 0x2b, 6), + /* + TWL_ADJUSTABLE_LDO(VPLL1, 0x2f, 7), + TWL_ADJUSTABLE_LDO(VPLL2, 0x33, 8), + */ + TWL_ADJUSTABLE_LDO(VSIM, 0x37, 9), + TWL_ADJUSTABLE_LDO(VDAC, 0x3b, 10), + /* + TWL_ADJUSTABLE_LDO(VINTANA1, 0x3f, 11), + TWL_ADJUSTABLE_LDO(VINTANA2, 0x43, 12), + TWL_ADJUSTABLE_LDO(VINTDIG, 0x47, 13), + TWL_SMPS(VIO, 0x4b, 14), + TWL_SMPS(VDD1, 0x55, 15), + TWL_SMPS(VDD2, 0x63, 16), + */ + TWL_FIXED_LDO(VUSB1V5, 0x71, 1500, 17), + TWL_FIXED_LDO(VUSB1V8, 0x74, 1800, 18), + TWL_FIXED_LDO(VUSB3V1, 0x77, 3100, 19), + /* VUSBCP is managed *only* by the USB subchip */ +}; + +static int twl4030reg_probe(struct platform_device *pdev) +{ + int i; + struct twlreg_info *info; + struct regulator_init_data *initdata; + struct regulation_constraints *c; + struct regulator_dev *rdev; + int min_uV, max_uV; + + for (i = 0, info = NULL; i < ARRAY_SIZE(twl4030_regs); i++) { + if (twl4030_regs[i].desc.id != pdev->id) + continue; + info = twl4030_regs + i; + min_uV = info->min_mV * 1000; + max_uV = info->max_mV * 1000; + break; + } + if (!info) + return -ENODEV; + + initdata = pdev->dev.platform_data; + if (!initdata) + return -EINVAL; + + /* Constrain board-specific capabilities according to what + * this driver and the chip itself can actually do. + */ + c = &initdata->constraints; + if (!c->min_uV || c->min_uV < min_uV) + c->min_uV = min_uV; + if (!c->max_uV || c->max_uV > max_uV) + c->max_uV = max_uV; + c->valid_modes_mask &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY; + c->valid_ops_mask &= REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS; + + rdev = regulator_register(&info->desc, &pdev->dev, info); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "can't register %s, %ld\n", + info->desc.name, PTR_ERR(rdev)); + return PTR_ERR(rdev); + } + platform_set_drvdata(pdev, rdev); + + /* NOTE: many regulators support short-circuit IRQs (presentable + * as REGULATOR_OVER_CURRENT notifications?) configured via: + * - SC_CONFIG + * - SC_DETECT1 (vintana2, vmmc1/2, vaux1/2/3/4) + * - SC_DETECT2 (vusb, vdac, vio, vdd1/2, vpll2) + * - IT_CONFIG + */ + + return 0; +} + +static int __devexit twl4030reg_remove(struct platform_device *pdev) +{ + regulator_unregister(platform_get_drvdata(pdev)); + return 0; +} + +MODULE_ALIAS("platform:twl4030_reg"); + +static struct platform_driver twl4030reg_driver = { + .probe = twl4030reg_probe, + .remove = __devexit_p(twl4030reg_remove), + /* NOTE: short name, to work around driver model truncation of + * "twl4030_regulator.12" (and friends) to "twl4030_regulator.1". + */ + .driver.name = "twl4030_reg", + .driver.owner = THIS_MODULE, +}; + +static int __init twl4030reg_init(void) +{ + unsigned i, j; + + /* determine min/max voltage constraints, taking into account + * whether set_voltage() will use the "unsupported" settings + */ + for (i = 0; i < ARRAY_SIZE(twl4030_regs); i++) { + struct twlreg_info *info = twl4030_regs + i; + const u16 *table; + + /* fixed-voltage regulators */ + if (!info->table_len) + continue; + + /* LDO regulators: */ + for (j = 0, table = info->table; + j < info->table_len; + j++, table++) { + u16 mV = *table; + + if (IS_UNSUP(mV)) + continue; + mV = LDO_MV(mV); + + if (info->min_mV == 0 || info->min_mV > mV) + info->min_mV = mV; + if (info->max_mV < mV) + info->max_mV = mV; + } + } + + return platform_driver_register(&twl4030reg_driver); +} +subsys_initcall(twl4030reg_init); + +static void __exit twl4030reg_exit(void) +{ + platform_driver_unregister(&twl4030reg_driver); +} +module_exit(twl4030reg_exit) + +MODULE_DESCRIPTION("TWL4030 regulator driver"); +MODULE_LICENSE("GPL"); --- a/include/linux/i2c/twl4030.h +++ b/include/linux/i2c/twl4030.h @@ -218,6 +218,53 @@ int twl4030_i2c_read(u8 mod_no, u8 *valu /*----------------------------------------------------------------------*/ +/* Power bus message definitions */ + +#define DEV_GRP_NULL 0x0 +#define DEV_GRP_P1 0x1 +#define DEV_GRP_P2 0x2 +#define DEV_GRP_P3 0x4 + +#define RES_GRP_RES 0x0 +#define RES_GRP_PP 0x1 +#define RES_GRP_RC 0x2 +#define RES_GRP_PP_RC 0x3 +#define RES_GRP_PR 0x4 +#define RES_GRP_PP_PR 0x5 +#define RES_GRP_RC_PR 0x6 +#define RES_GRP_ALL 0x7 + +#define RES_TYPE2_R0 0x0 + +#define RES_TYPE_ALL 0x7 + +#define RES_STATE_WRST 0xF +#define RES_STATE_ACTIVE 0xE +#define RES_STATE_SLEEP 0x8 +#define RES_STATE_OFF 0x0 + +/* + * Power Bus Message Format ... these can be sent individually by Linux, + * but are usually part of downloaded scripts that are run when various + * power events are triggered. + * + * Broadcast Message (16 Bits): + * DEV_GRP[15:13] MT[12] RES_GRP[11:9] RES_TYPE2[8:7] RES_TYPE[6:4] + * RES_STATE[3:0] + * + * Singular Message (16 Bits): + * DEV_GRP[15:13] MT[12] RES_ID[11:4] RES_STATE[3:0] + */ + +#define MSG_BROADCAST(devgrp, grp, type, type2, state) \ + ( (devgrp) << 13 | 1 << 12 | (grp) << 9 | (type2) << 7 \ + | (type) << 4 | (state)) + +#define MSG_SINGULAR(devgrp, id, state) \ + ((devgrp) << 13 | 0 << 12 | (id) << 4 | (state)) + +/*----------------------------------------------------------------------*/ + struct twl4030_bci_platform_data { int *battery_tmp_tbl; unsigned int tblsize;