N900 USB fix (Was: Re: [PATCH/RFC 2/6] OMAP2+: PM: move runtime PM implementation to use device power domains)
Kevin Hilman wrote: > Sakari Ailus writes: > >> Hi Kevin and Felipe, >> >> Kevin Hilman wrote: >>> In commit 7538e3db6e015e890825fbd9f8659952896ddd5b (PM: add support >>> for device power domains) a better way for handling platform-specific >>> power hooks was introduced. >>> >>> Rather than using the platform_bus dev_pm_ops overrides >>> (platform_bus_set_pm_ops()), this patch moves the OMAP runtime PM >>> implementation over to using device power domains. >>> >>> Since OMAP is the only user of platform_bus_set_pm_ops(), that >>> interface can be removed (and will be in a forthcoming patch.) >> >> I have little doubt of the correctness of the patch itself, but it >> actually does break the USB on N900. I don't know PM so well that I >> would have a good idea what might be going wrong here, so I'm not >> certain that this is specific to the N900 either. >> >> It looks strange to me also but I've tested it several times so I'm >> fairly certain that the culprit is this very patch. :-) > > You're correct, it's broken. > > A fix has been posted (and pull req sent to Tony.) Can you try my > for_3.0/pm-fixes branch which fixes this problem? It's available in my > git tree: > > git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git Hi, Kevin! Many thanks to you! :-) The patches indeed fix the problem. I seem to have used for_3.0/pm-fixes-2 branch, though. I guess that doesn't really matter. :-) Cheers, -- Sakari Ailus sakari.ai...@maxwell.research.nokia.com -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2 20/28] OMAP: DSS2: Use PM runtime & HWMOD support
On Fri, 2011-06-10 at 05:03 +0900, Paul Mundt wrote: > On Thu, Jun 09, 2011 at 04:56:42PM +0300, Tomi Valkeinen wrote: > > +int dispc_runtime_get(void) > > +{ > > + int r; > > + > > + DSSDBG("dispc_runtime_get\n"); > > + > > + r = pm_runtime_get_sync(&dispc.pdev->dev); > > + WARN_ON(r < 0); > > + return r < 0 ? r : 0; > > +} > > + > > +void dispc_runtime_put(void) > > +{ > > + int r; > > + > > + DSSDBG("dispc_runtime_put\n"); > > + > > + r = pm_runtime_put(&dispc.pdev->dev); > > + WARN_ON(r < 0); > > } > > > This seems a bit odd. Your runtime_get wrapper is explicitly synchronous > while your put wrapper is explicitly asynchronous, although these details > (if intentional) are not at all obvious from the wrapper naming. From Yes, the naming could be improved to make the (a)synchronousness obvious to the caller. The functions are internal to DSS, but still. > the use in the error paths and so on you will definitely need to be using > pm_runtime_put_sync() at least some of the time. Hmm, why is that? When the user of, say, dispc, has finished with it and calls dispc_runtime_put(), the caller shouldn't care if the HW is actually turned off now or later. pm_runtime_put() can return an error value, but my wrappers discard it, as I don't know in which situations it could happen, and what could the driver do about it. If the HW cannot be turned off now, why could it be turned off later, and when would that be? > In the interest of avoiding confusion, I would in general just get rid of > these wrappers and use the pm_runtime calls openly, as you already do for > some of the other parts of the API. The runtime PM framework has pretty > verbose debugging already that goes well beyond what you presently have, > too. Yes, my main reason for the wrapper is to hide the device pointer from the users. So when, say, DSI block needs to use DISPC, it can just call dispc_runtime_get(), instead of having a mechanism to get the dispc device (dispc_get_dev() perhaps), and then using pm_runtime directly. Not a big difference, but I'd like to keep the dispc device pointer internal to dispc, as there's no real need to access it directly from elsewhere. Some of the wrappers are actually private to the file already, like for dsi. These wrappers could be removed without exposing any device pointers, but having them keeps the pattern consistent in all parts of the dss. And it allows me to have the WARN_ONs there easily. > You seem to have adopted this sync/async pattern for all of the users: Yes, I think the pattern is similar all around: when you get the device, you want it to be up and running immediately. When you put the device, you don't care when it's actually disabled. Tomi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] dmaengine: add new api for preparing simple slave transfer
On Thu, 2011-06-09 at 17:32 +0100, Russell King - ARM Linux wrote: > On Thu, Jun 09, 2011 at 09:31:56PM +0530, Raju, Sundaram wrote: > > Here it is, with proper line wrapping; > > Thanks. This is much easier to reply to. > > > I believe that even though the dmaengine framework addresses and > > supports most of the required use cases of a client driver to a DMA > > controller, some extensions are required in it to make it still more > > generic. > > > > Current framework contains two APIs to prepare for slave transfers: > > > > struct dma_async_tx_descriptor *(*device_prep_slave_sg)( > > struct dma_chan *chan, struct scatterlist *sgl, > > unsigned int sg_len, enum dma_data_direction direction, > > unsigned long flags); > > > > struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( > > struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, > > size_t period_len, enum dma_data_direction direction); > > > > and one control API. > > int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, > > unsigned long arg); > > > > A simple single buffer transfer (i.e. non sg transfer) can be done only > > as a trivial case of the device_prep_slave_sg API. The client driver is > > expected to prepare a sg list and provide to the dmaengine API for that > > single buffer also. > > We can avoid preparing a sg list in every driver which wants this by > having dmaengine.h provide a helper for this case: > > static inline dma_async_tx_descriptor *dmaengine_prep_slave_single( > struct dma_chan *chan, void *buf, size_t len, > enum dma_data_direction dir, unsigned long flags) > { > struct scatterlist sg; > > sg_init_one(&sg, buf, len); > > return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); > } That sounds good... > > I think also providing dmaengine_prep_slave_sg() and > dmaengine_prep_dma_cyclic() as wrappers to hide the chan->device->blah > bit would also be beneficial (and helps keep that detail out of the > users of DMA engine.) > > > In a slave transfer, the client has to define all the buffer related > > attributes and the peripheral related attributes. > > I'd argue that it is incorrect to have drivers specify the buffer > related attributes - that makes the API unnecessarily complicated > to use, requiring two calls (one to configure the channel, and one > to prepare the transfer) each time it needs to be used. > > Not only that but the memory side of the transfer should be no business > of the driver - the driver itself should only specify the attributes > for the device being driven. The attributes for the memory side of the > transfer should be a property of the DMA engine itself. > > I would like to see in the long term the dma_slave_config structure > lose its 'direction' argument, and the rest of the parameters used to > define the device side parameters only. I am not sure why direction flag is required and can be done away with. Both sg and cyclic API have a direction parameter and that should be used. A channel can be used in any direction client wishes to. > > This will allow the channel to be configured once when its requested, > and then the prepare call can configure the direction as required. > > > Now coming to the buffer related attributes, sg list is a nice way to > > represent a disjoint buffer; all the offload engines in drivers/dma > > create a descriptor for each of the contiguous chunk in the sg list > > buffer and pass it to the controller. > > The sg list is the standard Linux way to describe scattered buffers. > > > But many a times a client may want to transfer from a single buffer to > > the peripheral and most of the DMA controllers have the capability to > > transfer data in chunks/frames directly at a stretch. > > So far, I've only seen DMA controllers which operate on a linked list of > source, destination, length, attributes, and next entry pointer. > > > All the attributes of a buffer, which are required for the transfer > > can be programmed in single descriptor and submitted to the > > DMA controller. > > I'm not sure that this is useful - in order to make use of the data, the > data would have to be copied in between the descriptors - and doesn't that > rather negate the point of DMA if you have to memcpy() the data around? > > Isn't it far more efficient to have DMA place the data exactly where it's > required in memory right from the start without any memcpy() operations? > > Can you explain where and how you would use something like this: > > > --- > > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame 0 > > --- > > | Inter Frame Gap | > > --- > > | Chunk 0 |ICG| Chunk 1 |ICG
RE: [RFC] dmaengine: add new api for preparing simple slave transfer
On Thu, 2011-06-09 at 21:31 +0530, Raju, Sundaram wrote: > Here it is, with proper line wrapping; Please cc the respective MAINTAINERS, added Dan... > > SDMA and EDMA are TI SoC specific DMA controllers. Their drivers have > been maintained in the respective SoC folders till now. > arch/arm/plat-omap/dma.c > arch/arm/mach-davinci/dma.c > > I have gone through the existing offload engine (DMA) drivers in > drivers/dma which do slave transfers. > I would like to move SDMA and EDMA also to dmaengine framework. > > I believe that even though the dmaengine framework addresses and > supports most of the required use cases of a client driver to a DMA > controller, some extensions are required in it to make it still more > generic. > > Current framework contains two APIs to prepare for slave transfers: > > struct dma_async_tx_descriptor *(*device_prep_slave_sg)( > struct dma_chan *chan, struct scatterlist *sgl, > unsigned int sg_len, enum dma_data_direction direction, > unsigned long flags); > > struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( > struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, > size_t period_len, enum dma_data_direction direction); > > and one control API. > int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, > unsigned long arg); > > A simple single buffer transfer (i.e. non sg transfer) can be done only > as a trivial case of the device_prep_slave_sg API. The client driver is > expected to prepare a sg list and provide to the dmaengine API for that > single buffer also. > > In a slave transfer, the client has to define all the buffer related > attributes and the peripheral related attributes. > > The above 2 APIs in the dmaengine framework expect all the > peripheral/slave related attributes to be filled in the > dma_slave_config data structure. > struct dma_slave_config { > enum dma_data_direction direction; > dma_addr_t src_addr; > dma_addr_t dst_addr; > enum dma_slave_buswidth src_addr_width; > enum dma_slave_buswidth dst_addr_width; > u32 src_maxburst; > u32 dst_maxburst; > }; > > This data structure is passed to the offload engine via the dma_chan > data structure in its private pointer. No, this is passed thru control API you described above. Please read Documentation/dmaengine.txt > Now coming to the buffer related attributes, sg list is a nice way to > represent a disjoint buffer; all the offload engines in drivers/dma > create a descriptor for each of the contiguous chunk in the sg list > buffer and pass it to the controller. > > But many a times a client may want to transfer from a single buffer to > the peripheral and most of the DMA controllers have the capability to > transfer data in chunks/frames directly at a stretch. > All the attributes of a buffer, which are required for the transfer > can be programmed in single descriptor and submitted to the > DMA controller. > > So I think the slave transfer API must also have a provision to pass > the buffer configuration. The buffer attributes have to be passed > directly as an argument in the prepare API, unlike dma_slave_config > as they will be different for each buffer that is going to be > transferred. Can you articulate what attributes you are talking about. The dma_slave_config parameters don't represent buffer attributes. They represent the dma attributes on how you want to transfer. These things like bus widths, burst lengths are usually constant for the slave transfers, not sure why they should change per buffer? > > It is a stretch and impractical to use a highly segmented buffer (like > the one described below) in a sglist. This is because sg list itself > is a representation of a disjoint buffer collection in terms of > smaller buffers. Now then each of these smaller buffers can have > different buffer configurations (like described below) and we are not > going to go down that road now. well thats the linux idea, you use sg-list to describe this segmentation... > > Hence it makes sense to pass these buffer attributes for only a single > buffer transfer and not a sg list. > This can be done by OPTION #1 > 1. Adding a pointer of the dma_buffer_config data structure in the > device_prep_slave_sg API. > 2. Ensuring that it will be ignored if a sg list passed. > Only when a single buffer is passed (in the sg list) then this buffer > configuration will be used. > 3. Any client that wants to do a sg transfer can simply ignore this > buffer configuration and pass NULL. > The main disadvantage of this option is that all the existing drivers > need to be updated since the API signature is changed. > > It might even be better to have a separate API for non sg transfers. > This is OPTION #2 > Advantages of this option are > 1. No change required in the existing drivers that use > device_prep_slave_sg
Re: [PATCH v3 06/12] MFD: twl4030-codec -> twl4030-audio: Rename the driver
On Thursday 09 June 2011 22:37:28 Arnd Bergmann wrote: > Better use the -M flag to git-format-patch when moving files, to make it > obvious what has or has not changed, and to reduce the size of the email. I tend to forgot the -M flag, thanks. > Also, shouldn't this file go into the sound/soc/ directory? It seems that > this is really the device driver, not part of the multi-function layer. This driver is the MFD core part for the audio block within the twl4030 series pmic. We have the slave drivers under sound/soc/codecs/twl4030.c and drivers/input/misc/twl4030-vibra.c. The audio block has codec, and vibra functionality, and we need to have this driver to properly manage this block within twl. -- Péter -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
beagleboard xm alsa in mcbsp3. 2.6.39-rc4
Hi, I have mcbsp1 working on an external codec. I moved the wires to the mcbsp3 pins. The codec is master, using tdm mode. I use the same codec i2s bus, and it gets the same setup (I change the dai-link stuff in my alsa machine driver to use the other omap i2s bus for my tests). If I pull the clk wire off the beagleboard pin, the clock from the codec looks good. With the wire attached to the pin, I don't see the pin wiggling. So it looks like maybe the pin is an output or something. The frame clock looks ok while connected. In the board-omap3beagle.c I configure all 3 mcbsp the same way: #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { #if 1 /* McBSP 1 slave */ OMAP3_MUX(MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP1_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP1_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), #else /* McBSP 1 master */ OMAP3_MUX(MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), OMAP3_MUX(MCBSP1_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP1_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), #endif #if 1 /* McBSP 2 slave */ OMAP3_MUX(MCBSP2_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP2_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP2_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP2_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), #else /* McBSP 2 master */ OMAP3_MUX(MCBSP2_FSX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), OMAP3_MUX(MCBSP2_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), OMAP3_MUX(MCBSP2_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP2_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), #endif #if 1 /* McBSP 3 slave */ OMAP3_MUX(MCBSP3_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP3_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP3_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP3_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), #else /* McBSP 3 master */ OMAP3_MUX(MCBSP3_FSX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), OMAP3_MUX(MCBSP3_CLKX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), OMAP3_MUX(MCBSP3_DR, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), OMAP3_MUX(MCBSP3_DX, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT), #endif { .reg_offset = OMAP_MUX_TERMINATOR }, }; #endif So far I have not been able to get the codec mastered bit clock to work on either mcbsp2 or msbsp3. I have been trying to follow the logic in mcbsp.c and in omap-mcbsp.c in how things get inited. I suspect there is something I have not done? Any ideas. Thanks, Steve -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/8] OMAP2+: PM: idle clkdms only if already in idle
On Thu, Jun 09, 2011 at 04:24:09PM +0530, Rajendra Nayak wrote: > The omap_set_pwrdm_state function forces clockdomains > to idle, without checking the existing idle state > programmed, instead based solely on the HW capability > of the clockdomain to support idle. > This is wrong and the clockdomains should be idled > post a state_switch *only* if idle transitions on the > clockdomain were already enabled. > > Signed-off-by: Rajendra Nayak > --- > arch/arm/mach-omap2/pm.c |4 +++- > 1 files changed, 3 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c > index d48813f..840b0e1 100644 > --- a/arch/arm/mach-omap2/pm.c > +++ b/arch/arm/mach-omap2/pm.c > @@ -108,6 +108,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 > state) > u32 cur_state; > int sleep_switch = -1; > int ret = 0; > + int hwsup = 0; > > if (pwrdm == NULL || IS_ERR(pwrdm)) > return -EINVAL; > @@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 > state) > (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { > sleep_switch = LOWPOWERSTATE_SWITCH; > } else { > + hwsup = clkdm_is_idle(pwrdm->pwrdm_clkdms[0]); > clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); > pwrdm_wait_transition(pwrdm); > sleep_switch = FORCEWAKEUP_SWITCH; > @@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 > state) > > switch (sleep_switch) { > case FORCEWAKEUP_SWITCH: > - if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) > + if (hwsup) > clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); > else > clkdm_sleep(pwrdm->pwrdm_clkdms[0]); Is concurrency protection needed here? Not sure if it's expected that multiple threads would simultaneously manage the state of the same power domain, or that the associated clock domain would change state concurrently. Todd > 1.7.0.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe linux-omap" 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/8] OMAP2+: clockdomain: Add an api to read idle mode
On Thu, Jun 09, 2011 at 04:24:06PM +0530, Rajendra Nayak wrote: > Add a clockdomain api to check if hardware supervised > idle transitions are enabled on a clockdomain. > ... > + * clkdm_is_idle - Check if the clkdm hwsup/autoidle is enabled A minor suggestion on naming: "clkdm_allows_idle" seems more accurate and a natural complement to the existing clkdm_allow_idle(). Todd -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] arm: omap: mark dt_compat __initconst
we have a special section for const data which is only needed during init, that's __initconst. Use that instead of __initdata which is for non-const data. Signed-off-by: Felipe Balbi --- This patch is against devel-devicetree branch from linux-omap. arch/arm/mach-omap2/board-igep0020.c|2 +- arch/arm/mach-omap2/board-igep0030.c|2 +- arch/arm/mach-omap2/board-omap3beagle.c |2 +- arch/arm/mach-omap2/board-omap4panda.c |2 +- arch/arm/mach-omap2/board-overo.c |2 +- arch/arm/mach-omap2/board-zoom.c|2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index eb198a6..d9888eb 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c @@ -703,7 +703,7 @@ static void __init igep2_init(void) } -static const char *igep2_dt_compat[] __initdata = { +static const char *igep2_dt_compat[] __initconst = { "ISEE,igep-v2", NULL }; diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c index e13fdf0..984e4a1 100644 --- a/arch/arm/mach-omap2/board-igep0030.c +++ b/arch/arm/mach-omap2/board-igep0030.c @@ -447,7 +447,7 @@ static void __init igep3_init(void) } -static const char *igep3_dt_compat[] __initdata = { +static const char *igep3_dt_compat[] __initconst = { "ISEE,igep-v3", NULL }; diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index b9ad453..85ca38f 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -681,7 +681,7 @@ static void __init omap3_beagle_init(void) beagle_opp_init(); } -static const char *omap3_beagle_dt_match[] __initdata = { +static const char *omap3_beagle_dt_match[] __initconst = { "ti,omap3-beagle", NULL }; diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 47738db..58adeaf 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -741,7 +741,7 @@ static void __init omap4_panda_map_io(void) omap44xx_map_common_io(); } -static const char *omap4_panda_match[] __initdata = { +static const char *omap4_panda_match[] __initconst = { "ti,omap4-panda", NULL, }; diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index e91942a..e88f846 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -785,7 +785,7 @@ static void __init overo_init(void) "OVERO_GPIO_USBH_CPEN\n"); } -static const char *omap3_overo_dt_match[] __initdata = { +static const char *omap3_overo_dt_match[] __initconst = { "gumstix,omap3-overo", NULL }; diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c index 6cc9569..0627ea2 100644 --- a/arch/arm/mach-omap2/board-zoom.c +++ b/arch/arm/mach-omap2/board-zoom.c @@ -132,7 +132,7 @@ static void __init omap_zoom_init(void) zoom_display_init(); } -static const char *zoom3_dt_match[] __initdata = { +static const char *zoom3_dt_match[] __initconst = { "ti,zoom3", NULL }; -- 1.7.6.rc1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 04/12] Serial: OMAP: Add runtime pm support for omap-serial driver
On 06/09/2011 03:49 PM, Jon Hunter wrote: Hi Govindraj On 06/08/2011 11:35 PM, Govindraj wrote: On Thu, Jun 9, 2011 at 2:09 AM, Jon Hunter wrote: Hi Govindraj, On 6/8/2011 6:23 AM, Govindraj.R wrote: [snip] + +#define OMAP_UART_AUTOSUSPEND_DELAY (30 * HZ) /* Value is msecs */ [snip] @@ -1295,18 +1381,36 @@ static int serial_omap_probe(struct platform_device *pdev) up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; } + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, + OMAP_UART_AUTOSUSPEND_DELAY); Something is weird here...DEFAULT_AUTOSUSPEND_DELAY is defined as (30*HZ) which would appear to be jiffies (ticks per second) and NOT msecs. However, pm_runtime_set_autosuspend is clearly expecting msecs. So this seems to conflict. By default 30*HZ for omap would be 30*128 = 3840ms so not quite 4 seconds. What were you intending here? Intention is to get approx 3 secs timeout for autosuspend. In that case you should just define DEFAULT_AUTOSUSPEND_DELAY as 3. The above is just confusing as you are mixing time types and hence, it is not clear what you intend the default timeout to be. Sorry, I meant 3000 and not 3 above, if you want 3 secs. Jon -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 04/12] Serial: OMAP: Add runtime pm support for omap-serial driver
Hi Govindraj On 06/08/2011 11:35 PM, Govindraj wrote: On Thu, Jun 9, 2011 at 2:09 AM, Jon Hunter wrote: Hi Govindraj, On 6/8/2011 6:23 AM, Govindraj.R wrote: [snip] + +#define OMAP_UART_AUTOSUSPEND_DELAY (30 * HZ) /* Value is msecs */ [snip] @@ -1295,18 +1381,36 @@ static int serial_omap_probe(struct platform_device *pdev) up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE; } + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_autosuspend_delay(&pdev->dev, + OMAP_UART_AUTOSUSPEND_DELAY); Something is weird here...DEFAULT_AUTOSUSPEND_DELAY is defined as (30*HZ) which would appear to be jiffies (ticks per second) and NOT msecs. However, pm_runtime_set_autosuspend is clearly expecting msecs. So this seems to conflict. By default 30*HZ for omap would be 30*128 = 3840ms so not quite 4 seconds. What were you intending here? Intention is to get approx 3 secs timeout for autosuspend. In that case you should just define DEFAULT_AUTOSUSPEND_DELAY as 3. The above is just confusing as you are mixing time types and hence, it is not clear what you intend the default timeout to be. Jon -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2 20/28] OMAP: DSS2: Use PM runtime & HWMOD support
On Thu, Jun 09, 2011 at 04:56:42PM +0300, Tomi Valkeinen wrote: > +int dispc_runtime_get(void) > +{ > + int r; > + > + DSSDBG("dispc_runtime_get\n"); > + > + r = pm_runtime_get_sync(&dispc.pdev->dev); > + WARN_ON(r < 0); > + return r < 0 ? r : 0; > +} > + > +void dispc_runtime_put(void) > +{ > + int r; > + > + DSSDBG("dispc_runtime_put\n"); > + > + r = pm_runtime_put(&dispc.pdev->dev); > + WARN_ON(r < 0); > } > This seems a bit odd. Your runtime_get wrapper is explicitly synchronous while your put wrapper is explicitly asynchronous, although these details (if intentional) are not at all obvious from the wrapper naming. From the use in the error paths and so on you will definitely need to be using pm_runtime_put_sync() at least some of the time. In the interest of avoiding confusion, I would in general just get rid of these wrappers and use the pm_runtime calls openly, as you already do for some of the other parts of the API. The runtime PM framework has pretty verbose debugging already that goes well beyond what you presently have, too. You seem to have adopted this sync/async pattern for all of the users: > +int dsi_runtime_get(struct platform_device *dsidev) > { > - if (enable) > - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); > - else > - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); > + int r; > + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); > + > + DSSDBG("dsi_runtime_get\n"); > + > + r = pm_runtime_get_sync(&dsi->pdev->dev); > + WARN_ON(r < 0); > + return r < 0 ? r : 0; > +} > + > +void dsi_runtime_put(struct platform_device *dsidev) > +{ > + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); > + int r; > + > + DSSDBG("dsi_runtime_put\n"); > + > + r = pm_runtime_put(&dsi->pdev->dev); > + WARN_ON(r < 0); > } > Here. > -void dss_clk_disable(enum dss_clock clks) > -{ .. > - dss_clk_disable_no_ctx(clks); > + r = pm_runtime_get_sync(&dss.pdev->dev); > + WARN_ON(r < 0); > + return r < 0 ? r : 0; > } > > -static void dss_clk_enable_all_no_ctx(void) > +void dss_runtime_put(void) > { .. > + r = pm_runtime_put(&dss.pdev->dev); > + WARN_ON(r < 0); > } > And here. > +static int hdmi_runtime_get(void) > +{ > + int r; > + > + DSSDBG("hdmi_runtime_get\n"); > + > + r = pm_runtime_get_sync(&hdmi.pdev->dev); > + WARN_ON(r < 0); > + return r < 0 ? r : 0; > +} > + > +static void hdmi_runtime_put(void) > +{ > + int r; > + > + DSSDBG("hdmi_runtime_put\n"); > + > + r = pm_runtime_put(&hdmi.pdev->dev); > + WARN_ON(r < 0); > +} > + And here. > -static void rfbi_enable_clocks(bool enable) > +static int rfbi_runtime_get(void) > { > - if (enable) > - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); > - else > - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); > + int r; > + > + DSSDBG("rfbi_runtime_get\n"); > + > + r = pm_runtime_get_sync(&rfbi.pdev->dev); > + WARN_ON(r < 0); > + return r < 0 ? r : 0; > +} > + > +static void rfbi_runtime_put(void) > +{ > + int r; > + > + DSSDBG("rfbi_runtime_put\n"); > + > + r = pm_runtime_put(&rfbi.pdev->dev); > + WARN_ON(r < 0); > } > And here. > +static int venc_runtime_get(void) > { > - if (enable) { > - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); > - if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) > - dss_clk_enable(DSS_CLK_VIDFCK); > - } else { > - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); > - if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) > - dss_clk_disable(DSS_CLK_VIDFCK); > - } > + int r; > + > + DSSDBG("venc_runtime_get\n"); > + > + r = pm_runtime_get_sync(&venc.pdev->dev); > + WARN_ON(r < 0); > + return r < 0 ? r : 0; > +} > + > +static void venc_runtime_put(void) > +{ > + int r; > + > + DSSDBG("venc_runtime_put\n"); > + > + r = pm_runtime_put(&venc.pdev->dev); > + WARN_ON(r < 0); > } > And here. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 06/12] MFD: twl4030-codec -> twl4030-audio: Rename the driver
On Thursday 09 June 2011 15:30:24 Peter Ujfalusi wrote: > Rename the driver, and header file from twl4030-codec to > twl4030-audio. > To avoid breakage change depending drivers at the same time. > > Signed-off-by: Peter Ujfalusi > CC: Misael Lopez Cruz > --- > drivers/input/misc/Kconfig |2 +- > drivers/input/misc/twl4030-vibra.c | 10 +- > drivers/mfd/Kconfig|2 +- > drivers/mfd/Makefile |2 +- > drivers/mfd/twl4030-audio.c| 277 +++ > drivers/mfd/twl4030-codec.c| 278 > > include/linux/mfd/twl4030-audio.h | 272 +++ > include/linux/mfd/twl4030-codec.h | 272 --- Better use the -M flag to git-format-patch when moving files, to make it obvious what has or has not changed, and to reduce the size of the email. Also, shouldn't this file go into the sound/soc/ directory? It seems that this is really the device driver, not part of the multi-function layer. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] dmaengine: add new api for preparing simple slave transfer
On Thu, Jun 9, 2011 at 6:09 PM, Raju, Sundaram wrote: > Generic buffer description: > A generic buffer can be split into number of frames which contain number of > chunks inside them. The frames need not be contiguous, nor do the chunks > inside a frame. > > --- > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame 0 > --- > | Inter Frame Gap | > --- > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame 1 > --- > | Inter Frame Gap | > --- > | > | > --- > | Inter Frame Gap | > --- > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame m > --- IIUC the above figure, the work done by DMA controller remains the same, either by passing this as a transfer of the new type or as a normal sg-list - unless the DMAC driver attempts to reorder the transfers or the DMAC h/w natively supports some form of sg-list. For DMACs, that have no special support, different representation wouldn't make a difference. And if the DMAC does support the kind of fancy scatter-gather, it should be possible for the dma api driver to analyze the submitted 'normal' sg-list and program the transfers at one go. Besides, it should be possible to have a 'template' sequence of requests prepared already because usually, for above mentioned scenario, the parameters don't change across items in a list. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [pm-wip/voltdm_nm][PATCH 04/10] OMAP4: PM: VC: allow channels use of default channel volt_reg_addr
Nishanth Menon writes: > OMAP4's PRM_VC_CFG_CHANNEL register allows for flexibility of configuring > for various PMIC configurations. In combinations where we'd like to > use the default VC channel's voltage_reg address in a particular non-default > VC channel, we allow the use of USE_DEFAULT_CHANNEL_I2C_PARAM. > > Since 0 is a valid register address, we need to increase the size of > reg storage for the flag. Depending on the PMIC and platform used, > this can be populated on the PMIC's datastructure and percolates to > VC's configuration. > > Signed-off-by: Nishanth Menon Approach is fine. After rebase, you won't have to do the u16 changes anymore since I squashed them into earlier patches already. Minor nit below... > --- > arch/arm/mach-omap2/vc.c | 17 ++--- > arch/arm/mach-omap2/vc.h |2 +- > arch/arm/mach-omap2/voltage.h |4 ++-- > 3 files changed, 13 insertions(+), 10 deletions(-) > > diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c > index 6017c70..53a16cc 100644 > --- a/arch/arm/mach-omap2/vc.c > +++ b/arch/arm/mach-omap2/vc.c > @@ -310,10 +310,11 @@ void __init omap_vc_init_channel(struct voltagedomain > *voltdm) > vc->setup_time = voltdm->pmic->volt_setup_time; > > if ((vc->flags & OMAP_VC_CHANNEL_DEFAULT) && > - (vc->i2c_slave_addr == USE_DEFAULT_CHANNEL_I2C_PARAM)) { > + ((vc->i2c_slave_addr == USE_DEFAULT_CHANNEL_I2C_PARAM) || > + (vc->volt_reg_addr == USE_DEFAULT_CHANNEL_I2C_PARAM))) { Please fixup the indentation here. (and in original patch that added this.) Run it through scripts/Lindent and see what the result should look like. I usually ends up to be leading tabs plus any extra spaces required to make it line up right. Kevin > pr_err("%s: voltdm %s: default channel " > - "bad config-sa=%2x ?\n", __func__, voltdm->name, > - vc->i2c_slave_addr); > + "bad config-sa=%2x vol=%2x?\n", __func__, voltdm->name, > + vc->i2c_slave_addr, vc->volt_reg_addr); > return; > } > > @@ -328,10 +329,12 @@ void __init omap_vc_init_channel(struct voltagedomain > *voltdm) > /* >* Configure the PMIC register addresses. >*/ > - voltdm->rmw(vc->smps_volra_mask, > - vc->volt_reg_addr << __ffs(vc->smps_volra_mask), > - vc->common->smps_volra_reg); > - vc->cfg_channel |= vc_cfg_bits->rav; > + if (vc->volt_reg_addr != USE_DEFAULT_CHANNEL_I2C_PARAM) { > + voltdm->rmw(vc->smps_volra_mask, > + vc->volt_reg_addr << __ffs(vc->smps_volra_mask), > + vc->common->smps_volra_reg); > + vc->cfg_channel |= vc_cfg_bits->rav; > + } > > if (vc->cmd_reg_addr) { > voltdm->rmw(vc->smps_cmdra_mask, > diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h > index 22c0060..310368f 100644 > --- a/arch/arm/mach-omap2/vc.h > +++ b/arch/arm/mach-omap2/vc.h > @@ -78,7 +78,7 @@ struct omap_vc_channel { > > /* channel state */ > u16 i2c_slave_addr; > - u8 volt_reg_addr; > + u16 volt_reg_addr; > u8 cmd_reg_addr; > u8 cfg_channel; > u16 setup_time; > diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h > index 1732258..75f3557 100644 > --- a/arch/arm/mach-omap2/voltage.h > +++ b/arch/arm/mach-omap2/voltage.h > @@ -114,7 +114,7 @@ struct omap_volt_data { > * channel is MPU, all other domains such as IVA/CORE, could optionally > * link their i2c reg configuration to use MPU channel's configuration if > * required. To do this, mark in the PMIC structure's > - * i2c_slave_addr with this macro. > + * i2c_slave_addr, volt_reg_addr with this macro. > */ > #define USE_DEFAULT_CHANNEL_I2C_PARAM 0x8000 > > @@ -142,7 +142,7 @@ struct omap_voltdm_pmic { > u8 vp_vddmax; > u8 vp_timeout_us; > u16 i2c_slave_addr; > - u8 volt_reg_addr; > + u16 volt_reg_addr; > u8 cmd_reg_addr; > bool i2c_high_speed; > u8 i2c_mcode; -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [pm-wip/voltdm_nm][PATCH 02/10] OMAP4: PM: VC: allow channels use of default channel i2c_slaveaddr
Kevin Hilman writes: [...] >> diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h >> index f079167..1732258 100644 >> --- a/arch/arm/mach-omap2/voltage.h >> +++ b/arch/arm/mach-omap2/voltage.h >> @@ -109,6 +109,15 @@ struct omap_volt_data { >> u8 vp_errgain; >> }; >> >> +/* >> + * Introduced in OMAP4, is a concept of a default channel - in OMAP4, this >> + * channel is MPU, all other domains such as IVA/CORE, could optionally >> + * link their i2c reg configuration to use MPU channel's configuration if >> + * required. To do this, mark in the PMIC structure's >> + * i2c_slave_addr with this macro. >> + */ >> +#define USE_DEFAULT_CHANNEL_I2C_PARAM 0x8000 >> + > > Needs a VC prefix, also use BIT(). > > Also, later on in the series you use the same value for things other > than the I2C slave address. How about just calling this: > > #define OMAP_VC_USE_DEFAULT_CHANNELBIT(15) > Also, this should be in vc.h, not voltage.h Kevin -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [pm-wip/voltdm_nm][PATCH 02/10] OMAP4: PM: VC: allow channels use of default channel i2c_slaveaddr
Nishanth Menon writes: > OMAP4's PRM_VC_CFG_CHANNEL register allows for flexibility of configuring > for various PMIC configurations. In combinations where the same slave address > is used for all domains, it is possible to setup the VC channel for the > dependent channels to use the same slave address as the default channel. > > Since I2C addressing could be 7 bit or 11 bits as per the I2C specification, That alone should be the justification for the u8 -> u16 change. In fact, I'll change all these i2c address fields so u16 in the original patches for that reason. Then here, you can just say you use BIT(15) because I2C address are a max of 11 bits. BTW is it 11 or 10? I've only heard of 10-bit addressing for I2C. > we use the BIT(15) to flag that this should use the default channel's > configuration. Depending on the PMIC and platform used, this can > be populated on the PMIC's datastructure and percolates to VC's configuration. > > Signed-off-by: Nishanth Menon > --- > arch/arm/mach-omap2/vc.c | 18 ++ > arch/arm/mach-omap2/vc.h |2 +- > arch/arm/mach-omap2/voltage.h | 11 ++- > 3 files changed, 25 insertions(+), 6 deletions(-) > > diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c > index aa9f0bc..0c0e416 100644 > --- a/arch/arm/mach-omap2/vc.c > +++ b/arch/arm/mach-omap2/vc.c > @@ -309,11 +309,21 @@ void __init omap_vc_init_channel(struct voltagedomain > *voltdm) > vc->cmd_reg_addr = voltdm->pmic->cmd_reg_addr; > vc->setup_time = voltdm->pmic->volt_setup_time; > > + if ((vc->flags & OMAP_VC_CHANNEL_DEFAULT) && > + (vc->i2c_slave_addr == USE_DEFAULT_CHANNEL_I2C_PARAM)) { > + pr_err("%s: voltdm %s: default channel " > + "bad config-sa=%2x ?\n", __func__, voltdm->name, > + vc->i2c_slave_addr); > + return; > + } > + > /* Configure the i2c slave address for this VC */ > - voltdm->rmw(vc->smps_sa_mask, > - vc->i2c_slave_addr << __ffs(vc->smps_sa_mask), > - vc->common->smps_sa_reg); > - vc->cfg_channel |= vc_cfg_bits->sa; > + if (vc->i2c_slave_addr != USE_DEFAULT_CHANNEL_I2C_PARAM) { > + voltdm->rmw(vc->smps_sa_mask, > + vc->i2c_slave_addr << __ffs(vc->smps_sa_mask), > + vc->common->smps_sa_reg); > + vc->cfg_channel |= vc_cfg_bits->sa; > + } > > /* >* Configure the PMIC register addresses. > diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h > index e16dacf..22c0060 100644 > --- a/arch/arm/mach-omap2/vc.h > +++ b/arch/arm/mach-omap2/vc.h > @@ -77,7 +77,7 @@ struct omap_vc_channel { > u8 flags; > > /* channel state */ > - u8 i2c_slave_addr; > + u16 i2c_slave_addr; > u8 volt_reg_addr; > u8 cmd_reg_addr; > u8 cfg_channel; > diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h > index f079167..1732258 100644 > --- a/arch/arm/mach-omap2/voltage.h > +++ b/arch/arm/mach-omap2/voltage.h > @@ -109,6 +109,15 @@ struct omap_volt_data { > u8 vp_errgain; > }; > > +/* > + * Introduced in OMAP4, is a concept of a default channel - in OMAP4, this > + * channel is MPU, all other domains such as IVA/CORE, could optionally > + * link their i2c reg configuration to use MPU channel's configuration if > + * required. To do this, mark in the PMIC structure's > + * i2c_slave_addr with this macro. > + */ > +#define USE_DEFAULT_CHANNEL_I2C_PARAM 0x8000 > + Needs a VC prefix, also use BIT(). Also, later on in the series you use the same value for things other than the I2C slave address. How about just calling this: #define OMAP_VC_USE_DEFAULT_CHANNELBIT(15) > /** > * struct omap_voltdm_pmic - PMIC specific data required by voltage driver. > * @slew_rate: PMIC slew rate (in uv/us) > @@ -132,7 +141,7 @@ struct omap_voltdm_pmic { > u8 vp_vddmin; > u8 vp_vddmax; > u8 vp_timeout_us; > - u8 i2c_slave_addr; > + u16 i2c_slave_addr; > u8 volt_reg_addr; > u8 cmd_reg_addr; > bool i2c_high_speed; -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [pm-wip/voltdm_nm][PATCH 03/10] OMAP4: PM: VC: allow channels to use cmdra reg
Nishanth Menon writes: > if volt_reg and cmd_reg are the same from PMIC configuration, > we can use the cmd reg by using racen - -ECONFUSED If volt_reg and cmd_reg are the same then I understood RACEN to be a don't care. Zero means use volt_reg, 1 means use cmd_reg, but if volt_reg == cmd_reg, then either way is the same result. The way I understood (and coded) this is that the only time you need RACEN set is precicesly the case when a cmd_reg is provided (and thus is different from volt_reg. What am I missing? Or, stated differently, I guess I don't understand the use case for RAC != RACEN Kevin > this is valid for > voltage commands, however, in most cases, we'd like to retain > voltage reg configuration as well for vfsm commands going thru > from h/w. > > Signed-off-by: Nishanth Menon > --- > arch/arm/mach-omap2/vc.c |6 +- > 1 files changed, 5 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c > index 0c0e416..6017c70 100644 > --- a/arch/arm/mach-omap2/vc.c > +++ b/arch/arm/mach-omap2/vc.c > @@ -337,9 +337,13 @@ void __init omap_vc_init_channel(struct voltagedomain > *voltdm) > voltdm->rmw(vc->smps_cmdra_mask, > vc->cmd_reg_addr << __ffs(vc->smps_cmdra_mask), > vc->common->smps_cmdra_reg); > - vc->cfg_channel |= vc_cfg_bits->rac | vc_cfg_bits->racen; > + vc->cfg_channel |= vc_cfg_bits->rac; > } > > + /* If voltage and cmd regs are same, we can use cmdra register */ > + if (vc->volt_reg_addr == vc->cmd_reg_addr) > + vc->cfg_channel |= vc_cfg_bits->racen; > + > /* Set up the on, inactive, retention and off voltage */ > on_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->on_volt); > onlp_vsel = voltdm->pmic->uv_to_vsel(voltdm->pmic->onlp_volt); -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [pm-wip/voltdm_nm][PATCH 01/10] OMAP3+: VC: fix mutant channel handling
Nishanth Menon writes: > "OMAP3+: PM: VC: handle mutant channel config for OMAP4 MPU channel" > handles the mutant channel flags, however since vc_cfg_bits is static > file wide variable, it makes better sense to update this based on > the specific channel using mutant or not. else if we have a initial > registration of mutant channel definition, all other channels will > end up using the mutant definition. Indeed. > Signed-off-by: Nishanth Menon > --- > we should probably squash this in to the original commit Thanks, squashed. Kevin > arch/arm/mach-omap2/vc.c |4 +++- > 1 files changed, 3 insertions(+), 1 deletions(-) > > diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c > index c8deac9..aa9f0bc 100644 > --- a/arch/arm/mach-omap2/vc.c > +++ b/arch/arm/mach-omap2/vc.c > @@ -53,7 +53,7 @@ static struct omap_vc_channel_cfg vc_mutant_channel_cfg = { > .cmd = BIT(1), > }; > > -static struct omap_vc_channel_cfg *vc_cfg_bits = &vc_default_channel_cfg; > +static struct omap_vc_channel_cfg *vc_cfg_bits; > #define CFG_CHANNEL_MASK 0x1f > > /** > @@ -300,6 +300,8 @@ void __init omap_vc_init_channel(struct voltagedomain > *voltdm) > vc->cfg_channel = 0; > if (vc->flags & OMAP_VC_CHANNEL_CFG_MUTANT) > vc_cfg_bits = &vc_mutant_channel_cfg; > + else > + vc_cfg_bits = &vc_default_channel_cfg; > > /* get PMIC/board specific settings */ > vc->i2c_slave_addr = voltdm->pmic->i2c_slave_addr; -- To unsubscribe from this list: send the line "unsubscribe linux-omap" 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 2/6] OMAP2+: PM: move runtime PM implementation to use device power domains
Sakari Ailus writes: > Hi Kevin and Felipe, > > Kevin Hilman wrote: >> In commit 7538e3db6e015e890825fbd9f8659952896ddd5b (PM: add support >> for device power domains) a better way for handling platform-specific >> power hooks was introduced. >> >> Rather than using the platform_bus dev_pm_ops overrides >> (platform_bus_set_pm_ops()), this patch moves the OMAP runtime PM >> implementation over to using device power domains. >> >> Since OMAP is the only user of platform_bus_set_pm_ops(), that >> interface can be removed (and will be in a forthcoming patch.) > > I have little doubt of the correctness of the patch itself, but it > actually does break the USB on N900. I don't know PM so well that I > would have a good idea what might be going wrong here, so I'm not > certain that this is specific to the N900 either. > > It looks strange to me also but I've tested it several times so I'm > fairly certain that the culprit is this very patch. :-) You're correct, it's broken. A fix has been posted (and pull req sent to Tony.) Can you try my for_3.0/pm-fixes branch which fixes this problem? It's available in my git tree: git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm.git Thanks, Kevin -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] dmaengine: add new api for preparing simple slave transfer
On Thu, Jun 09, 2011 at 09:31:56PM +0530, Raju, Sundaram wrote: > Here it is, with proper line wrapping; Thanks. This is much easier to reply to. > I believe that even though the dmaengine framework addresses and > supports most of the required use cases of a client driver to a DMA > controller, some extensions are required in it to make it still more > generic. > > Current framework contains two APIs to prepare for slave transfers: > > struct dma_async_tx_descriptor *(*device_prep_slave_sg)( > struct dma_chan *chan, struct scatterlist *sgl, > unsigned int sg_len, enum dma_data_direction direction, > unsigned long flags); > > struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( > struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, > size_t period_len, enum dma_data_direction direction); > > and one control API. > int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, > unsigned long arg); > > A simple single buffer transfer (i.e. non sg transfer) can be done only > as a trivial case of the device_prep_slave_sg API. The client driver is > expected to prepare a sg list and provide to the dmaengine API for that > single buffer also. We can avoid preparing a sg list in every driver which wants this by having dmaengine.h provide a helper for this case: static inline dma_async_tx_descriptor *dmaengine_prep_slave_single( struct dma_chan *chan, void *buf, size_t len, enum dma_data_direction dir, unsigned long flags) { struct scatterlist sg; sg_init_one(&sg, buf, len); return chan->device->device_prep_slave_sg(chan, &sg, 1, dir, flags); } I think also providing dmaengine_prep_slave_sg() and dmaengine_prep_dma_cyclic() as wrappers to hide the chan->device->blah bit would also be beneficial (and helps keep that detail out of the users of DMA engine.) > In a slave transfer, the client has to define all the buffer related > attributes and the peripheral related attributes. I'd argue that it is incorrect to have drivers specify the buffer related attributes - that makes the API unnecessarily complicated to use, requiring two calls (one to configure the channel, and one to prepare the transfer) each time it needs to be used. Not only that but the memory side of the transfer should be no business of the driver - the driver itself should only specify the attributes for the device being driven. The attributes for the memory side of the transfer should be a property of the DMA engine itself. I would like to see in the long term the dma_slave_config structure lose its 'direction' argument, and the rest of the parameters used to define the device side parameters only. This will allow the channel to be configured once when its requested, and then the prepare call can configure the direction as required. > Now coming to the buffer related attributes, sg list is a nice way to > represent a disjoint buffer; all the offload engines in drivers/dma > create a descriptor for each of the contiguous chunk in the sg list > buffer and pass it to the controller. The sg list is the standard Linux way to describe scattered buffers. > But many a times a client may want to transfer from a single buffer to > the peripheral and most of the DMA controllers have the capability to > transfer data in chunks/frames directly at a stretch. So far, I've only seen DMA controllers which operate on a linked list of source, destination, length, attributes, and next entry pointer. > All the attributes of a buffer, which are required for the transfer > can be programmed in single descriptor and submitted to the > DMA controller. I'm not sure that this is useful - in order to make use of the data, the data would have to be copied in between the descriptors - and doesn't that rather negate the point of DMA if you have to memcpy() the data around? Isn't it far more efficient to have DMA place the data exactly where it's required in memory right from the start without any memcpy() operations? Can you explain where and how you would use something like this: > --- > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame 0 > --- > |Inter Frame Gap | > --- > | Chunk 0 |ICG| Chunk 1 |ICG| ... |ICG| Chunk n | Frame 1 > --- > |Inter Frame Gap | > --- > | | > --- > |Inter Frame Gap | > -
RE: [RFC] dmaengine: add new api for preparing simple slave transfer
Here it is, with proper line wrapping; SDMA and EDMA are TI SoC specific DMA controllers. Their drivers have been maintained in the respective SoC folders till now. arch/arm/plat-omap/dma.c arch/arm/mach-davinci/dma.c I have gone through the existing offload engine (DMA) drivers in drivers/dma which do slave transfers. I would like to move SDMA and EDMA also to dmaengine framework. I believe that even though the dmaengine framework addresses and supports most of the required use cases of a client driver to a DMA controller, some extensions are required in it to make it still more generic. Current framework contains two APIs to prepare for slave transfers: struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_data_direction direction, unsigned long flags); struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); and one control API. int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg); A simple single buffer transfer (i.e. non sg transfer) can be done only as a trivial case of the device_prep_slave_sg API. The client driver is expected to prepare a sg list and provide to the dmaengine API for that single buffer also. In a slave transfer, the client has to define all the buffer related attributes and the peripheral related attributes. The above 2 APIs in the dmaengine framework expect all the peripheral/slave related attributes to be filled in the dma_slave_config data structure. struct dma_slave_config { enum dma_data_direction direction; dma_addr_t src_addr; dma_addr_t dst_addr; enum dma_slave_buswidth src_addr_width; enum dma_slave_buswidth dst_addr_width; u32 src_maxburst; u32 dst_maxburst; }; This data structure is passed to the offload engine via the dma_chan data structure in its private pointer. Now coming to the buffer related attributes, sg list is a nice way to represent a disjoint buffer; all the offload engines in drivers/dma create a descriptor for each of the contiguous chunk in the sg list buffer and pass it to the controller. But many a times a client may want to transfer from a single buffer to the peripheral and most of the DMA controllers have the capability to transfer data in chunks/frames directly at a stretch. All the attributes of a buffer, which are required for the transfer can be programmed in single descriptor and submitted to the DMA controller. So I think the slave transfer API must also have a provision to pass the buffer configuration. The buffer attributes have to be passed directly as an argument in the prepare API, unlike dma_slave_config as they will be different for each buffer that is going to be transferred. It is a stretch and impractical to use a highly segmented buffer (like the one described below) in a sglist. This is because sg list itself is a representation of a disjoint buffer collection in terms of smaller buffers. Now then each of these smaller buffers can have different buffer configurations (like described below) and we are not going to go down that road now. Hence it makes sense to pass these buffer attributes for only a single buffer transfer and not a sg list. This can be done by OPTION #1 1. Adding a pointer of the dma_buffer_config data structure in the device_prep_slave_sg API. 2. Ensuring that it will be ignored if a sg list passed. Only when a single buffer is passed (in the sg list) then this buffer configuration will be used. 3. Any client that wants to do a sg transfer can simply ignore this buffer configuration and pass NULL. The main disadvantage of this option is that all the existing drivers need to be updated since the API signature is changed. It might even be better to have a separate API for non sg transfers. This is OPTION #2 Advantages of this option are 1. No change required in the existing drivers that use device_prep_slave_sg API. 2. If any offload engine wants to prepare a simple buffer transfer differently and not as a trivial case of a sg list, this will be useful. I know this can be done using 2 different implementations inside the device_prep_slave_sg itself, but I think it's cleaner to have different APIs. I have provided the generic buffer configuration I can think of, here and also a new API definition, if it makes sense to have one. This buffer configuration might not be completely generic, and hence I ask all of you to please provide comments to improve it. Generic buffer description: A generic buffer can be split into number of frames which contain number of chunks inside them. The frames need not be contiguous, nor do the chunks inside a frame. -
Re: [PATCH/RFC 2/6] OMAP2+: PM: move runtime PM implementation to use device power domains
Hi Kevin and Felipe, Kevin Hilman wrote: > In commit 7538e3db6e015e890825fbd9f8659952896ddd5b (PM: add support > for device power domains) a better way for handling platform-specific > power hooks was introduced. > > Rather than using the platform_bus dev_pm_ops overrides > (platform_bus_set_pm_ops()), this patch moves the OMAP runtime PM > implementation over to using device power domains. > > Since OMAP is the only user of platform_bus_set_pm_ops(), that > interface can be removed (and will be in a forthcoming patch.) I have little doubt of the correctness of the patch itself, but it actually does break the USB on N900. I don't know PM so well that I would have a good idea what might be going wrong here, so I'm not certain that this is specific to the N900 either. It looks strange to me also but I've tested it several times so I'm fairly certain that the culprit is this very patch. :-) I'm using NFS root and the device fails to respond to ping with the patch although it can be clearly recognised by the host, and it also recognises the host. It seems just that the data doesn't get through. My .config may be found here: http://www.retiisi.org.uk/~sakke/foo/.config> And the respective boot logs, without and with the patch, are here: http://www.retiisi.org.uk/~sakke/foo/boot-success.txt> http://www.retiisi.org.uk/~sakke/foo/boot-fail.txt> They're mostly the same. There's no difference on host side logs either. The first connection is with the patch, whereas the second one is without: --- usb 5-2.1: new high speed USB device using ehci_hcd and address 42 cdc_ether 5-2.1:1.0: usb0: register 'cdc_ether' at usb-:00:1d.7-2.1, CDC Ethernet Device, 0a:3b:20:fa:58:eb device usb0 entered promiscuous mode eth-usb: port 2(usb0) entering learning state eth-usb: port 2(usb0) entering learning state eth-usb: port 2(usb0) entering forwarding state usb 5-2.1: USB disconnect, address 42 cdc_ether 5-2.1:1.0: usb0: unregister 'cdc_ether' usb-:00:1d.7-2.1, CDC Ethernet Device eth-usb: port 2(usb0) entering forwarding state device usb0 left promiscuous mode eth-usb: port 2(usb0) entering disabled state usb 5-2.1: new high speed USB device using ehci_hcd and address 43 usb 5-2.1: USB disconnect, address 43 usb 5-2.1: new high speed USB device using ehci_hcd and address 44 cdc_ether 5-2.1:1.0: usb0: register 'cdc_ether' at usb-:00:1d.7-2.1, CDC Ethernet Device, 4a:bc:09:bb:ba:98 device usb0 entered promiscuous mode eth-usb: port 2(usb0) entering learning state eth-usb: port 2(usb0) entering learning state eth-usb: port 2(usb0) entering learning state eth-usb: port 2(usb0) entering learning state eth-usb: port 2(usb0) entering learning state eth-usb: port 2(usb0) entering forwarding state usb 5-2.1: USB disconnect, address 44 --- Any ideas? The id of the patch in the mainline kernel is 638080c37ae08fd0c44cec13d7948ca5385ae851 . Thanks. > Cc: Grant Likely > Cc: Magnus Damm > Cc: Rafael J. Wysocki > Signed-off-by: Kevin Hilman > --- > arch/arm/mach-omap2/Makefile |6 +- > arch/arm/mach-omap2/pm_bus.c | 85 > -- > arch/arm/plat-omap/omap_device.c | 22 ++ > 3 files changed, 25 insertions(+), 88 deletions(-) > delete mode 100644 arch/arm/mach-omap2/pm_bus.c > > diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile > index a45cd64..b353584 100644 > --- a/arch/arm/mach-omap2/Makefile > +++ b/arch/arm/mach-omap2/Makefile > @@ -59,10 +59,10 @@ endif > # Power Management > ifeq ($(CONFIG_PM),y) > obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o > -obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o pm_bus.o > +obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o > obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o \ > -cpuidle34xx.o pm_bus.o > -obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o pm_bus.o > +cpuidle34xx.o > +obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o > obj-$(CONFIG_PM_DEBUG) += pm-debug.o > obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o > obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)+= smartreflex-class3.o > diff --git a/arch/arm/mach-omap2/pm_bus.c b/arch/arm/mach-omap2/pm_bus.c > deleted file mode 100644 > index 5acd2ab..000 > --- a/arch/arm/mach-omap2/pm_bus.c > +++ /dev/null > @@ -1,85 +0,0 @@ > -/* > - * Runtime PM support code for OMAP > - * > - * Author: Kevin Hilman, Deep Root Systems, LLC > - * > - * Copyright (C) 2010 Texas Instruments, Inc. > - * > - * This file is licensed under the terms of the GNU General Public > - * License version 2. This program is licensed "as is" without any > - * warranty of any kind, whether express or implied. > - */ > -#include > -#include > -#include > -#include > -#include > -#include > - > -#include > -#include > - > -#ifdef CONFIG_PM_RUNTIME > -static int omap_pm_runtime_suspend(struct device *dev) > -{ > - stru
Re: [PATCHv2 00/28] OMAP DSS runtime PM adaptation
On Thu, 2011-06-09 at 16:56 +0300, Tomi Valkeinen wrote: > Hi, > > This patch set implements runtime PM adaptation for OMAP DSS driver. > These patches can be found from: > > git://gitorious.org/linux-omap-dss2/linux.git pmruntime The branch is actually "pmruntime-v2", my mistake. Tomi -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 23/28] OMAP: DSS2: DISPC: remove finegrained clk enables/disables
dispc.c enables and disables clocks in almost every function to make sure the clocks are enabled when the function is called. This is rather unoptimal way to handle the problem. With pm_runtime other components have to call dispc_runtime_get() to enable dispc clocks before calling any other dispc functions. Thus the finegrained clk enables/disables can be removed. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 165 +-- 1 files changed, 19 insertions(+), 146 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 3f2265f..2de7e92 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -604,8 +604,6 @@ void dispc_go(enum omap_channel channel) int bit; bool enable_bit, go_bit; - dispc_runtime_get(); - if (channel == OMAP_DSS_CHANNEL_LCD || channel == OMAP_DSS_CHANNEL_LCD2) bit = 0; /* LCDENABLE */ @@ -619,7 +617,7 @@ void dispc_go(enum omap_channel channel) enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1; if (!enable_bit) - goto end; + return; if (channel == OMAP_DSS_CHANNEL_LCD || channel == OMAP_DSS_CHANNEL_LCD2) @@ -634,7 +632,7 @@ void dispc_go(enum omap_channel channel) if (go_bit) { DSSERR("GO bit not down for channel %d\n", channel); - goto end; + return; } DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : @@ -644,8 +642,6 @@ void dispc_go(enum omap_channel channel) REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit); else REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); -end: - dispc_runtime_put(); } static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) @@ -1019,7 +1015,7 @@ static void _dispc_set_color_mode(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); } -static void _dispc_set_channel_out(enum omap_plane plane, +void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel) { int shift; @@ -1072,8 +1068,6 @@ void dispc_set_burst_size(enum omap_plane plane, int shift; u32 val; - dispc_runtime_get(); - switch (plane) { case OMAP_DSS_GFX: shift = 6; @@ -1090,8 +1084,6 @@ void dispc_set_burst_size(enum omap_plane plane, val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); val = FLD_MOD(val, burst_size, shift+1, shift); dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); - - dispc_runtime_put(); } void dispc_enable_gamma_table(bool enable) @@ -1128,9 +1120,7 @@ void dispc_enable_replication(enum omap_plane plane, bool enable) else bit = 10; - dispc_runtime_get(); REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); - dispc_runtime_put(); } void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) @@ -1138,9 +1128,7 @@ void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) u32 val; BUG_ON((width > (1 << 11)) || (height > (1 << 11))); val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - dispc_runtime_get(); dispc_write_reg(DISPC_SIZE_MGR(channel), val); - dispc_runtime_put(); } void dispc_set_digit_size(u16 width, u16 height) @@ -1148,9 +1136,7 @@ void dispc_set_digit_size(u16 width, u16 height) u32 val; BUG_ON((width > (1 << 11)) || (height > (1 << 11))); val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); - dispc_runtime_get(); dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); - dispc_runtime_put(); } static void dispc_read_plane_fifo_sizes(void) @@ -1159,8 +1145,6 @@ static void dispc_read_plane_fifo_sizes(void) int plane; u8 start, end; - dispc_runtime_get(); - dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { @@ -1168,8 +1152,6 @@ static void dispc_read_plane_fifo_sizes(void) start, end); dispc.fifo_size[plane] = size; } - - dispc_runtime_put(); } u32 dispc_get_plane_fifo_size(enum omap_plane plane) @@ -1184,8 +1166,6 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); - dispc_runtime_get(); - DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", plane, REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), @@ -1197,18 +1177,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
[PATCHv2 24/28] OMAP: DSS2: Remove unused code from display.c
oh_core variable is no longer used, so it and its initialization can be removed. Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c | 10 -- 1 files changed, 0 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index af43620..a5b7a23 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -43,9 +43,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = { }, }; -/* oh_core is used for getting opt-clocks */ -static struct omap_hwmod *oh_core; - struct omap_dss_hwmod_data { const char *oh_name; const char *dev_name; @@ -99,13 +96,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) oh_count = ARRAY_SIZE(omap4_dss_hwmod_data); } - /* opt_clks are always associated with dss hwmod */ - oh_core = omap_hwmod_lookup("dss_core"); - if (!oh_core) { - pr_err("Could not look up dss_core.\n"); - return -ENODEV; - } - pdata.board_data = board_data; pdata.board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 28/28] OMAP: DSS2: DSS: Fix context save/restore
The current method of saving and restoring the context could cause a restore before saving, effectively "restoring" zero values to registers. Add ctx_valid field to indicate if the saved context is valid and can be restored. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 10 ++ 1 files changed, 10 insertions(+), 0 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 21c8389..5c6499a 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -74,6 +74,7 @@ static struct { enum omap_dss_clk_source dispc_clk_source; enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; + boolctx_valid; u32 ctx[DSS_SZ_REGS / sizeof(u32)]; } dss; @@ -109,12 +110,19 @@ static void dss_save_context(void) SR(SDI_CONTROL); SR(PLL_CONTROL); } + + dss.ctx_valid = true; + + DSSDBG("context saved\n"); } static void dss_restore_context(void) { DSSDBG("dss_restore_context\n"); + if (!dss.ctx_valid) + return; + RR(CONTROL); if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & @@ -122,6 +130,8 @@ static void dss_restore_context(void) RR(SDI_CONTROL); RR(PLL_CONTROL); } + + DSSDBG("context restored\n"); } #undef SR -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 26/28] OMAP4: CLKDEV: Remove omapdss clock aliases
omapdss driver now gets the clocks via hwmod opt clocks, so clock aliases for omapdss_dss are no longer needed. Cc: Benoit Cousson Cc: Paul Walmsley Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/clock44xx_data.c | 10 +- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 8c96567..4d278e7 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -3114,11 +3114,11 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X), CLK(NULL, "dmic_fck", &dmic_fck, CK_443X), CLK(NULL, "dsp_fck", &dsp_fck, CK_443X), - CLK("omapdss_dss", "sys_clk", &dss_sys_clk, CK_443X), - CLK("omapdss_dss", "tv_clk", &dss_tv_clk, CK_443X), - CLK("omapdss_dss", "video_clk",&dss_48mhz_clk, CK_443X), - CLK("omapdss_dss", "fck", &dss_dss_clk, CK_443X), - CLK("omapdss_dss", "ick", &dss_fck, CK_443X), + CLK(NULL, "sys_clk", &dss_sys_clk, CK_443X), + CLK(NULL, "tv_clk", &dss_tv_clk, CK_443X), + CLK(NULL, "video_clk",&dss_48mhz_clk, CK_443X), + CLK(NULL, "fck", &dss_dss_clk, CK_443X), + CLK(NULL, "ick", &dss_fck, CK_443X), CLK(NULL, "efuse_ctrl_cust_fck", &efuse_ctrl_cust_fck, CK_443X), CLK(NULL, "emif1_fck",&emif1_fck, CK_443X), CLK(NULL, "emif2_fck",&emif2_fck, CK_443X), -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 27/28] OMAP: DSS2: DISPC: Fix context save/restore
The current method of saving and restoring the context could cause a restore before saving, effectively "restoring" zero values to registers. Add ctx_valid field to indicate if the saved context is valid and can be restored. Also restructure the code to save the ctx_loss_count in save_context(), which makes more sense than the previous method of storing new ctx_loss_count in dispc_need_ctx_restore. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c | 97 +++--- 1 files changed, 38 insertions(+), 59 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 2de7e92..eac768f 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -108,6 +108,7 @@ static struct { u32 error_irqs; struct work_struct error_work; + boolctx_valid; u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS @@ -140,6 +141,23 @@ static inline u32 dispc_read_reg(const u16 idx) return __raw_readl(dispc.base + idx); } +static int dispc_get_ctx_loss_count(void) +{ + struct device *dev = &dispc.pdev->dev; + struct omap_display_platform_data *pdata = dev->platform_data; + struct omap_dss_board_info *board_data = pdata->board_data; + int cnt; + + if (!board_data->get_context_loss_count) + return -ENOENT; + + cnt = board_data->get_context_loss_count(dev); + + WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt); + + return cnt; +} + #define SR(reg) \ dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) #define RR(reg) \ @@ -316,14 +334,30 @@ static void dispc_save_context(void) if (dss_has_feature(FEAT_CORE_CLK_DIV)) SR(DIVISOR); + + dispc.ctx_loss_cnt = dispc_get_ctx_loss_count(); + dispc.ctx_valid = true; + + DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); } static void dispc_restore_context(void) { - int i; + int i, ctx; DSSDBG("dispc_restore_context\n"); + if (!dispc.ctx_valid) + return; + + ctx = dispc_get_ctx_loss_count(); + + if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) + return; + + DSSDBG("ctx_loss_count: saved %d, current %d\n", + dispc.ctx_loss_cnt, ctx); + /*RR(IRQENABLE);*/ /*RR(CONTROL);*/ RR(CONFIG); @@ -502,65 +536,13 @@ static void dispc_restore_context(void) * the context is fully restored */ RR(IRQENABLE); + + DSSDBG("context restored\n"); } #undef SR #undef RR -static void dispc_init_ctx_loss_count(void) -{ - struct device *dev = &dispc.pdev->dev; - struct omap_display_platform_data *pdata = dev->platform_data; - struct omap_dss_board_info *board_data = pdata->board_data; - int cnt = 0; - - /* -* get_context_loss_count returns negative on error. We'll ignore the -* error and store the error to ctx_loss_cnt, which will cause -* dispc_need_ctx_restore() call to return true. -*/ - - if (board_data->get_context_loss_count) - cnt = board_data->get_context_loss_count(dev); - - WARN_ON(cnt < 0); - - dispc.ctx_loss_cnt = cnt; - - DSSDBG("initial ctx_loss_cnt %u\n", cnt); -} - -static bool dispc_need_ctx_restore(void) -{ - struct device *dev = &dispc.pdev->dev; - struct omap_display_platform_data *pdata = dev->platform_data; - struct omap_dss_board_info *board_data = pdata->board_data; - int cnt; - - /* -* If get_context_loss_count is not available, assume that we need -* context restore always. -*/ - if (!board_data->get_context_loss_count) - return true; - - cnt = board_data->get_context_loss_count(dev); - if (cnt < 0) { - dev_err(dev, "getting context loss count failed, will force " - "context restore\n"); - dispc.ctx_loss_cnt = cnt; - return true; - } - - if (cnt == dispc.ctx_loss_cnt) - return false; - - DSSDBG("ctx_loss_cnt %d -> %d\n", dispc.ctx_loss_cnt, cnt); - dispc.ctx_loss_cnt = cnt; - - return true; -} - int dispc_runtime_get(void) { int r; @@ -3641,8 +3623,6 @@ static int omap_dispchw_probe(struct platform_device *pdev) goto err_irq; } - dispc_init_ctx_loss_count(); - pm_runtime_enable(&pdev->dev); r = dispc_runtime_get(); @@ -3701,8 +3681,7 @@ static int dispc_runtime_resume(struct device *dev) return r; clk_enable(dispc.dss_clk); - if (dispc_need_ctx_restore()) - dispc_restore_context(); + dispc_restore_context(); return 0; } -- 1.7.4.1 -- To unsubscribe from this list
[PATCHv2 25/28] OMAP: DSS2: Remove ctx loss count from dss.c
dss.c only saves 1 register (3 in OMAP3) so the extra overhead from need_ctx_restore & co. is probably bigger than the time spent saving and restoring those few registers every time. So remove the code from dss.c and restore context every time dss has been off. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 62 + 1 files changed, 1 insertions(+), 61 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 4e36a07..21c8389 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -62,8 +62,6 @@ static struct { struct platform_device *pdev; void __iomem*base; - int ctx_loss_cnt; - struct clk *dpll4_m4_ck; struct clk *dss_clk; @@ -631,61 +629,6 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ } -/* CONTEXT */ -static void dss_init_ctx_loss_count(void) -{ - struct device *dev = &dss.pdev->dev; - struct omap_display_platform_data *pdata = dev->platform_data; - struct omap_dss_board_info *board_data = pdata->board_data; - int cnt = 0; - - /* -* get_context_loss_count returns negative on error. We'll ignore the -* error and store the error to ctx_loss_cnt, which will cause -* dss_need_ctx_restore() call to return true. -*/ - - if (board_data->get_context_loss_count) - cnt = board_data->get_context_loss_count(dev); - - WARN_ON(cnt < 0); - - dss.ctx_loss_cnt = cnt; - - DSSDBG("initial ctx_loss_cnt %u\n", cnt); -} - -static bool dss_need_ctx_restore(void) -{ - struct device *dev = &dss.pdev->dev; - struct omap_display_platform_data *pdata = dev->platform_data; - struct omap_dss_board_info *board_data = pdata->board_data; - int cnt; - - /* -* If get_context_loss_count is not available, assume that we need -* context restore always. -*/ - if (!board_data->get_context_loss_count) - return true; - - cnt = board_data->get_context_loss_count(dev); - if (cnt < 0) { - dev_err(dev, "getting context loss count failed, will force " - "context restore\n"); - dss.ctx_loss_cnt = cnt; - return true; - } - - if (cnt == dss.ctx_loss_cnt) - return false; - - DSSDBG("ctx_loss_cnt %d -> %d\n", dss.ctx_loss_cnt, cnt); - dss.ctx_loss_cnt = cnt; - - return true; -} - static int dss_get_clocks(void) { struct clk *clk; @@ -797,8 +740,6 @@ static int omap_dsshw_probe(struct platform_device *pdev) if (r) goto err_clocks; - dss_init_ctx_loss_count(); - pm_runtime_enable(&pdev->dev); r = dss_runtime_get(); @@ -875,8 +816,7 @@ static int dss_runtime_suspend(struct device *dev) static int dss_runtime_resume(struct device *dev) { clk_enable(dss.dss_clk); - if (dss_need_ctx_restore()) - dss_restore_context(); + dss_restore_context(); return 0; } -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 22/28] OMAP: DSS2: Remove unused opt_clock_available
opt_clock_available() is no longer needed, so remove it. Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c | 12 include/video/omapdss.h |2 -- 2 files changed, 0 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index c7e19c4..af43620 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -46,17 +46,6 @@ static struct omap_device_pm_latency omap_dss_latency[] = { /* oh_core is used for getting opt-clocks */ static struct omap_hwmod *oh_core; -static bool opt_clock_available(const char *clk_role) -{ - int i; - - for (i = 0; i < oh_core->opt_clks_cnt; i++) { - if (!strcmp(oh_core->opt_clks[i].role, clk_role)) - return true; - } - return false; -} - struct omap_dss_hwmod_data { const char *oh_name; const char *dev_name; @@ -120,7 +109,6 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) pdata.board_data = board_data; pdata.board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count; - pdata.opt_clock_available = opt_clock_available; for (i = 0; i < oh_count; i++) { oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name); diff --git a/include/video/omapdss.h b/include/video/omapdss.h index 4f914a5..06914b1 100644 --- a/include/video/omapdss.h +++ b/include/video/omapdss.h @@ -264,8 +264,6 @@ static inline int omap_display_init(struct omap_dss_board_info *board_data) struct omap_display_platform_data { struct omap_dss_board_info *board_data; /* TODO: Additional members to be added when PM is considered */ - - bool (*opt_clock_available)(const char *clk_role); }; struct omap_video_timings { -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 21/28] OMAP4: HWMOD: Remove unneeded DSS opt clocks
Some of the optional clocks for dss_core are not needed. Remove them. Cc: Benoit Cousson Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c |3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 857bdda..d7d86b6 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1164,10 +1164,7 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = { }; static struct omap_hwmod_opt_clk dss_opt_clks[] = { - { .role = "sys_clk", .clk = "dss_sys_clk" }, - { .role = "tv_clk", .clk = "dss_tv_clk" }, { .role = "dss_clk", .clk = "dss_dss_clk" }, - { .role = "video_clk", .clk = "dss_48mhz_clk" }, }; static struct omap_hwmod omap44xx_dss_hwmod = { -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 19/28] OMAP4: HWMOD: change DSS main_clk scheme
Currently using pm_runtime with DSS requires the DSS driver to enable the DSS functional clock before calling pm_runtime_get(). That makes it impossible to use pm_runtime in DSS as it is meant to be used, with pm_runtime callbacks. This patch changes the hwmod database for OMAP4 so that enabling the hwmod via pm_runtime will also enable the DSS functional clock, allowing us to use pm_runtime properly in DSS driver. The DSS HWMOD side is not really correct, not before nor after this patch, and getting DSS to retention will probably not work currently. However, it is not supported in the mainline kernel anyway, so this won't break anything. So this patch allows us to write the pm_runtime adaptation for the DSS driver the way it should be done, and the HWMOD/PM side can be fixed later. Cc: Benoit Cousson Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 28 ++-- 1 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 4f6ae94..857bdda 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1133,7 +1133,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = { static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_dss_hwmod, - .clk= "l3_div_ck", + .clk= "dss_fck", .addr = omap44xx_dss_dma_addrs, .addr_cnt = ARRAY_SIZE(omap44xx_dss_dma_addrs), .user = OCP_USER_SDMA, @@ -1173,7 +1173,7 @@ static struct omap_hwmod_opt_clk dss_opt_clks[] = { static struct omap_hwmod omap44xx_dss_hwmod = { .name = "dss_core", .class = &omap44xx_dss_hwmod_class, - .main_clk = "dss_fck", + .main_clk = "dss_dss_clk", .prcm = { .omap4 = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, @@ -1233,7 +1233,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = { static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_dss_dispc_hwmod, - .clk= "l3_div_ck", + .clk= "dss_fck", .addr = omap44xx_dss_dispc_dma_addrs, .addr_cnt = ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs), .user = OCP_USER_SDMA, @@ -1282,7 +1282,7 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = { .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_irqs), .sdma_reqs = omap44xx_dss_dispc_sdma_reqs, .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs), - .main_clk = "dss_fck", + .main_clk = "dss_dss_clk", .prcm = { .omap4 = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, @@ -1338,7 +1338,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = { static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_dss_dsi1_hwmod, - .clk= "l3_div_ck", + .clk= "dss_fck", .addr = omap44xx_dss_dsi1_dma_addrs, .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs), .user = OCP_USER_SDMA, @@ -1380,7 +1380,7 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = { .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_irqs), .sdma_reqs = omap44xx_dss_dsi1_sdma_reqs, .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs), - .main_clk = "dss_fck", + .main_clk = "dss_dss_clk", .prcm = { .omap4 = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, @@ -1415,7 +1415,7 @@ static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = { static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = { .master = &omap44xx_l3_main_2_hwmod, .slave = &omap44xx_dss_dsi2_hwmod, - .clk= "l3_div_ck", + .clk= "dss_fck", .addr = omap44xx_dss_dsi2_dma_addrs, .addr_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs), .user = OCP_USER_SDMA, @@ -1452,7 +1452,7 @@ static struct omap_hwmod omap44xx_dss_dsi2_hwmod = { .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_irqs), .sdma_reqs = omap44xx_dss_dsi2_sdma_reqs, .sdma_reqs_cnt = ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs), - .main_clk = "dss_fck", + .main_clk = "dss_dss_clk", .prcm = { .omap4 = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, @@ -1505,7 +1505,7 @@ static str
[PATCHv2 18/28] OMAP2430: HWMOD: Add DSS opt clocks
Add DSS optional clocks to HWMOD data for OMAP2430. Cc: Benoit Cousson Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 19 +++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 9682dd5..8009945 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -1302,6 +1302,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = { }; static struct omap_hwmod_opt_clk dss_opt_clks[] = { + { .role = "dss_clk", .clk = "dss1_fck" }, { .role = "tv_clk", .clk = "dss_54m_fck" }, { .role = "sys_clk", .clk = "dss2_fck" }, }; @@ -1379,6 +1380,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = { &omap2430_l4_core__dss_dispc, }; +static struct omap_hwmod_opt_clk dispc_opt_clks[] = { + { .role = "dss_clk", .clk = "dss1_fck" }, +}; + static struct omap_hwmod omap2430_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap2430_dispc_hwmod_class, @@ -1394,6 +1399,8 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = { .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT, }, }, + .opt_clks = dispc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks), .slaves = omap2430_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap2430_dss_dispc_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), @@ -1443,6 +1450,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = { &omap2430_l4_core__dss_rfbi, }; +static struct omap_hwmod_opt_clk rfbi_opt_clks[] = { + { .role = "rfbi_iclk", .clk = "dss_ick" }, +}; + static struct omap_hwmod omap2430_dss_rfbi_hwmod = { .name = "dss_rfbi", .class = &omap2430_rfbi_hwmod_class, @@ -1454,6 +1465,8 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = { .module_offs = CORE_MOD, }, }, + .opt_clks = rfbi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks), .slaves = omap2430_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap2430_dss_rfbi_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), @@ -1494,6 +1507,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = { &omap2430_l4_core__dss_venc, }; +static struct omap_hwmod_opt_clk venc_opt_clks[] = { + { .role = "tv_clk", .clk = "dss_54m_fck" }, +}; + static struct omap_hwmod omap2430_dss_venc_hwmod = { .name = "dss_venc", .class = &omap2430_venc_hwmod_class, @@ -1505,6 +1522,8 @@ static struct omap_hwmod omap2430_dss_venc_hwmod = { .module_offs = CORE_MOD, }, }, + .opt_clks = venc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(venc_opt_clks), .slaves = omap2430_dss_venc_slaves, .slaves_cnt = ARRAY_SIZE(omap2430_dss_venc_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430), -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 17/28] OMAP2420: HWMOD: Add DSS opt clocks
Add DSS optional clocks to HWMOD data for OMAP2420. Cc: Benoit Cousson Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 19 +++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c index c4d0ae8..d87019d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c @@ -1208,6 +1208,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = { }; static struct omap_hwmod_opt_clk dss_opt_clks[] = { + { .role = "dss_clk", .clk = "dss1_fck" }, { .role = "tv_clk", .clk = "dss_54m_fck" }, { .role = "sys_clk", .clk = "dss2_fck" }, }; @@ -1291,6 +1292,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = { &omap2420_l4_core__dss_dispc, }; +static struct omap_hwmod_opt_clk dispc_opt_clks[] = { + { .role = "dss_clk", .clk = "dss1_fck" }, +}; + static struct omap_hwmod omap2420_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap2420_dispc_hwmod_class, @@ -1306,6 +1311,8 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = { .idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT, }, }, + .opt_clks = dispc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks), .slaves = omap2420_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap2420_dss_dispc_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), @@ -1361,6 +1368,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = { &omap2420_l4_core__dss_rfbi, }; +static struct omap_hwmod_opt_clk rfbi_opt_clks[] = { + { .role = "rfbi_iclk", .clk = "dss_ick" }, +}; + static struct omap_hwmod omap2420_dss_rfbi_hwmod = { .name = "dss_rfbi", .class = &omap2420_rfbi_hwmod_class, @@ -1372,6 +1383,8 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = { .module_offs = CORE_MOD, }, }, + .opt_clks = rfbi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks), .slaves = omap2420_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap2420_dss_rfbi_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), @@ -1418,6 +1431,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = { &omap2420_l4_core__dss_venc, }; +static struct omap_hwmod_opt_clk venc_opt_clks[] = { + { .role = "tv_clk", .clk = "dss_54m_fck" }, +}; + static struct omap_hwmod omap2420_dss_venc_hwmod = { .name = "dss_venc", .class = &omap2420_venc_hwmod_class, @@ -1429,6 +1446,8 @@ static struct omap_hwmod omap2420_dss_venc_hwmod = { .module_offs = CORE_MOD, }, }, + .opt_clks = venc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(venc_opt_clks), .slaves = omap2420_dss_venc_slaves, .slaves_cnt = ARRAY_SIZE(omap2420_dss_venc_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420), -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 16/28] OMAP3: HWMOD: Add DSS opt clocks
Add DSS optional clocks to HWMOD data for OMAP3xxx. Cc: Benoit Cousson Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 37 ++- 1 files changed, 35 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 909a84d..5fac4c0 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -1542,9 +1542,15 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = { }; static struct omap_hwmod_opt_clk dss_opt_clks[] = { - { .role = "tv_clk", .clk = "dss_tv_fck" }, - { .role = "video_clk", .clk = "dss_96m_fck" }, + { .role = "dss_clk", .clk = "dss1_alwon_fck" }, + /* +* The rest of the clocks are not needed by the driver, +* but are needed by the hwmod to reset DSS properly. +*/ { .role = "sys_clk", .clk = "dss2_alwon_fck" }, + { .role = "tv_clk", .clk = "dss_tv_fck" }, + /* required only on OMAP3430 */ + { .role = "tv_dac_clk", .clk = "dss_96m_fck" }, }; static struct omap_hwmod omap3430es1_dss_core_hwmod = { @@ -1656,6 +1662,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = { &omap3xxx_l4_core__dss_dispc, }; +static struct omap_hwmod_opt_clk dispc_opt_clks[] = { + { .role = "dss_clk", .clk = "dss1_alwon_fck" }, +}; + static struct omap_hwmod omap3xxx_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap3xxx_dispc_hwmod_class, @@ -1669,6 +1679,8 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = { .module_offs = OMAP3430_DSS_MOD, }, }, + .opt_clks = dispc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks), .slaves = omap3xxx_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dispc_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | @@ -1720,6 +1732,11 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = { &omap3xxx_l4_core__dss_dsi1, }; +static struct omap_hwmod_opt_clk dsi1_opt_clks[] = { + { .role = "dss_clk", .clk = "dss1_alwon_fck" }, + { .role = "sys_clk", .clk = "dss2_alwon_fck" }, +}; + static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = { .name = "dss_dsi1", .class = &omap3xxx_dsi_hwmod_class, @@ -1733,6 +1750,8 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = { .module_offs = OMAP3430_DSS_MOD, }, }, + .opt_clks = dsi1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dsi1_opt_clks), .slaves = omap3xxx_dss_dsi1_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | @@ -1791,6 +1810,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = { &omap3xxx_l4_core__dss_rfbi, }; +static struct omap_hwmod_opt_clk rfbi_opt_clks[] = { + { .role = "rfbi_iclk", .clk = "dss_ick" }, +}; + static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = { .name = "dss_rfbi", .class = &omap3xxx_rfbi_hwmod_class, @@ -1802,6 +1825,8 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = { .module_offs = OMAP3430_DSS_MOD, }, }, + .opt_clks = rfbi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks), .slaves = omap3xxx_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | @@ -1851,6 +1876,12 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = { &omap3xxx_l4_core__dss_venc, }; +static struct omap_hwmod_opt_clk venc_opt_clks[] = { + { .role = "tv_clk", .clk = "dss_tv_fck" }, + /* required only on OMAP3430 */ + { .role = "tv_dac_clk", .clk = "dss_96m_fck" }, +}; + static struct omap_hwmod omap3xxx_dss_venc_hwmod = { .name = "dss_venc", .class = &omap3xxx_venc_hwmod_class, @@ -1862,6 +1893,8 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = { .module_offs = OMAP3430_DSS_MOD, }, }, + .opt_clks = venc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(venc_opt_clks), .slaves = omap3xxx_dss_venc_slaves, .slaves_cnt = ARRAY_SIZE(omap3xxx_dss_venc_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 | -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 15/28] OMAP4: HWMOD: Modify DSS opt clocks
Add missing DSS optional clocks to HWMOD data for OMAP4xxx. Add HWMOD_CONTROL_OPT_CLKS_IN_RESET flag for dispc to fix dispc reset. Cc: Benoit Cousson Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 40 1 files changed, 40 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index abc548a..4f6ae94 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1263,9 +1263,21 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = { &omap44xx_l4_per__dss_dispc, }; +static struct omap_hwmod_opt_clk dispc_opt_clks[] = { + { .role = "dss_clk", .clk = "dss_dss_clk" }, + /* +* The rest of the clocks are not needed by the driver, +* but are needed by the hwmod to reset DSS properly. +*/ + { .role = "sys_clk", .clk = "dss_sys_clk" }, + { .role = "tv_clk", .clk = "dss_tv_clk" }, + { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, +}; + static struct omap_hwmod omap44xx_dss_dispc_hwmod = { .name = "dss_dispc", .class = &omap44xx_dispc_hwmod_class, + .flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET, .mpu_irqs = omap44xx_dss_dispc_irqs, .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_dss_dispc_irqs), .sdma_reqs = omap44xx_dss_dispc_sdma_reqs, @@ -1276,6 +1288,8 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, }, }, + .opt_clks = dispc_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dispc_opt_clks), .slaves = omap44xx_dss_dispc_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dispc_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), @@ -1354,6 +1368,11 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = { &omap44xx_l4_per__dss_dsi1, }; +static struct omap_hwmod_opt_clk dsi1_opt_clks[] = { + { .role = "dss_clk", .clk = "dss_dss_clk" }, + { .role = "sys_clk", .clk = "dss_sys_clk" }, +}; + static struct omap_hwmod omap44xx_dss_dsi1_hwmod = { .name = "dss_dsi1", .class = &omap44xx_dsi_hwmod_class, @@ -1367,6 +1386,8 @@ static struct omap_hwmod omap44xx_dss_dsi1_hwmod = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, }, }, + .opt_clks = dsi1_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(dsi1_opt_clks), .slaves = omap44xx_dss_dsi1_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_dsi1_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), @@ -1514,6 +1535,11 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = { &omap44xx_l4_per__dss_hdmi, }; +static struct omap_hwmod_opt_clk hdmi_opt_clks[] = { + { .role = "sys_clk", .clk = "dss_sys_clk" }, + { .role = "hdmi_clk", .clk = "dss_48mhz_clk" }, +}; + static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { .name = "dss_hdmi", .class = &omap44xx_hdmi_hwmod_class, @@ -1527,6 +1553,8 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, }, }, + .opt_clks = hdmi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(hdmi_opt_clks), .slaves = omap44xx_dss_hdmi_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_hdmi_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), @@ -1600,6 +1628,10 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = { &omap44xx_l4_per__dss_rfbi, }; +static struct omap_hwmod_opt_clk rfbi_opt_clks[] = { + { .role = "rfbi_iclk", .clk = "dss_fck" }, +}; + static struct omap_hwmod omap44xx_dss_rfbi_hwmod = { .name = "dss_rfbi", .class = &omap44xx_rfbi_hwmod_class, @@ -1611,6 +1643,8 @@ static struct omap_hwmod omap44xx_dss_rfbi_hwmod = { .clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL, }, }, + .opt_clks = rfbi_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(rfbi_opt_clks), .slaves = omap44xx_dss_rfbi_slaves, .slaves_cnt = ARRAY_SIZE(omap44xx_dss_rfbi_slaves), .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430), @@ -1669,6 +1703,10 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = { &omap44xx_l4_per__dss_venc, }; +static struct omap_hwmod_opt_clk venc_opt_clks[] = { + { .role = "tv_clk", .clk = "dss_tv_clk" }, +}; + static struct omap_hwmod omap44xx_dss_venc_hwmod = { .name = "dss_venc", .class = &omap44xx_venc_hwmod_class, @@ -1678,6 +1716,8 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
[PATCHv2 14/28] OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET is used to avoid an unclear bug at DSS reset time. The pm runtime will handle reset in the future, and this code has to be removed. Hopefully we won't see this error anymore. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/Kconfig | 12 drivers/video/omap2/dss/dss.c | 13 - 2 files changed, 0 insertions(+), 25 deletions(-) diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 6b3e2da..0d12524 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig @@ -117,18 +117,6 @@ config OMAP2_DSS_MIN_FCK_PER_PCK Max FCK is 173MHz, so this doesn't work if your PCK is very high. -config OMAP2_DSS_SLEEP_BEFORE_RESET - bool "Sleep 50ms before DSS reset" - default y - help - For some unknown reason we may get SYNC_LOST errors from the display - subsystem at initialization time if we don't sleep before resetting - the DSS. See the source (dss.c) for more comments. - - However, 50ms is quite long time to sleep, and with some - configurations the SYNC_LOST may never happen, so the sleep can - be disabled here. - config OMAP2_DSS_SLEEP_AFTER_VENC_RESET bool "Sleep 20ms after VENC reset" default y diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index ff5664e..810ea8c 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -1037,19 +1037,6 @@ static int omap_dsshw_probe(struct platform_device *pdev) * the kernel resets it */ omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); -#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET - /* We need to wait here a bit, otherwise we sometimes start to -* get synclost errors, and after that only power cycle will -* restore DSS functionality. I have no idea why this happens. -* And we have to wait _before_ resetting the DSS, but after -* enabling clocks. -* -* This bug was at least present on OMAP3430. It's unknown -* if it happens on OMAP2 or OMAP3630. -*/ - msleep(50); -#endif - _omap_dss_reset(); /* autoidle */ -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 13/28] OMAP: DSS2: Remove core_dump_clocks
Currently dss.c does all the low level clock handling in the DSS, and thus it contains pointers to all the clocks. This allows dss.c to dump the clock information for all the clocks. With pm_runtime this is no longer the case, as each submodule will handle its clocks independently. Thus remove the core_dump_clocks function as it cannot be used with pm_runtime. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 40 1 files changed, 0 insertions(+), 40 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 4f3de35..ff5664e 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -989,50 +989,10 @@ static void dss_clk_disable_all_no_ctx(void) dss_clk_disable_no_ctx(clks); } -#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) -/* CLOCKS */ -static void core_dump_clocks(struct seq_file *s) -{ - int i; - struct clk *clocks[5] = { - dss.dss_ick, - dss.dss_fck, - dss.dss_sys_clk, - dss.dss_tv_fck, - dss.dss_video_fck - }; - - const char *names[5] = { - "ick", - "fck", - "sys_clk", - "tv_fck", - "video_fck" - }; - - seq_printf(s, "- CORE -\n"); - - seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); - - for (i = 0; i < 5; i++) { - if (!clocks[i]) - continue; - seq_printf(s, "%s (%s)%*s\t%lu\t%d\n", - names[i], - clocks[i]->name, - 24 - strlen(names[i]) - strlen(clocks[i]->name), - "", - clk_get_rate(clocks[i]), - clocks[i]->usecount); - } -} -#endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ - /* DEBUGFS */ #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) void dss_debug_dump_clocks(struct seq_file *s) { - core_dump_clocks(s); dss_dump_clocks(s); dispc_dump_clocks(s); #ifdef CONFIG_OMAP2_DSS_DSI -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 11/28] OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK
OMAP3430 requires an 96MHz clock to VENC's DAC, but no other OMAP needs it. Add a new feature, FEAT_VENC_REQUIRES_TV_DAC_CLK, which tells if the clock is needed on this platform, and use that feature in venc.c to decide if the clock needs enabling. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss_features.c |3 ++- drivers/video/omap2/dss/dss_features.h |1 + drivers/video/omap2/dss/venc.c | 16 ++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 1c1..a588380 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c @@ -286,7 +286,8 @@ static const struct omap_dss_features omap3430_dss_features = { FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | - FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC, + FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | + FEAT_VENC_REQUIRES_TV_DAC_CLK, .num_mgrs = 2, .num_ovls = 3, diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index 07b346f..3058e24 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h @@ -51,6 +51,7 @@ enum dss_feat_id { FEAT_HDMI_CTS_SWMODE= 1 << 19, FEAT_HANDLE_UV_SEPARATE = 1 << 20, FEAT_ATTR2 = 1 << 21, + FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22, }; /* DSS register field id */ diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 980f919..15b4431 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c @@ -38,6 +38,7 @@ #include #include "dss.h" +#include "dss_features.h" /* Venc registers */ #define VENC_REV_ID0x00 @@ -382,12 +383,15 @@ static void venc_reset(void) static void venc_enable_clocks(int enable) { - if (enable) - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | - DSS_CLK_VIDFCK); - else - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | - DSS_CLK_VIDFCK); + if (enable) { + dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); + if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) + dss_clk_enable(DSS_CLK_VIDFCK); + } else { + dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK); + if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) + dss_clk_disable(DSS_CLK_VIDFCK); + } } static const struct venc_config *venc_timings_to_config( -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 12/28] OMAP: DSS2: Add new FEAT definitions for features missing from OMAP2
OMAP2 doesn't have CPR, PRELOAD nor FIR_COEF_V registers. Add new feature definitions for those, and check the feature before accessing those registers. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dispc.c| 145 drivers/video/omap2/dss/dss_features.c | 12 ++- drivers/video/omap2/dss/dss_features.h |3 + drivers/video/omap2/dss/overlay.c |3 + 4 files changed, 105 insertions(+), 58 deletions(-) diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index a9eebd8..ee2052f 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -159,7 +159,8 @@ void dispc_save_context(void) SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); - SR(GLOBAL_ALPHA); + if (dss_has_feature(FEAT_GLOBAL_ALPHA)) + SR(GLOBAL_ALPHA); SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -189,20 +190,25 @@ void dispc_save_context(void) SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); + if (dss_has_feature(FEAT_CPR)) { + SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); + } if (dss_has_feature(FEAT_MGR_LCD2)) { - SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); - SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); - SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); + if (dss_has_feature(FEAT_CPR)) { + SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); + SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); + SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); + } SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); } - SR(OVL_PRELOAD(OMAP_DSS_GFX)); + if (dss_has_feature(FEAT_PRELOAD)) + SR(OVL_PRELOAD(OMAP_DSS_GFX)); /* VID1 */ SR(OVL_BA0(OMAP_DSS_VIDEO1)); @@ -227,8 +233,10 @@ void dispc_save_context(void) for (i = 0; i < 5; i++) SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); - for (i = 0; i < 8; i++) - SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); + if (dss_has_feature(FEAT_FIR_COEF_V)) { + for (i = 0; i < 8; i++) + SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); + } if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); @@ -249,7 +257,8 @@ void dispc_save_context(void) if (dss_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); - SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); + if (dss_has_feature(FEAT_PRELOAD)) + SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); /* VID2 */ SR(OVL_BA0(OMAP_DSS_VIDEO2)); @@ -274,8 +283,10 @@ void dispc_save_context(void) for (i = 0; i < 5; i++) SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); - for (i = 0; i < 8; i++) - SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); + if (dss_has_feature(FEAT_FIR_COEF_V)) { + for (i = 0; i < 8; i++) + SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); + } if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); @@ -296,7 +307,8 @@ void dispc_save_context(void) if (dss_has_feature(FEAT_ATTR2)) SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); - SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); + if (dss_has_feature(FEAT_PRELOAD)) + SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); if (dss_has_feature(FEAT_CORE_CLK_DIV)) SR(DIVISOR); @@ -318,7 +330,8 @@ void dispc_restore_context(void) RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); - RR(GLOBAL_ALPHA); + if (dss_has_feature(FEAT_GLOBAL_ALPHA)) + RR(GLOBAL_ALPHA); RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); if (dss_has_feature(FEAT_MGR_LCD2)) { @@ -348,20 +361,25 @@ void dispc_restore_context(void) RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); - RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); - RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); - RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); + if (dss_has_feature(FEAT_CPR)) { + RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); + RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); + R
[PATCHv2 10/28] OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable
DSI PLL requires sys_clk to function, and DPI enables sys_clk when it wants to use DSI PLL. However, DSI PLL code already handles enabling sys_clk, so DPI's sys_clk code is extra. Remove the unneeded sys_clk handling from dpi.c. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dpi.c | 11 +++ 1 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index ff6bd30..bab55cd 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -202,15 +202,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) goto err2; if (dpi_use_dsi_pll(dssdev)) { - dss_clk_enable(DSS_CLK_SYSCK); r = dsi_pll_init(dpi.dsidev, 0, 1); if (r) - goto err3; + goto err2; } r = dpi_set_mode(dssdev); if (r) - goto err4; + goto err3; mdelay(2); @@ -218,12 +217,9 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) return 0; -err4: - if (dpi_use_dsi_pll(dssdev)) - dsi_pll_uninit(dpi.dsidev, true); err3: if (dpi_use_dsi_pll(dssdev)) - dss_clk_disable(DSS_CLK_SYSCK); + dsi_pll_uninit(dpi.dsidev, true); err2: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); if (cpu_is_omap34xx()) @@ -242,7 +238,6 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) if (dpi_use_dsi_pll(dssdev)) { dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); dsi_pll_uninit(dpi.dsidev, true); - dss_clk_disable(DSS_CLK_SYSCK); } dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 09/28] OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss count
Initialize get_context_loss_count in the DSS board data to omap_pm_get_dev_context_loss_count, so that omapdss driver can use it. Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 084a51b..c7e19c4 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -25,6 +25,7 @@ #include #include #include +#include static struct platform_device omap_display_device = { .name = "omapdss", @@ -117,7 +118,8 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) } pdata.board_data = board_data; - pdata.board_data->get_context_loss_count = NULL; + pdata.board_data->get_context_loss_count = + omap_pm_get_dev_context_loss_count; pdata.opt_clock_available = opt_clock_available; for (i = 0; i < oh_count; i++) { -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 08/28] OMAP: DSS2: rewrite use of context_loss_count
The function to get device's context loss count has changed from omap_pm_get_last_off_on_transaction_id() to omap_pm_get_dev_context_loss_count() Change name of the function pointer in omapdss.h accordingly, and use the term "context loss count" instead of "context id" in the code. Restructure the context loss count functions to handle errors properly, and ensure that context is always considered lost if an error happens. Signed-off-by: Tomi Valkeinen --- arch/arm/mach-omap2/display.c |2 +- drivers/video/omap2/dss/dss.c | 71 +++-- drivers/video/omap2/dss/dss.h |1 - include/video/omapdss.h |2 +- 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c index 543fcb8..084a51b 100644 --- a/arch/arm/mach-omap2/display.c +++ b/arch/arm/mach-omap2/display.c @@ -117,7 +117,7 @@ int __init omap_display_init(struct omap_dss_board_info *board_data) } pdata.board_data = board_data; - pdata.board_data->get_last_off_on_transaction_id = NULL; + pdata.board_data->get_context_loss_count = NULL; pdata.opt_clock_available = opt_clock_available; for (i = 0; i < oh_count; i++) { diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 57ce428..4f3de35 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -60,7 +60,7 @@ struct dss_reg { static struct { struct platform_device *pdev; void __iomem*base; - int ctx_id; + int ctx_loss_cnt; struct clk *dpll4_m4_ck; struct clk *dss_ick; @@ -665,34 +665,58 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) } /* CONTEXT */ -static int dss_get_ctx_id(void) +static void dss_init_ctx_loss_count(void) { - struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; - int r; + struct device *dev = &dss.pdev->dev; + struct omap_display_platform_data *pdata = dev->platform_data; + struct omap_dss_board_info *board_data = pdata->board_data; + int cnt = 0; - if (!pdata->board_data->get_last_off_on_transaction_id) - return 0; - r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); - if (r < 0) { - dev_err(&dss.pdev->dev, "getting transaction ID failed, " - "will force context restore\n"); - r = -1; - } - return r; + /* +* get_context_loss_count returns negative on error. We'll ignore the +* error and store the error to ctx_loss_cnt, which will cause +* dss_need_ctx_restore() call to return true. +*/ + + if (board_data->get_context_loss_count) + cnt = board_data->get_context_loss_count(dev); + + WARN_ON(cnt < 0); + + dss.ctx_loss_cnt = cnt; + + DSSDBG("initial ctx_loss_cnt %u\n", cnt); } -int dss_need_ctx_restore(void) +static bool dss_need_ctx_restore(void) { - int id = dss_get_ctx_id(); + struct device *dev = &dss.pdev->dev; + struct omap_display_platform_data *pdata = dev->platform_data; + struct omap_dss_board_info *board_data = pdata->board_data; + int cnt; - if (id < 0 || id != dss.ctx_id) { - DSSDBG("ctx id %d -> id %d\n", - dss.ctx_id, id); - dss.ctx_id = id; - return 1; - } else { - return 0; + /* +* If get_context_loss_count is not available, assume that we need +* context restore always. +*/ + if (!board_data->get_context_loss_count) + return true; + + cnt = board_data->get_context_loss_count(dev); + if (cnt < 0) { + dev_err(dev, "getting context loss count failed, will force " + "context restore\n"); + dss.ctx_loss_cnt = cnt; + return true; } + + if (cnt == dss.ctx_loss_cnt) + return false; + + DSSDBG("ctx_loss_cnt %d -> %d\n", dss.ctx_loss_cnt, cnt); + dss.ctx_loss_cnt = cnt; + + return true; } static void save_all_ctx(void) @@ -1046,8 +1070,7 @@ static int omap_dsshw_probe(struct platform_device *pdev) dss_clk_enable_all_no_ctx(); - dss.ctx_id = dss_get_ctx_id(); - DSSDBG("initial ctx id %u\n", dss.ctx_id); + dss_init_ctx_loss_count(); /* disable LCD and DIGIT output. This seems to fix the synclost * problem that we get, if the bootloader starts the DSS and diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 8ab6d43..aeb611d 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -226,7 +226,6 @@ void dss_restore_context(void); void dss_clk_enable(enum dss_clock clks); void ds
[PATCHv2 07/28] OMAP: DSS2: Remove clk optimization at dss init
DSS enables core clocks for the duration of initialization to avoid unnecessary context saves and restores. With PM runtime the clocks cannot be handled in this way, outside the dss module drivers. Thus we need to remove the optimization. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c |4 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 02187df..f0bae6d 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -183,8 +183,6 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_dss; } - /* keep clocks enabled to prevent context saves/restores during init */ - dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); r = dispc_init_platform_driver(); if (r) { DSSERR("Failed to initialize dispc platform driver\n"); @@ -237,8 +235,6 @@ static int omap_dss_probe(struct platform_device *pdev) pdata->default_device = dssdev; } - dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); - return 0; err_register: -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 06/28] OMAP: DSS2: Init dispc first before other components
The initialization order of the DSS modules is important when pm_runtime support is implemented. Currently RFBI is initialized before DISPC, which will cause problems with pm_runtime as RFBI uses DISPC. Change the init order so that DISPC is before RFBI. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/core.c | 11 +-- 1 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 3da4267..02187df 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c @@ -185,6 +185,11 @@ static int omap_dss_probe(struct platform_device *pdev) /* keep clocks enabled to prevent context saves/restores during init */ dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); + r = dispc_init_platform_driver(); + if (r) { + DSSERR("Failed to initialize dispc platform driver\n"); + goto err_dispc; + } r = rfbi_init_platform_driver(); if (r) { @@ -192,12 +197,6 @@ static int omap_dss_probe(struct platform_device *pdev) goto err_rfbi; } - r = dispc_init_platform_driver(); - if (r) { - DSSERR("Failed to initialize dispc platform driver\n"); - goto err_dispc; - } - r = venc_init_platform_driver(); if (r) { DSSERR("Failed to initialize venc platform driver\n"); -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 05/28] OMAP: DSS2: Clean up probe for DSS & DSI
Both dss.c and dsi.c had a probe function, which was almost a dummy one, calling dss_init() and dsi_init(). Remove the init functions by moving the initialization code into probe functions. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c | 30 ++--- drivers/video/omap2/dss/dss.c | 145 ++--- 2 files changed, 69 insertions(+), 106 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 4496d09..0609885 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -4450,7 +4450,8 @@ static void dsi_calc_clock_param_ranges(struct platform_device *dsidev) dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); } -static int dsi_init(struct platform_device *dsidev) +/* DSI1 HW IP initialisation */ +static int omap_dsi1hw_probe(struct platform_device *dsidev) { struct omap_display_platform_data *dss_plat_data; struct omap_dss_board_info *board_info; @@ -4547,10 +4548,12 @@ err0: return r; } -static void dsi_exit(struct platform_device *dsidev) +static int omap_dsi1hw_remove(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + WARN_ON(dsi->scp_clk_refcount > 0); + if (dsi->vdds_dsi_reg != NULL) { if (dsi->vdds_dsi_enabled) { regulator_disable(dsi->vdds_dsi_reg); @@ -4566,29 +4569,6 @@ static void dsi_exit(struct platform_device *dsidev) kfree(dsi); - DSSDBG("omap_dsi_exit\n"); -} - -/* DSI1 HW IP initialisation */ -static int omap_dsi1hw_probe(struct platform_device *dsidev) -{ - int r; - - r = dsi_init(dsidev); - if (r) { - DSSERR("Failed to initialize DSI\n"); - goto err_dsi; - } -err_dsi: - return r; -} - -static int omap_dsi1hw_remove(struct platform_device *dsidev) -{ - struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); - - dsi_exit(dsidev); - WARN_ON(dsi->scp_clk_refcount > 0); return 0; } diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index bcd4a07..57ce428 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -664,79 +664,6 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ } -static int dss_init(void) -{ - int r; - u32 rev; - struct resource *dss_mem; - - dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); - if (!dss_mem) { - DSSERR("can't get IORESOURCE_MEM DSS\n"); - r = -EINVAL; - goto fail0; - } - dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); - if (!dss.base) { - DSSERR("can't ioremap DSS\n"); - r = -ENOMEM; - goto fail0; - } - - /* disable LCD and DIGIT output. This seems to fix the synclost -* problem that we get, if the bootloader starts the DSS and -* the kernel resets it */ - omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); - -#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET - /* We need to wait here a bit, otherwise we sometimes start to -* get synclost errors, and after that only power cycle will -* restore DSS functionality. I have no idea why this happens. -* And we have to wait _before_ resetting the DSS, but after -* enabling clocks. -* -* This bug was at least present on OMAP3430. It's unknown -* if it happens on OMAP2 or OMAP3630. -*/ - msleep(50); -#endif - - _omap_dss_reset(); - - /* autoidle */ - REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); - - /* Select DPLL */ - REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); - -#ifdef CONFIG_OMAP2_DSS_VENC - REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ - REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ - REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ -#endif - dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; - dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; - dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; - dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; - dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; - - dss_save_context(); - - rev = dss_read_reg(DSS_REVISION); - printk(KERN_INFO "OMAP DSS rev %d.%d\n", - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); - - return 0; - -fail0: - return r; -} - -static void dss_exit(void) -{ - iounmap(dss.base); -} - /* CONTEXT */ static int dss_get_ctx_id(void) { @@ -1094,10 +1021,25 @@ void dss_debug_dump_clocks(struct seq_file *s) /* DSS HW IP initialisation */ static int omap_dsshw_probe(struct platform_device *pdev) { + struct resource *dss_mem; +
[PATCHv2 04/28] OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks
Get and put for dpll4_m4_ck was handled in dss_init/dss_exit. Move the code to dss_get/put_clocks(), which is a better place to handle it. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dss.c | 52 1 files changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index d0b3f81..bcd4a07 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -669,7 +669,6 @@ static int dss_init(void) int r; u32 rev; struct resource *dss_mem; - struct clk *dpll4_m4_ck; dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); if (!dss_mem) { @@ -715,26 +714,6 @@ static int dss_init(void) REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ #endif - if (cpu_is_omap34xx()) { - dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); - if (IS_ERR(dpll4_m4_ck)) { - DSSERR("Failed to get dpll4_m4_ck\n"); - r = PTR_ERR(dpll4_m4_ck); - goto fail1; - } - } else if (cpu_is_omap44xx()) { - dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); - if (IS_ERR(dpll4_m4_ck)) { - DSSERR("Failed to get dpll4_m4_ck\n"); - r = PTR_ERR(dpll4_m4_ck); - goto fail1; - } - } else { /* omap24xx */ - dpll4_m4_ck = NULL; - } - - dss.dpll4_m4_ck = dpll4_m4_ck; - dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; @@ -749,17 +728,12 @@ static int dss_init(void) return 0; -fail1: - iounmap(dss.base); fail0: return r; } static void dss_exit(void) { - if (dss.dpll4_m4_ck) - clk_put(dss.dpll4_m4_ck); - iounmap(dss.base); } @@ -845,6 +819,7 @@ static int dss_get_clock(struct clk **clock, const char *clk_name) static int dss_get_clocks(void) { int r; + struct clk *dpll4_m4_ck; struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; dss.dss_ick = NULL; @@ -884,6 +859,27 @@ static int dss_get_clocks(void) goto err; } + if (cpu_is_omap34xx()) { + dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); + if (IS_ERR(dpll4_m4_ck)) { + DSSERR("Failed to get dpll4_m4_ck\n"); + r = PTR_ERR(dpll4_m4_ck); + goto err; + } + } else if (cpu_is_omap44xx()) { + dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); + if (IS_ERR(dpll4_m4_ck)) { + DSSERR("Failed to get dpll_per_m5x2_ck\n"); + r = PTR_ERR(dpll4_m4_ck); + goto err; + } + } else { /* omap24xx */ + dpll4_m4_ck = NULL; + } + + dss.dpll4_m4_ck = dpll4_m4_ck; + + return 0; err: @@ -897,12 +893,16 @@ err: clk_put(dss.dss_tv_fck); if (dss.dss_video_fck) clk_put(dss.dss_video_fck); + if (dss.dpll4_m4_ck) + clk_put(dss.dpll4_m4_ck); return r; } static void dss_put_clocks(void) { + if (dss.dpll4_m4_ck) + clk_put(dss.dpll4_m4_ck); if (dss.dss_video_fck) clk_put(dss.dss_video_fck); if (dss.dss_tv_fck) -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 03/28] OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use
LANEx_ULPS_SIG2 bits are left on after entering ULPS. This doesn't cause any problems currently, as DSI HW is reset when it is enabled. However, if the reset is not done, operation fails if the bits are still set. So reset the bits after entering ULPS to ensure operation even without HW reset. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/dss/dsi.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 69c2d4f..4496d09 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -3395,6 +3395,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev) dsi_unregister_isr_cio(dsidev, dsi_completion_handler, &completion, DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); + /* Reset LANEx_ULPS_SIG2 */ + REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), + 7, 5); + dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); dsi_if_enable(dsidev, false); -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 02/28] OMAP: DSS2: Taal: Make driver more fault tolerant
If ULPS exit fails, and the following reset fails also, Taal driver was left in state where it thinks DSI is enabled while it really isn't, leading to crash. This patch checks the return value of taal_panel_reset, and if that fails, ulps_enabled is left true, causing the driver to retry ulps exit later. Also the return value of taal_wake_up is checked at taal_disable, and if wake up fails, we'll skip the power_off. This could leave the panel into a not-quite-valid state, but there's nothing we can do about it in that situation. Signed-off-by: Tomi Valkeinen --- drivers/video/omap2/displays/panel-taal.c | 33 ++-- 1 files changed, 21 insertions(+), 12 deletions(-) diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index fdd5d4ae..b82bcc1 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c @@ -504,14 +504,18 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev) return 0; r = omapdss_dsi_display_enable(dssdev); - if (r) - goto err; + if (r) { + dev_err(&dssdev->dev, "failed to enable DSI\n"); + goto err1; + } omapdss_dsi_vc_enable_hs(dssdev, td->channel, true); r = _taal_enable_te(dssdev, true); - if (r) - goto err; + if (r) { + dev_err(&dssdev->dev, "failed to re-enable TE"); + goto err2; + } enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); @@ -521,13 +525,15 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev) return 0; -err: - dev_err(&dssdev->dev, "exit ULPS failed"); - r = taal_panel_reset(dssdev); - - enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); - td->ulps_enabled = false; +err2: + dev_err(&dssdev->dev, "failed to exit ULPS"); + r = taal_panel_reset(dssdev); + if (!r) { + enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); + td->ulps_enabled = false; + } +err1: taal_queue_ulps_work(dssdev); return r; @@ -1317,8 +1323,11 @@ static void taal_disable(struct omap_dss_device *dssdev) dsi_bus_lock(dssdev); if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { - taal_wake_up(dssdev); - taal_power_off(dssdev); + int r; + + r = taal_wake_up(dssdev); + if (!r) + taal_power_off(dssdev); } dsi_bus_unlock(dssdev); -- 1.7.4.1 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv2 01/28] OMAP: change get_context_loss_count ret value to int
get_context_loss_count functions return context loss count as u32, and zero means an error. However, zero is also returned when context has never been lost and could also be returned when the context loss count has wrapped and goes to zero. Change the functions to return an int, with negative value meaning an error. OMAP HSMMC code uses omap_pm_get_dev_context_loss_count(), but as the hsmmc code handles the returned value as an int, with negative value meaning an error, this patch actually fixes hsmmc code also. Signed-off-by: Tomi Valkeinen Acked-by: Kevin Hilman --- arch/arm/mach-omap2/omap_hwmod.c |2 +- arch/arm/mach-omap2/powerdomain.c | 14 ++ arch/arm/mach-omap2/powerdomain.h |2 +- arch/arm/plat-omap/include/plat/omap-pm.h |4 ++-- arch/arm/plat-omap/include/plat/omap_device.h |2 +- arch/arm/plat-omap/include/plat/omap_hwmod.h |2 +- arch/arm/plat-omap/omap-pm-noop.c | 24 +--- arch/arm/plat-omap/omap_device.c |2 +- 8 files changed, 34 insertions(+), 18 deletions(-) diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e034294..4f0d554 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -2332,7 +2332,7 @@ ohsps_unlock: * Returns the context loss count of the powerdomain assocated with @oh * upon success, or zero if no powerdomain exists for @oh. */ -u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) +int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh) { struct powerdomain *pwrdm; int ret = 0; diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 9af0847..9d53a34 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -935,16 +935,16 @@ int pwrdm_post_transition(void) * @pwrdm: struct powerdomain * to wait for * * Context loss count is the sum of powerdomain off-mode counter, the - * logic off counter and the per-bank memory off counter. Returns 0 + * logic off counter and the per-bank memory off counter. Returns negative * (and WARNs) upon error, otherwise, returns the context loss count. */ -u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm) +int pwrdm_get_context_loss_count(struct powerdomain *pwrdm) { int i, count; if (!pwrdm) { WARN(1, "powerdomain: %s: pwrdm is null\n", __func__); - return 0; + return -ENODEV; } count = pwrdm->state_counter[PWRDM_POWER_OFF]; @@ -953,7 +953,13 @@ u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm) for (i = 0; i < pwrdm->banks; i++) count += pwrdm->ret_mem_off_counter[i]; - pr_debug("powerdomain: %s: context loss count = %u\n", + /* +* Context loss count has to be a non-negative value. Clear the sign +* bit to get a value range from 0 to INT_MAX. +*/ + count &= INT_MAX; + + pr_debug("powerdomain: %s: context loss count = %d\n", pwrdm->name, count); return count; diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index d23d979..012827f 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -207,7 +207,7 @@ int pwrdm_clkdm_state_switch(struct clockdomain *clkdm); int pwrdm_pre_transition(void); int pwrdm_post_transition(void); int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); -u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm); +int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); extern void omap2xxx_powerdomains_init(void); diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index c0a7520..68df031 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -350,9 +350,9 @@ unsigned long omap_pm_cpu_get_freq(void); * driver must restore device context. If the number of context losses * exceeds the maximum positive integer, the function will wrap to 0 and * continue counting. Returns the number of context losses for this device, - * or zero upon error. + * or negative value upon error. */ -u32 omap_pm_get_dev_context_loss_count(struct device *dev); +int omap_pm_get_dev_context_loss_count(struct device *dev); void omap_pm_enable_off_mode(void); void omap_pm_disable_off_mode(void); diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index e4c349f..70d31d0 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -107,7 +107,7 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od); int omap_device_align_pm_lat(struct platform_device *pdev,
[PATCHv2 00/28] OMAP DSS runtime PM adaptation
Hi, This patch set implements runtime PM adaptation for OMAP DSS driver. This is second version of the set, changing the way pm_runtime is used. In this version the omapdss' pm_runtime adaptation is written as it should be, using pm_runtime callbacks, in which context save/restore and opt-clock enables/disables are made. This required changes (hacks?) to OMAP4 hwmod database, but it is meant to be fixed when the hwmod fmwk is improved to handle the DSS clocks properly. However, when that fix is done, omapdss driver won't need any changes. The bulk of the code is in the "OMAP: DSS2: Use PM runtime & HWMOD support" patch, which is a bit too large for comfort, but I haven't found out ways to split it up. All DSS HW modules now handle enabling and disabling of the HW block independently via pm_runtime calls. Some DSS modules also require other DSS modules, and for that we have functions like dispc_runtime_get/put() which can be used to enable that module. Previously DSS driver did reset the HW every time before taking it into use. This can no longer be done, as HWMOD framework handles the reset. While the driver works without resetting the HW, an error could render the HW inoperable and currently the driver may not be able to recover. So these patches may make the driver more unreliable on error cases. If a way to reset the HWMOD is added to the HWMOD framework, DSS driver can take it into use and the above mentioned problem should go away. Tested on OMAP4 Blaze, OMAP3 Overo, OMAP2420 N800. (However, N800 needs extra patches to get it and DSS2 running, can be found from n800 branch in my tree). The patch set still contains "OMAP: change get_context_loss_count ret value to int" for completeness, but the patch should go through Paul Walmsley. These patches can be found from: git://gitorious.org/linux-omap-dss2/linux.git pmruntime Changes in v2: * Add a HWMOD patch "OMAP4: HWMOD: change DSS main_clk scheme", which allows us to use pm_runtime as it should. * Modify "OMAP: DSS2: Use PM runtime & HWMOD support" to use pm_runtime as it should. Tomi Tomi Valkeinen (28): OMAP: change get_context_loss_count ret value to int OMAP: DSS2: Taal: Make driver more fault tolerant OMAP: DSS2: Reset LANEx_ULPS_SIG2 bits after use OMAP: DSS2: Handle dpll4_m4_ck in dss_get/put_clocks OMAP: DSS2: Clean up probe for DSS & DSI OMAP: DSS2: Init dispc first before other components OMAP: DSS2: Remove clk optimization at dss init OMAP: DSS2: rewrite use of context_loss_count OMAP: DSS2: Use omap_pm_get_dev_context_loss_count to get ctx loss count OMAP: DSS2: DPI: remove unneeded SYSCK enable/disable OMAP: DSS2: Add FEAT_VENC_REQUIRES_TV_DAC_CLK OMAP: DSS2: Add new FEAT definitions for features missing from OMAP2 OMAP: DSS2: Remove core_dump_clocks OMAP: DSS2: Remove CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET OMAP4: HWMOD: Modify DSS opt clocks OMAP3: HWMOD: Add DSS opt clocks OMAP2420: HWMOD: Add DSS opt clocks OMAP2430: HWMOD: Add DSS opt clocks OMAP4: HWMOD: change DSS main_clk scheme OMAP: DSS2: Use PM runtime & HWMOD support OMAP4: HWMOD: Remove unneeded DSS opt clocks OMAP: DSS2: Remove unused opt_clock_available OMAP: DSS2: DISPC: remove finegrained clk enables/disables OMAP: DSS2: Remove unused code from display.c OMAP: DSS2: Remove ctx loss count from dss.c OMAP4: CLKDEV: Remove omapdss clock aliases OMAP: DSS2: DISPC: Fix context save/restore OMAP: DSS2: DSS: Fix context save/restore arch/arm/mach-omap2/clock44xx_data.c | 10 +- arch/arm/mach-omap2/display.c | 26 +- arch/arm/mach-omap2/omap_hwmod.c |2 +- arch/arm/mach-omap2/omap_hwmod_2420_data.c| 19 + arch/arm/mach-omap2/omap_hwmod_2430_data.c| 19 + arch/arm/mach-omap2/omap_hwmod_3xxx_data.c| 37 ++- arch/arm/mach-omap2/omap_hwmod_44xx_data.c| 71 +++- arch/arm/mach-omap2/powerdomain.c | 14 +- arch/arm/mach-omap2/powerdomain.h |2 +- arch/arm/plat-omap/include/plat/omap-pm.h |4 +- arch/arm/plat-omap/include/plat/omap_device.h |2 +- arch/arm/plat-omap/include/plat/omap_hwmod.h |2 +- arch/arm/plat-omap/omap-pm-noop.c | 24 +- arch/arm/plat-omap/omap_device.c |2 +- drivers/video/omap2/displays/panel-taal.c | 33 +- drivers/video/omap2/dss/Kconfig | 12 - drivers/video/omap2/dss/core.c| 15 +- drivers/video/omap2/dss/dispc.c | 483 +++-- drivers/video/omap2/dss/dpi.c | 73 ++-- drivers/video/omap2/dss/dsi.c | 262 +++- drivers/video/omap2/dss/dss.c | 583 ++--- drivers/video/omap2/dss/dss.h | 34 +- drivers/video/omap2/dss/dss_features.c| 13 +- drivers/video/omap2/dss/dss_features.h|4 + drivers/video/omap2/dss/hdmi.c| 161 +-- drivers/video/omap
Re: [linux-pm] calling runtime PM from system PM methods
On Wed, 8 Jun 2011, Kevin Hilman wrote: > "Rafael J. Wysocki" writes: > > [...] > > > you need to separate the system suspend handling from runtime PM. > > /me risks getting yelled at again and jumps back in ;) > > > Each of them requires a different approach, because the goal is really > > different in both cases (basically, runtime PM triggers when the > > device is _known_ to be idle, while system suspend may trigger while > > it's actually being used). > > OK, but from the driver's perspective, the goals do not seem all that > different to me: > > Runtime suspend > 1. activity > 2. activity finishes > 3. device is _known_ to be idle > 4. trigger device low-power transition > > system suspend [echo mem > /sys/power/state] > 1. activity > 2. prevent future activity, halt/wait for current activity > 3. device is _known_ to be idle > 4. trigger device low-power transition > > The only difference is step 2. That _is_ the main difference, and it's a big one. (As Magnus pointed out, wakeup-enabling is another difference). > In runtime suspend, the activity > finishes on its own, in system suspend, the activity is forcibly > stopped. In either case, after that point the device is known to be > idle, and proceeding from there is identical. IOW, based on the above, > another way of looking at system PM is forcing idle so that runtime PM > can happen. > > I think it's important to note the similarities as well as the > differences. Maybe I'm still really blind here, but I cannot see how > they can be completely decoupled. They don't have to be decoupled, and indeed they can share code. The point Rafael and I are making is that they have to use different callback pointers, which gives you a chance to handle the differences as well as the similarities. > More specifically, what should be the approach in system suspend when a > device is already runtime suspended? If you treat runtime and system PM > as completely independent, you would have to runtime resume the device > so that it can then be immediately system suspended. Assuming the wakeup setting is correct, and assuming you use the same power level for runtime suspend and system suspend, then nothing needs to be done. If the wakeup setting is not correct, it has to be changed. That often implies going back to full power in order to change the wakeup setting, then going to low power again. This is all described in various files under Documentation/power/, in particular, devices.txt and runtime_pm.txt. > For many (if not all) devices though, what I suspect we would want is > for devices that are runtime suspended to stay runtime suspended across > a system suspend *and* resume. That would mean that the device power > domain would not call system PM callbacks on devices that are runtime > suspended. No, it's generally agreed that _all_ devices should return to full power during system resume -- even if they were runtime suspended before the system sleep. This also is explained in the Documentation files. > At least for device power domains where the low-power state is identical > between runtime suspend and system suspend, this makes a lot of sense > (to me.) Device power domain ->suspend might look something like this > (obviously not tested): > > if (pm_runtime_suspended(dev)) > return; You could test priv->flags here instead. But I suppose this would work. > pm_generic_suspend(dev); No, you shouldn't call the PM core here. > magic_device_idle(dev); /* HW-specific, shared with runtime PM */ At this point you should call magic_device_set_low_power(dev). That routine can also be shared with runtime PM. > priv->flags |= MY_DEVICE_SYS_SUSPENDED; I don't see any point in having separate flags for system suspend and runtime suspend. Just use MY_DEVICE_IS_SUSPENDED, and set it in the magic_device_set_low_power routine. > and ->resume(): > >if (priv->flags & MY_DEVICE_SYS_SUSPENDED) { >magic_device_enable(dev); >pm_generic_resume(dev); > } This should simply be: magic_device_set_full_power(dev); // clears MY_DEVICE_IS_SUSPENDED magic_device_enable(dev); Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
HELP:How to power down TWL5030 Voice/Bluetooth sidetone PGA?
Hello, I want to power down Voice/Bluetooth sidetone PGA of TWL5030. I set the VSTPGA Register/BTSTPGA Register to 0x00,but it seems that the Voice/Bluetooth sidetone PGA still work, and even set VSTPGA/BTSTPGA to Mute,there still have sidetone come out. How can I power down Voice/Bluetooth sidetone PGA? I don't need sidetone. thanks! -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
HELP:How to power down TWL5030 Voice/Bluetooth sidetone PGA?
Hello, I want to power down Voice/Bluetooth sidetone PGA of TWL5030. I set the VSTPGA Register/BTSTPGA Register to 0x00,but it seems that the Voice/Bluetooth sidetone PGA still work, and even set VSTPGA/BTSTPGA to Mute,there still have sidetone come out. How can I power down Voice/Bluetooth sidetone PGA? I don't need sidetone. thanks! -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 01/12] OMAP: New twl-common for common TWL configuration
Introduce a new file, which will be used to configure common pmic (TWL) devices, regulators, and TWL audio. Signed-off-by: Peter Ujfalusi --- arch/arm/mach-omap2/Makefile |2 +- arch/arm/mach-omap2/common-board-devices.c | 21 - arch/arm/mach-omap2/common-board-devices.h | 26 +-- arch/arm/mach-omap2/twl-common.c | 46 arch/arm/mach-omap2/twl-common.h | 28 + 5 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 arch/arm/mach-omap2/twl-common.c create mode 100644 arch/arm/mach-omap2/twl-common.h diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index b148077..fee192e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -269,4 +269,4 @@ obj-$(CONFIG_ARCH_OMAP4)+= hwspinlock.o disp-$(CONFIG_OMAP2_DSS) := display.o obj-y += $(disp-m) $(disp-y) -obj-y += common-board-devices.o +obj-y += common-board-devices.o twl-common.o diff --git a/arch/arm/mach-omap2/common-board-devices.c b/arch/arm/mach-omap2/common-board-devices.c index 94ccf46..5e03b2e 100644 --- a/arch/arm/mach-omap2/common-board-devices.c +++ b/arch/arm/mach-omap2/common-board-devices.c @@ -20,36 +20,15 @@ * */ -#include -#include - #include #include #include -#include #include #include #include "common-board-devices.h" -static struct i2c_board_info __initdata pmic_i2c_board_info = { - .addr = 0x48, - .flags = I2C_CLIENT_WAKE, -}; - -void __init omap_pmic_init(int bus, u32 clkrate, - const char *pmic_type, int pmic_irq, - struct twl4030_platform_data *pmic_data) -{ - strncpy(pmic_i2c_board_info.type, pmic_type, - sizeof(pmic_i2c_board_info.type)); - pmic_i2c_board_info.irq = pmic_irq; - pmic_i2c_board_info.platform_data = pmic_data; - - omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1); -} - #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE) static struct omap2_mcspi_device_config ads7846_mcspi_config = { diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h index 6797190..a0b4a428 100644 --- a/arch/arm/mach-omap2/common-board-devices.h +++ b/arch/arm/mach-omap2/common-board-devices.h @@ -1,33 +1,11 @@ #ifndef __OMAP_COMMON_BOARD_DEVICES__ #define __OMAP_COMMON_BOARD_DEVICES__ +#include "twl-common.h" + #define NAND_BLOCK_SIZESZ_128K -struct twl4030_platform_data; struct mtd_partition; - -void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq, - struct twl4030_platform_data *pmic_data); - -static inline void omap2_pmic_init(const char *pmic_type, - struct twl4030_platform_data *pmic_data) -{ - omap_pmic_init(2, 2600, pmic_type, INT_24XX_SYS_NIRQ, pmic_data); -} - -static inline void omap3_pmic_init(const char *pmic_type, - struct twl4030_platform_data *pmic_data) -{ - omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data); -} - -static inline void omap4_pmic_init(const char *pmic_type, - struct twl4030_platform_data *pmic_data) -{ - /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */ - omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data); -} - struct ads7846_platform_data; void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce, diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c new file mode 100644 index 000..4f7b24c --- /dev/null +++ b/arch/arm/mach-omap2/twl-common.c @@ -0,0 +1,46 @@ +/* + * twl-common.c + * + * Copyright (C) 2011 Texas Instruments, Inc.. + * Author: Peter Ujfalusi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include +#include +#include + +#include + +#include "twl-common.h" + +static struct i2c_board_info __initdata pmic_i2c_board_info = { + .addr = 0x48, + .flags = I2C_CLIENT_WAKE, +}; + +void __init omap_pmic_init(int bus, u32 clkrate, +
[PATCH v3 03/12] OMAP3: Move common twl configuration to twl-common
Reduce the amount of duplicated code by moving the common configuration for twl4030/5030/tpsxx to the twl-common file. Use the omap3_pmic_get_config function from board files to properly configure the PMIC with the common fields. Signed-off-by: Peter Ujfalusi --- arch/arm/mach-omap2/board-3430sdp.c | 42 ++-- arch/arm/mach-omap2/board-cm-t35.c |9 + arch/arm/mach-omap2/board-devkit8000.c | 18 + arch/arm/mach-omap2/board-igep0020.c | 20 ++ arch/arm/mach-omap2/board-ldp.c | 15 +-- arch/arm/mach-omap2/board-omap3beagle.c | 18 + arch/arm/mach-omap2/board-omap3evm.c | 24 +-- arch/arm/mach-omap2/board-omap3pandora.c | 17 +--- arch/arm/mach-omap2/board-omap3stalker.c | 24 +-- arch/arm/mach-omap2/board-omap3touchbook.c | 19 + arch/arm/mach-omap2/board-overo.c| 17 +--- arch/arm/mach-omap2/board-rm680.c|8 +--- arch/arm/mach-omap2/board-rx51-peripherals.c | 15 +-- arch/arm/mach-omap2/board-zoom-peripherals.c | 51 + arch/arm/mach-omap2/twl-common.c | 53 ++ arch/arm/mach-omap2/twl-common.h |6 +++ 16 files changed, 99 insertions(+), 257 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 5dac974..4810dcc 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -231,22 +231,6 @@ static void __init omap_3430sdp_init_early(void) omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL); } -static int sdp3430_batt_table[] = { -/* 0 C*/ -30800, 29500, 28300, 27100, -26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900, -17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100, -11600, 11200, 10800, 10400, 1, 9630, 9280, 8950, 8620, 8310, -8020, 7730, 7460, 7200, 6950, 6710, 6470, 6250, 6040, 5830, -5640, 5450, 5260, 5090, 4920, 4760, 4600, 4450, 4310, 4170, -4040, 3910, 3790, 3670, 3550 -}; - -static struct twl4030_bci_platform_data sdp3430_bci_data = { - .battery_tmp_tbl= sdp3430_batt_table, - .tblsize= ARRAY_SIZE(sdp3430_batt_table), -}; - static struct omap2_hsmmc_info mmc[] = { { .mmc= 1, @@ -292,14 +276,6 @@ static struct twl4030_gpio_platform_data sdp3430_gpio_data = { .setup = sdp3430_twl_gpio_setup, }; -static struct twl4030_usb_data sdp3430_usb_data = { - .usb_mode = T2_USB_MODE_ULPI, -}; - -static struct twl4030_madc_platform_data sdp3430_madc_data = { - .irq_line = 1, -}; - /* regulator consumer mappings */ /* ads7846 on SPI */ @@ -463,24 +439,10 @@ static struct regulator_init_data sdp3430_vpll2 = { .consumer_supplies = sdp3430_vpll2_supplies, }; -static struct twl4030_codec_audio_data sdp3430_audio; - -static struct twl4030_codec_data sdp3430_codec = { - .audio_mclk = 2600, - .audio = &sdp3430_audio, -}; - static struct twl4030_platform_data sdp3430_twldata = { - .irq_base = TWL4030_IRQ_BASE, - .irq_end= TWL4030_IRQ_END, - /* platform_data for children goes here */ - .bci= &sdp3430_bci_data, .gpio = &sdp3430_gpio_data, - .madc = &sdp3430_madc_data, .keypad = &sdp3430_kp_data, - .usb= &sdp3430_usb_data, - .codec = &sdp3430_codec, .vaux1 = &sdp3430_vaux1, .vaux2 = &sdp3430_vaux2, @@ -496,7 +458,11 @@ static struct twl4030_platform_data sdp3430_twldata = { static int __init omap3430_i2c_init(void) { /* i2c1 for PMIC only */ + omap3_pmic_get_config(&sdp3430_twldata, + TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI | + TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO, 0); omap3_pmic_init("twl4030", &sdp3430_twldata); + /* i2c2 on camera connector (for sensor control) and optional isp1301 */ omap_register_i2c_bus(2, 400, NULL, 0); /* i2c3 on display connector (for DVI, tfp410) */ diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 77456de..e867474 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -410,10 +410,6 @@ static struct regulator_init_data cm_t35_vpll2 = { .consumer_supplies = &cm_t35_vdvi_supply, }; -static struct twl4030_usb_data cm_t35_usb_data = { - .usb_mode = T2_USB_MODE_ULPI, -}; - static uint32_t cm_t35_keymap[] = { KEY(0, 0, KEY_A), KEY(0, 1, KEY_B), KEY(0, 2, KEY_LEFT), KEY(1, 0, KEY_UP), KEY(1, 1, KEY_ENTER), KEY(1, 2, KEY_DOWN), @@ -496,12 +492,8 @@ static stru
[PATCH v3 04/12] OMAP3: Move common regulator configuration to twl-common
Some regulator config can be moved out from board files, since they are close to identical. Signed-off-by: Peter Ujfalusi --- arch/arm/mach-omap2/board-3430sdp.c | 51 -- arch/arm/mach-omap2/board-cm-t35.c | 41 +++-- arch/arm/mach-omap2/board-devkit8000.c | 21 +-- arch/arm/mach-omap2/board-igep0020.c | 28 +++ arch/arm/mach-omap2/board-omap3beagle.c | 44 ++ arch/arm/mach-omap2/board-omap3evm.c | 47 +++- arch/arm/mach-omap2/board-omap3pandora.c | 44 -- arch/arm/mach-omap2/board-omap3stalker.c | 48 +++- arch/arm/mach-omap2/board-omap3touchbook.c | 40 arch/arm/mach-omap2/board-overo.c| 44 ++ arch/arm/mach-omap2/board-rx51-peripherals.c | 25 ++--- arch/arm/mach-omap2/board-zoom-peripherals.c | 41 ++--- arch/arm/mach-omap2/twl-common.c | 42 + arch/arm/mach-omap2/twl-common.h |5 +++ 14 files changed, 109 insertions(+), 412 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 4810dcc..d944a56 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -283,16 +283,6 @@ static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = { REGULATOR_SUPPLY("vcc", "spi1.0"), }; -static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = { - REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"), -}; - -/* VPLL2 for digital video outputs */ -static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { - REGULATOR_SUPPLY("vdds_dsi", "omapdss"), - REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), -}; - static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = { REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), }; @@ -409,36 +399,6 @@ static struct regulator_init_data sdp3430_vsim = { .consumer_supplies = sdp3430_vsim_supplies, }; -/* VDAC for DSS driving S-Video */ -static struct regulator_init_data sdp3430_vdac = { - .constraints = { - .min_uV = 180, - .max_uV = 180, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(sdp3430_vdda_dac_supplies), - .consumer_supplies = sdp3430_vdda_dac_supplies, -}; - -static struct regulator_init_data sdp3430_vpll2 = { - .constraints = { - .name = "VDVI", - .min_uV = 180, - .max_uV = 180, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(sdp3430_vpll2_supplies), - .consumer_supplies = sdp3430_vpll2_supplies, -}; - static struct twl4030_platform_data sdp3430_twldata = { /* platform_data for children goes here */ .gpio = &sdp3430_gpio_data, @@ -451,16 +411,19 @@ static struct twl4030_platform_data sdp3430_twldata = { .vmmc1 = &sdp3430_vmmc1, .vmmc2 = &sdp3430_vmmc2, .vsim = &sdp3430_vsim, - .vdac = &sdp3430_vdac, - .vpll2 = &sdp3430_vpll2, }; static int __init omap3430_i2c_init(void) { /* i2c1 for PMIC only */ omap3_pmic_get_config(&sdp3430_twldata, - TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI | - TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO, 0); + TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI | + TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO, + TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2); + sdp3430_twldata.vdac->constraints.apply_uV = true; + sdp3430_twldata.vpll2->constraints.apply_uV = true; + sdp3430_twldata.vpll2->constraints.name = "VDVI"; + omap3_pmic_init("twl4030", &sdp3430_twldata); /* i2c2 on camera connector (for sensor control) and optional isp1301 */ diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index e867474..2ae6afe 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -345,9 +345,6 @@ sta
[PATCH v3 05/12] MFD: twl4030-codec: Rename internals from codec to audio
In preparation of renaming the driver from twl4030-codec to twl4030-audio, first do some clean ups in the driver, which does not cause any problems outside. Signed-off-by: Peter Ujfalusi --- drivers/mfd/twl4030-codec.c | 135 ++- 1 files changed, 68 insertions(+), 67 deletions(-) diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c index 2bf4136..e1782b3 100644 --- a/drivers/mfd/twl4030-codec.c +++ b/drivers/mfd/twl4030-codec.c @@ -1,5 +1,6 @@ /* - * MFD driver for twl4030 codec submodule + * MFD driver for twl4030 audio submodule, which contains an audio codec, and + * the vibra control. * * Author: Peter Ujfalusi * @@ -31,53 +32,53 @@ #include #include -#define TWL4030_CODEC_CELLS2 +#define TWL4030_AUDIO_CELLS2 -static struct platform_device *twl4030_codec_dev; +static struct platform_device *twl4030_audio_dev; -struct twl4030_codec_resource { +struct twl4030_audio_resource { int request_count; u8 reg; u8 mask; }; -struct twl4030_codec { +struct twl4030_audio { unsigned int audio_mclk; struct mutex mutex; - struct twl4030_codec_resource resource[TWL4030_CODEC_RES_MAX]; - struct mfd_cell cells[TWL4030_CODEC_CELLS]; + struct twl4030_audio_resource resource[TWL4030_CODEC_RES_MAX]; + struct mfd_cell cells[TWL4030_AUDIO_CELLS]; }; /* * Modify the resource, the function returns the content of the register * after the modification. */ -static int twl4030_codec_set_resource(enum twl4030_codec_res id, int enable) +static int twl4030_audio_set_resource(enum twl4030_codec_res id, int enable) { - struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev); + struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev); u8 val; twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val, - codec->resource[id].reg); + audio->resource[id].reg); if (enable) - val |= codec->resource[id].mask; + val |= audio->resource[id].mask; else - val &= ~codec->resource[id].mask; + val &= ~audio->resource[id].mask; twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, - val, codec->resource[id].reg); + val, audio->resource[id].reg); return val; } -static inline int twl4030_codec_get_resource(enum twl4030_codec_res id) +static inline int twl4030_audio_get_resource(enum twl4030_codec_res id) { - struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev); + struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev); u8 val; twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &val, - codec->resource[id].reg); + audio->resource[id].reg); return val; } @@ -88,24 +89,24 @@ static inline int twl4030_codec_get_resource(enum twl4030_codec_res id) */ int twl4030_codec_enable_resource(enum twl4030_codec_res id) { - struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev); + struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev); int val; if (id >= TWL4030_CODEC_RES_MAX) { - dev_err(&twl4030_codec_dev->dev, + dev_err(&twl4030_audio_dev->dev, "Invalid resource ID (%u)\n", id); return -EINVAL; } - mutex_lock(&codec->mutex); - if (!codec->resource[id].request_count) + mutex_lock(&audio->mutex); + if (!audio->resource[id].request_count) /* Resource was disabled, enable it */ - val = twl4030_codec_set_resource(id, 1); + val = twl4030_audio_set_resource(id, 1); else - val = twl4030_codec_get_resource(id); + val = twl4030_audio_get_resource(id); - codec->resource[id].request_count++; - mutex_unlock(&codec->mutex); + audio->resource[id].request_count++; + mutex_unlock(&audio->mutex); return val; } @@ -117,31 +118,31 @@ EXPORT_SYMBOL_GPL(twl4030_codec_enable_resource); */ int twl4030_codec_disable_resource(unsigned id) { - struct twl4030_codec *codec = platform_get_drvdata(twl4030_codec_dev); + struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev); int val; if (id >= TWL4030_CODEC_RES_MAX) { - dev_err(&twl4030_codec_dev->dev, + dev_err(&twl4030_audio_dev->dev, "Invalid resource ID (%u)\n", id); return -EINVAL; } - mutex_lock(&codec->mutex); - if (!codec->resource[id].request_count) { - dev_err(&twl4030_codec_dev->dev, + mutex_lock(&audio->mutex); + if (!audio->resource[id].request_count) { +
[PATCH v3 08/12] mfd: twl6040: Add initial support
From: Misael Lopez Cruz TWL6040 IC provides analog high-end audio codec functions for handset applications. It contains several audio analog inputs and outputs as well as vibrator support. It's connected to the host processor via PDM interface for audio data communication. The audio modules are controlled by internal registers that can be accessed by I2C and PDM interface. TWL6040 MFD will be registered as a child of TWL-CORE, and will have two children of its own: twl6040-codec and twl6040-vibra. This driver is based on TWL4030 and WM8350 MFD drivers. Signed-off-by: Misael Lopez Cruz Signed-off-by: Jorge Eduardo Candelaria Signed-off-by: Margarita Olaya Cabrera Signed-off-by: Peter Ujfalusi --- arch/arm/plat-omap/include/plat/irqs.h | 12 +- drivers/mfd/Kconfig|6 + drivers/mfd/Makefile |1 + drivers/mfd/twl-core.c |5 +- drivers/mfd/twl6040-core.c | 602 drivers/mfd/twl6040-irq.c | 205 +++ include/linux/i2c/twl.h|1 + include/linux/mfd/twl6040.h| 261 ++ 8 files changed, 1088 insertions(+), 5 deletions(-) create mode 100644 drivers/mfd/twl6040-core.c create mode 100644 drivers/mfd/twl6040-irq.c create mode 100644 include/linux/mfd/twl6040.h diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index 5a25098..2cfba51 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -407,11 +407,19 @@ #endif #define TWL6030_IRQ_END(TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS) +#define TWL6040_CODEC_IRQ_BASE TWL6030_IRQ_END +#ifdef CONFIG_TWL6040_CODEC +#define TWL6040_CODEC_NR_IRQS 6 +#else +#define TWL6040_CODEC_NR_IRQS 0 +#endif +#define TWL6040_CODEC_IRQ_END (TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS) + /* Total number of interrupts depends on the enabled blocks above */ -#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END) +#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END) #define TWL_IRQ_ENDTWL4030_GPIO_IRQ_END #else -#define TWL_IRQ_ENDTWL6030_IRQ_END +#define TWL_IRQ_ENDTWL6040_CODEC_IRQ_END #endif /* GPMC related */ diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3a6f76a..ac6b4ae 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -233,6 +233,12 @@ config TWL6030_PWM Say yes here if you want support for TWL6030 PWM. This is used to control charging LED brightness. +config TWL6040_CORE + bool + depends on TWL4030_CORE && GENERIC_HARDIRQS + select MFD_CORE + default n + config MFD_STMPE bool "Support STMicroelectronics STMPE" depends on I2C=y && GENERIC_HARDIRQS diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 4cf9465..41f3b61 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL4030_POWER)+= twl4030-power.o obj-$(CONFIG_MFD_TWL4030_AUDIO)+= twl4030-audio.o obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o +obj-$(CONFIG_TWL6040_CORE) += twl6040-core.o twl6040-irq.o obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index f9d7880..a2eddc7 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -110,7 +110,7 @@ #endif #if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\ - defined(CONFIG_SND_SOC_TWL6040) || defined(CONFIG_SND_SOC_TWL6040_MODULE) + defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE) #define twl_has_codec()true #else #define twl_has_codec()false @@ -824,10 +824,9 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) return PTR_ERR(child); } - /* Phoenix codec driver is probed directly atm */ if (twl_has_codec() && pdata->audio && twl_class_is_6030()) { sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; - child = add_child(sub_chip_id, "twl6040-codec", + child = add_child(sub_chip_id, "twl6040", pdata->audio, sizeof(*pdata->audio), false, 0, 0); if (IS_ERR(child)) diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c new file mode 100644 index 000..195613c --- /dev/null +++ b/drivers/mfd/twl6040-core.c @@ -0,0 +1,602 @@ +/* + * MFD driver for TWL6040 audio device + * + * Authors:Misael Lopez Cruz + * Jorge Eduardo Candelaria + * Peter Ujfalusi + * + * Copyright: (C) 2011 Texas Instruments, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Sof
[PATCH v3 11/12] input: Add initial support for TWL6040 vibrator
From: Misael Lopez Cruz Add twl6040_vibra as a child of MFD device twl6040_codec. This implementation covers the PCM-to-PWM mode of TWL6040 vibrator module. Signed-off-by: Jorge Eduardo Candelaria Signed-off-by: Misael Lopez Cruz Signed-off-by: Peter Ujfalusi --- drivers/input/misc/Kconfig | 11 + drivers/input/misc/Makefile|1 + drivers/input/misc/twl6040-vibra.c | 428 include/linux/i2c/twl.h|8 + 4 files changed, 448 insertions(+), 0 deletions(-) create mode 100644 drivers/input/misc/twl6040-vibra.c diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 077309a..d1bf872 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -275,6 +275,17 @@ config INPUT_TWL4030_VIBRA To compile this driver as a module, choose M here. The module will be called twl4030_vibra. +config INPUT_TWL6040_VIBRA + tristate "Support for TWL6040 Vibrator" + depends on TWL4030_CORE + select TWL6040_CORE + select INPUT_FF_MEMLESS + help + This option enables support for TWL6040 Vibrator Driver. + + To compile this driver as a module, choose M here. The module will + be called twl6040_vibra. + config INPUT_UINPUT tristate "User level driver support" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 38efb2c..4da7c3a 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o +obj-$(CONFIG_INPUT_TWL6040_VIBRA) += twl6040-vibra.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c new file mode 100644 index 000..5a54515 --- /dev/null +++ b/drivers/input/misc/twl6040-vibra.c @@ -0,0 +1,428 @@ +/* + * twl6040-vibra.c - TWL6040 Vibrator driver + * + * Author: Jorge Eduardo Candelaria + * Author: Misael Lopez Cruz + * + * Copyright: (C) 2011 Texas Instruments, Inc. + * + * Based on twl4030-vibra.c by Henrik Saari + * Felipe Balbi + * Jari Vanhala + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFFECT_DIR_180_DEG 0x8000 + +/* Recommended modulation index 85% */ +#define TWL6040_VIBRA_MOD 85 + +#define TWL6040_NUM_SUPPLIES 2 + +struct vibra_info { + struct device *dev; + struct input_dev *input_dev; + struct workqueue_struct *workqueue; + struct work_struct play_work; + struct mutex mutex; + + bool enabled; + int weak_speed; + int strong_speed; + int direction; + + unsigned int vibldrv_res; + unsigned int vibrdrv_res; + unsigned int viblmotor_res; + unsigned int vibrmotor_res; + + struct regulator_bulk_data supplies[TWL6040_NUM_SUPPLIES]; + + struct twl6040 *twl6040; +}; + +static irqreturn_t twl6040_vib_irq_handler(int irq, void *data) +{ + struct vibra_info *info = data; + struct twl6040 *twl6040 = info->twl6040; + u8 status; + + status = twl6040_reg_read(twl6040, TWL6040_REG_STATUS); + if (status & TWL6040_VIBLOCDET) { + dev_warn(info->dev, "Left Vibrator overcurrent detected\n"); + twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLL, + TWL6040_VIBENAL); + } + if (status & TWL6040_VIBROCDET) { + dev_warn(info->dev, "Right Vibrator overcurrent detected\n"); + twl6040_clear_bits(twl6040, TWL6040_REG_VIBCTLR, + TWL6040_VIBENAR); + } + + return IRQ_HANDLED; +} + +static void twl6040_vibra_enable(struct vibra_info *info) +{ + struct twl6040 *twl6040 = info->twl6040; + int ret = 0; + + ret = regulator_bulk_enable(ARRAY_SIZE(info->supplies), info->supplies); + if (re
[PATCH v3 12/12] OMAP4: SDP4430: Add twl6040 vibrator platform support
Add twl4030_vibra platform data, and the needed regulators for twl6040 vibrator. Signed-off-by: Peter Ujfalusi --- arch/arm/mach-omap2/board-4430sdp.c | 48 +++ 1 files changed, 48 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 968029a..266d146 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -276,11 +277,40 @@ static struct platform_device sdp4430_lcd_device = { .id = -1, }; +static struct regulator_consumer_supply sdp4430_vbat_supply[] = { + REGULATOR_SUPPLY("vddvibl", "twl6040-vibra"), + REGULATOR_SUPPLY("vddvibr", "twl6040-vibra"), +}; + +static struct regulator_init_data sdp4430_vbat_data = { + .constraints = { + .always_on = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(sdp4430_vbat_supply), + .consumer_supplies = sdp4430_vbat_supply, +}; + +static struct fixed_voltage_config sdp4430_vbat_pdata = { + .supply_name= "VBAT", + .microvolts = 375, + .init_data = &sdp4430_vbat_data, + .gpio = -EINVAL, +}; + +static struct platform_device sdp4430_vbat = { + .name = "reg-fixed-voltage", + .id = -1, + .dev = { + .platform_data = &sdp4430_vbat_pdata, + }, +}; + static struct platform_device *sdp4430_devices[] __initdata = { &sdp4430_lcd_device, &sdp4430_gpio_keys_device, &sdp4430_leds_gpio, &sdp4430_leds_pwm, + &sdp4430_vbat, }; static struct omap_lcd_config sdp4430_lcd_config __initdata = { @@ -402,7 +432,25 @@ static struct regulator_init_data sdp4430_vusim = { }, }; +static struct twl4030_vibra_data twl6040_vibra = { + .vibldrv_res = 8, + .vibrdrv_res = 3, + .viblmotor_res = 10, + .vibrmotor_res = 10, + .vddvibl_uV = 0,/* fixed volt supply - VBAT */ + .vddvibr_uV = 0,/* fixed volt supply - VBAT */ +}; + +static struct twl4030_audio_data twl6040_audio = { + .codec = NULL, + .vibra = &twl6040_vibra, + .audpwron_gpio = 127, + .naudint_irq= OMAP44XX_IRQ_SYS_2N, + .irq_base = TWL6040_CODEC_IRQ_BASE, +}; + static struct twl4030_platform_data sdp4430_twldata = { + .audio = &twl6040_audio, /* Regulators */ .vusim = &sdp4430_vusim, .vaux1 = &sdp4430_vaux1, -- 1.7.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 09/12] ASoC: twl6040: Convert into TWL6040 MFD child
From: Misael Lopez Cruz Convert TWL6040 CODEC driver into a TWL6040 MFD child, it implies that MFD-level operations like register accesses, clock setting and power management are done through MFD APIs, not directly by CODEC driver anymore. To avoid conflicts with the other MFD child, vibrator registers are skipped in CODEC driver. Signed-off-by: Misael Lopez Cruz Signed-off-by: Jorge Eduardo Candelaria Signed-off-by: Peter Ujfalusi Acked-by: Mark Brown --- sound/soc/codecs/Kconfig |1 + sound/soc/codecs/twl6040.c | 426 +--- sound/soc/codecs/twl6040.h | 118 sound/soc/omap/sdp4430.c |2 + 4 files changed, 91 insertions(+), 456 deletions(-) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0002220..922f59f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -240,6 +240,7 @@ config SND_SOC_TWL4030 tristate config SND_SOC_TWL6040 + select TWL6040_CORE tristate config SND_SOC_UDA134X diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index ade6616..209089c 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c @@ -24,11 +24,10 @@ #include #include #include -#include -#include #include #include #include +#include #include #include @@ -77,14 +76,12 @@ struct twl6040_jack_data { /* codec private data */ struct twl6040_data { - int audpwron; - int naudint; int codec_powered; int pll; int non_lp; + unsigned int clk_in; unsigned int sysclk; struct snd_pcm_hw_constraint_list *sysclk_constraints; - struct completion ready; struct twl6040_jack_data hs_jack; struct snd_soc_codec *codec; struct workqueue_struct *workqueue; @@ -239,12 +236,13 @@ static inline void twl6040_write_reg_cache(struct snd_soc_codec *codec, static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, unsigned int reg) { + struct twl6040 *twl6040 = codec->control_data; u8 value; if (reg >= TWL6040_CACHEREGNUM) return -EIO; - twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &value, reg); + value = twl6040_reg_read(twl6040, reg); twl6040_write_reg_cache(codec, reg, value); return value; @@ -256,11 +254,13 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, static int twl6040_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { + struct twl6040 *twl6040 = codec->control_data; + if (reg >= TWL6040_CACHEREGNUM) return -EIO; twl6040_write_reg_cache(codec, reg, value); - return twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, value, reg); + return twl6040_reg_write(twl6040, reg, value); } static void twl6040_init_vio_regs(struct snd_soc_codec *codec) @@ -268,15 +268,21 @@ static void twl6040_init_vio_regs(struct snd_soc_codec *codec) u8 *cache = codec->reg_cache; int reg, i; - /* allow registers to be accessed by i2c */ - twl6040_write(codec, TWL6040_REG_ACCCTL, cache[TWL6040_REG_ACCCTL]); - for (i = 0; i < TWL6040_VIOREGNUM; i++) { reg = twl6040_vio_reg[i]; - /* skip read-only registers (ASICID, ASICREV, STATUS) */ + /* +* skip read-only registers (ASICID, ASICREV, STATUS) +* and registers shared among MFD children +*/ switch (reg) { case TWL6040_REG_ASICID: case TWL6040_REG_ASICREV: + case TWL6040_REG_INTID: + case TWL6040_REG_INTMR: + case TWL6040_REG_NCPCTL: + case TWL6040_REG_LDOCTL: + case TWL6040_REG_GPOCTL: + case TWL6040_REG_ACCCTL: case TWL6040_REG_STATUS: continue; default: @@ -293,6 +299,20 @@ static void twl6040_init_vdd_regs(struct snd_soc_codec *codec) for (i = 0; i < TWL6040_VDDREGNUM; i++) { reg = twl6040_vdd_reg[i]; + /* skip vibra and PLL registers */ + switch (reg) { + case TWL6040_REG_VIBCTLL: + case TWL6040_REG_VIBDATL: + case TWL6040_REG_VIBCTLR: + case TWL6040_REG_VIBDATR: + case TWL6040_REG_HPPLLCTL: + case TWL6040_REG_LPPLLCTL: + case TWL6040_REG_LPPLLDIV: + continue; + default: + break; + } + twl6040_write(codec, reg, cache[reg]); } } @@ -596,88 +616,6 @@ static int pga_event(struct snd_soc_dapm_widget *w, return 0; } -/* twl6040 codec manual power-up sequence */ -static void twl6040_power_up(struct snd_soc_codec *codec) -{ - u8 ncpctl, ldoctl, lppllctl, accct
[PATCH v3 10/12] MFD: twl6040: Change platform data for soc codec driver
Pass twl4030_codec_data instead of the twl4030_audio_data for the ASoC codec driver. Signed-off-by: Peter Ujfalusi --- drivers/mfd/twl6040-core.c |5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c index 195613c..b6e5338 100644 --- a/drivers/mfd/twl6040-core.c +++ b/drivers/mfd/twl6040-core.c @@ -507,9 +507,8 @@ static int __devinit twl6040_probe(struct platform_device *pdev) if (pdata->codec) { cell = &twl6040->cells[children]; cell->name = "twl6040-codec"; - /* The codec expects the twl4030_audio_data as platform data */ - cell->platform_data = pdata; - cell->pdata_size = sizeof(*pdata); + cell->platform_data = pdata->codec; + cell->pdata_size = sizeof(*pdata->codec); children++; } -- 1.7.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 07/12] MFD: twl4030-audio: Rename platform data
Allign the platform data names for twl4030 audio submodule: twl4030_audio_data: for the core MFD driver twl4030_codec_data: for ASoC codec driver twl4030_vibra_data: for the input/ForceFeedback driver To avoid breakage, change all depending drivers, files to use the new types. Signed-off-by: Peter Ujfalusi --- arch/arm/mach-omap2/board-rx51-peripherals.c |6 +++--- arch/arm/mach-omap2/board-zoom-peripherals.c | 10 +- arch/arm/mach-omap2/twl-common.c | 10 +- drivers/input/misc/twl4030-vibra.c |2 +- drivers/mfd/twl-core.c |8 drivers/mfd/twl4030-audio.c |8 include/linux/i2c/twl.h | 12 ++-- sound/soc/codecs/twl4030.c |6 +++--- sound/soc/codecs/twl6040.c |2 +- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index dfaf874..a2d3e19 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -738,11 +738,11 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = { .resource_config = twl4030_rconfig, }; -struct twl4030_codec_vibra_data rx51_vibra_data __initdata = { +struct twl4030_vibra_data rx51_vibra_data __initdata = { .coexist= 0, }; -struct twl4030_codec_data rx51_codec_data __initdata = { +struct twl4030_audio_data rx51_audio_data __initdata = { .audio_mclk = 2600, .vibra = &rx51_vibra_data, }; @@ -752,7 +752,7 @@ static struct twl4030_platform_data rx51_twldata __initdata = { .gpio = &rx51_gpio_data, .keypad = &rx51_kp_data, .power = &rx51_t2scripts_data, - .codec = &rx51_codec_data, + .audio = &rx51_audio_data, .vaux1 = &rx51_vaux1, .vaux2 = &rx51_vaux2, diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index 8853dc4..6d44409 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -282,12 +282,12 @@ static int __init omap_i2c_init(void) TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2); if (machine_is_omap_zoom2()) { - struct twl4030_codec_audio_data *audio_data; - audio_data = zoom_twldata.codec->audio; + struct twl4030_codec_data *codec_data; + codec_data = zoom_twldata.audio->codec; - audio_data->ramp_delay_value = 3; /* 161 ms */ - audio_data->hs_extmute = 1; - audio_data->set_hs_extmute = zoom2_set_hs_extmute; + codec_data->ramp_delay_value = 3; /* 161 ms */ + codec_data->hs_extmute = 1; + codec_data->set_hs_extmute = zoom2_set_hs_extmute; } omap_pmic_init(1, 2400, "twl5030", INT_34XX_SYS_NIRQ, &zoom_twldata); omap_register_i2c_bus(2, 400, NULL, 0); diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index f15f880..ca219ea 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -80,11 +80,11 @@ static struct twl4030_madc_platform_data omap3_madc_pdata = { .irq_line = 1, }; -static struct twl4030_codec_audio_data omap3_audio; +static struct twl4030_codec_data omap3_codec; -static struct twl4030_codec_data omap3_codec_pdata = { +static struct twl4030_audio_data omap3_audio_pdata = { .audio_mclk = 2600, - .audio = &omap3_audio, + .codec = &omap3_codec, }; static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = { @@ -292,8 +292,8 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data, if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc) pmic_data->madc = &omap3_madc_pdata; - if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->codec) - pmic_data->codec = &omap3_codec_pdata; + if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio) + pmic_data->audio = &omap3_audio_pdata; /* Common regulator configurations */ if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac) diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 7abca85..3c1a432 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -196,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, static int __devinit twl4030_vibra_probe(struct platform_device *pdev) { - struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; + struct twl4030_vibra_data *pdata = pdev->dev
[PATCH v3 06/12] MFD: twl4030-codec -> twl4030-audio: Rename the driver
Rename the driver, and header file from twl4030-codec to twl4030-audio. To avoid breakage change depending drivers at the same time. Signed-off-by: Peter Ujfalusi CC: Misael Lopez Cruz --- drivers/input/misc/Kconfig |2 +- drivers/input/misc/twl4030-vibra.c | 10 +- drivers/mfd/Kconfig|2 +- drivers/mfd/Makefile |2 +- drivers/mfd/twl4030-audio.c| 277 +++ drivers/mfd/twl4030-codec.c| 278 include/linux/mfd/twl4030-audio.h | 272 +++ include/linux/mfd/twl4030-codec.h | 272 --- sound/soc/codecs/Kconfig |2 +- sound/soc/codecs/twl4030.c | 16 +- sound/soc/omap/sdp3430.c |2 +- sound/soc/omap/zoom2.c |2 +- 12 files changed, 568 insertions(+), 569 deletions(-) create mode 100644 drivers/mfd/twl4030-audio.c delete mode 100644 drivers/mfd/twl4030-codec.c create mode 100644 include/linux/mfd/twl4030-audio.h delete mode 100644 include/linux/mfd/twl4030-codec.h diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 45dc6aa..077309a 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -267,7 +267,7 @@ config INPUT_TWL4030_PWRBUTTON config INPUT_TWL4030_VIBRA tristate "Support for TWL4030 Vibrator" depends on TWL4030_CORE - select TWL4030_CODEC + select MFD_TWL4030_AUDIO select INPUT_FF_MEMLESS help This option enables support for TWL4030 Vibrator Driver. diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 014dd4a..7abca85 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include @@ -67,7 +67,7 @@ static void vibra_enable(struct vibra_info *info) { u8 reg; - twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); + twl4030_audio_enable_resource(TWL4030_AUDIO_RES_POWER); /* turn H-Bridge on */ twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, @@ -75,7 +75,7 @@ static void vibra_enable(struct vibra_info *info) twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); - twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); + twl4030_audio_enable_resource(TWL4030_AUDIO_RES_APLL); info->enabled = true; } @@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info) twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); - twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); - twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); + twl4030_audio_disable_resource(TWL4030_AUDIO_RES_APLL); + twl4030_audio_disable_resource(TWL4030_AUDIO_RES_POWER); info->enabled = false; } diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 0f09c05..3a6f76a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -218,7 +218,7 @@ config TWL4030_POWER and load scripts controlling which resources are switched off/on or reset when a sleep, wakeup or warm reset event occurs. -config TWL4030_CODEC +config MFD_TWL4030_AUDIO bool depends on TWL4030_CORE select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index efe3cc3..4cf9465 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_MENELAUS)+= menelaus.o obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o obj-$(CONFIG_TWL4030_POWER)+= twl4030-power.o -obj-$(CONFIG_TWL4030_CODEC)+= twl4030-codec.o +obj-$(CONFIG_MFD_TWL4030_AUDIO)+= twl4030-audio.o obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c new file mode 100644 index 000..5cdf841 --- /dev/null +++ b/drivers/mfd/twl4030-audio.c @@ -0,0 +1,277 @@ +/* + * MFD driver for twl4030 audio submodule, which contains an audio codec, and + * the vibra control. + * + * Author: Peter Ujfalusi + * + * Copyright: (C) 2009 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Pu
[PATCH v3 02/12] OMAP4: Move common twl6030 configuration to twl-common
Reduce the amount of duplicated code by moving the common configuration for TWL6030 (on OMAP4 platform) to the twl-common file. Use the omap4_pmic_get_config function from board files to properly configure the PMIC with the common fields. Signed-off-by: Peter Ujfalusi --- arch/arm/mach-omap2/board-4430sdp.c| 143 ++-- arch/arm/mach-omap2/board-omap4panda.c | 149 +++--- arch/arm/mach-omap2/twl-common.c | 163 arch/arm/mach-omap2/twl-common.h | 20 4 files changed, 205 insertions(+), 270 deletions(-) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 63de2d3..968029a 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -306,14 +306,6 @@ static struct omap_musb_board_data musb_board_data = { .power = 100, }; -static struct twl4030_usb_data omap4_usbphy_data = { - .phy_init = omap4430_phy_init, - .phy_exit = omap4430_phy_exit, - .phy_power = omap4430_phy_power, - .phy_set_clock = omap4430_phy_set_clk, - .phy_suspend= omap4430_phy_suspend, -}; - static struct omap2_hsmmc_info mmc[] = { { .mmc= 2, @@ -338,12 +330,6 @@ static struct regulator_consumer_supply sdp4430_vaux_supply[] = { .dev_name = "omap_hsmmc.1", }, }; -static struct regulator_consumer_supply sdp4430_vmmc_supply[] = { - { - .supply = "vmmc", - .dev_name = "omap_hsmmc.0", - }, -}; static int omap4_twl6030_hsmmc_late_init(struct device *dev) { @@ -403,61 +389,6 @@ static struct regulator_init_data sdp4430_vaux1 = { .consumer_supplies = sdp4430_vaux_supply, }; -static struct regulator_init_data sdp4430_vaux2 = { - .constraints = { - .min_uV = 120, - .max_uV = 280, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -static struct regulator_init_data sdp4430_vaux3 = { - .constraints = { - .min_uV = 100, - .max_uV = 300, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -/* VMMC1 for MMC1 card */ -static struct regulator_init_data sdp4430_vmmc = { - .constraints = { - .min_uV = 120, - .max_uV = 300, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = 1, - .consumer_supplies = sdp4430_vmmc_supply, -}; - -static struct regulator_init_data sdp4430_vpp = { - .constraints = { - .min_uV = 180, - .max_uV = 250, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE - | REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - static struct regulator_init_data sdp4430_vusim = { .constraints = { .min_uV = 120, @@ -471,74 +402,10 @@ static struct regulator_init_data sdp4430_vusim = { }, }; -static struct regulator_init_data sdp4430_vana = { - .constraints = { - .min_uV = 210, - .max_uV = 210, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -static struct regulator_init_data sdp4430_vcxio = { - .constraints = { - .min_uV
[PATCH v3 00/12] MFD/ASoC/Input: TWL4030/TWL60X0 changes
Hello, Changes since v2: - TWL_COMMON_PDATA_AUDIO is used from the beginning, reducing changes later - twl6040 thermal shutdown handling added - pmic-common.c/h renamed as twl-common.c/h. This will allows new twl related features to be added, not directly related to pmic. - Rebased on top of linux-3.0-rc2 (l-o next, asoc next, mfd next) Updated intro message from the v2 series: The series will do four major things, and they are in one series, because they pretty much depending on each other, so it is easier to handle them together. 0. Move the common pmic related configurations out from the board files. New twl-common.c/h file has been created for this purpose. OMAP3 board files received two patches (pdata, and regualtor changes), OMAP4 board files has been changed with one patch. 1. Rename the twl4030-codec MFD driver to twl4030-audio Since the ASoC multicomponent introduction (2.6.37) the twl4030-codec MFD dirver had been using twl4030-audio to register (twl4030-codec is the ASoC codec driver). The documentation refers to this part of twl as audio block, so it is better to rename the driver as well to avoid confusion. 2. Introduction of MFD driver for twl6040. The TWL6040 audio IC has codec and vibra functionality. Convert the existing ASoC codec driver to use the new MFD driver's interface. 3. Vibrator driver for TWL6040 (Input/ForceFeedback driver) The driver itself, and support for the vibrators in SDP4430 board. Regards, Peter --- Misael Lopez Cruz (3): mfd: twl6040: Add initial support ASoC: twl6040: Convert into TWL6040 MFD child input: Add initial support for TWL6040 vibrator Peter Ujfalusi (9): OMAP: New twl-common for common TWL configuration OMAP4: Move common twl6030 configuration to twl-common OMAP3: Move common twl configuration to twl-common OMAP3: Move common regulator configuration to twl-common MFD: twl4030-codec: Rename internals from codec to audio MFD: twl4030-codec -> twl4030-audio: Rename the driver MFD: twl4030-audio: Rename platform data MFD: twl6040: Change platform data for soc codec driver OMAP4: SDP4430: Add twl6040 vibrator platform support arch/arm/mach-omap2/Makefile |2 +- arch/arm/mach-omap2/board-3430sdp.c | 89 + arch/arm/mach-omap2/board-4430sdp.c | 183 +++-- arch/arm/mach-omap2/board-cm-t35.c | 48 +-- arch/arm/mach-omap2/board-devkit8000.c | 37 +-- arch/arm/mach-omap2/board-igep0020.c | 44 +-- arch/arm/mach-omap2/board-ldp.c | 15 +- arch/arm/mach-omap2/board-omap3beagle.c | 60 +--- arch/arm/mach-omap2/board-omap3evm.c | 67 +--- arch/arm/mach-omap2/board-omap3pandora.c | 59 +--- arch/arm/mach-omap2/board-omap3stalker.c | 70 +--- arch/arm/mach-omap2/board-omap3touchbook.c | 57 +-- arch/arm/mach-omap2/board-omap4panda.c | 149 +-- arch/arm/mach-omap2/board-overo.c| 59 +--- arch/arm/mach-omap2/board-rm680.c|8 +- arch/arm/mach-omap2/board-rx51-peripherals.c | 44 +-- arch/arm/mach-omap2/board-zoom-peripherals.c | 88 + arch/arm/mach-omap2/common-board-devices.c | 21 - arch/arm/mach-omap2/common-board-devices.h | 26 +- arch/arm/mach-omap2/twl-common.c | 304 + arch/arm/mach-omap2/twl-common.h | 59 +++ arch/arm/plat-omap/include/plat/irqs.h | 12 +- drivers/input/misc/Kconfig | 13 +- drivers/input/misc/Makefile |1 + drivers/input/misc/twl4030-vibra.c | 12 +- drivers/input/misc/twl6040-vibra.c | 428 ++ drivers/mfd/Kconfig |8 +- drivers/mfd/Makefile |3 +- drivers/mfd/twl-core.c | 13 +- drivers/mfd/twl4030-audio.c | 277 drivers/mfd/twl4030-codec.c | 277 drivers/mfd/twl6040-core.c | 601 ++ drivers/mfd/twl6040-irq.c| 205 + include/linux/i2c/twl.h | 21 +- include/linux/mfd/twl4030-audio.h| 272 include/linux/mfd/twl4030-codec.h| 272 include/linux/mfd/twl6040.h | 261 +++ sound/soc/codecs/Kconfig |3 +- sound/soc/codecs/twl4030.c | 22 +- sound/soc/codecs/twl6040.c | 426 --- sound/soc/codecs/twl6040.h | 118 - sound/soc/omap/sdp3430.c |2 +- sound/soc/omap/sdp4430.c |2 + sound/soc/omap/zoom2.c |2 +- 44 files changed, 2729 insertions(+), 2011 deletions(-) create mode 100644 arch/arm/mach-omap2/twl-common.c create mode 100644 arch/arm/mach-omap2/twl-common.h create mode 100644 drivers/input/misc/twl6040-vibra.c create mo
[PATCH 3/3] HACK: OMAP: Serial: use PRCM wakeup events to enable clocks
This patch is just to test that the idea works generally, proper implementation should be done for the OMAP UART driver. Signed-off-by: Tero Kristo --- arch/arm/mach-omap2/pm44xx.c |4 arch/arm/mach-omap2/serial.c |3 +++ drivers/tty/serial/omap-serial.c |7 +++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index f70a9ad..ac6aa77 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -103,10 +103,6 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state) if (core_next_state < PWRDM_POWER_ON) { omap2_gpio_resume_after_idle(); - omap_uart_resume_idle(0); - omap_uart_resume_idle(1); - omap_uart_resume_idle(2); - omap_uart_resume_idle(3); } return; diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 6959d65..4cf8c4a 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "prm2xxx_3xxx.h" #include "pm.h" @@ -574,6 +575,8 @@ static void omap_uart_idle_init(struct omap_uart_state *uart) ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt, IRQF_SHARED, "serial idle", (void *)uart); WARN_ON(ret); + ret = omap_prcm_register_pad_irq(uart->padconf, uart->irq); + WARN_ON(ret); } void omap_uart_enable_irqs(int enable) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 0275c28..cfe2e7c 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -261,6 +261,8 @@ static void serial_omap_start_tx(struct uart_port *port) unsigned int start; int ret = 0; + omap_uart_resume_idle(up->pdev->id); + if (!up->use_dma) { serial_omap_enable_ier_thri(up); return; @@ -354,6 +356,8 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id) unsigned int iir, lsr; unsigned long flags; + omap_uart_resume_idle(up->pdev->id); + iir = serial_in(up, UART_IIR); if (iir & UART_IIR_NO_INT) return IRQ_NONE; @@ -947,6 +951,8 @@ serial_omap_console_write(struct console *co, const char *s, unsigned int ier; int locked = 1; + omap_uart_resume_idle(up->pdev->id); + local_irq_save(flags); if (up->port.sysrq) locked = 0; @@ -1303,6 +1309,7 @@ static int serial_omap_probe(struct platform_device *pdev) goto do_release_region; platform_set_drvdata(pdev, up); + pr_info("OMAP UART %d is up\n", pdev->id); return 0; err: dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n", -- 1.7.4.1 Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] PRCM: Add support for PAD wakeup interrupts
PRCM interrupt handler will now parse registered pads to see whether there is an active wakeup event. If this is the case, the corresponding interrupt will be triggered. This can be used for example with UART driver to register PAD wakeup event for the UART RX pin, and when this happens, UART interrupt will be triggered. Signed-off-by: Tero Kristo --- arch/arm/mach-omap2/prcm.c | 53 arch/arm/plat-omap/include/plat/prcm.h |3 ++ 2 files changed, 56 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c index 362c59c..754a5a6 100644 --- a/arch/arm/mach-omap2/prcm.c +++ b/arch/arm/mach-omap2/prcm.c @@ -53,6 +53,15 @@ static struct omap_prcm_irq *omap_prcm_irqs; /* Number of entries in omap_prcm_irqs */ static int omap_prcm_irqs_nr; +/* PAD handlers list */ +struct pad_def { + u32 pad; + unsigned int irq; + struct list_head node; +}; + +static LIST_HEAD(pad_handler_list); + /* Pointers to either OMAP3 or OMAP4 specific functions */ static void (*omap_prcm_mask_event)(unsigned event); static void (*omap_prcm_unmask_event)(unsigned event); @@ -84,6 +93,28 @@ static struct irq_chip prcm_irq_chip = { .irq_unmask = prcm_irq_unmask, }; + +/* + * Handler for PAD irqs, called from PRCM interrupt handler + */ +static void omap_prcm_handle_pad_irqs(void) +{ + struct pad_def *def; + u16 val = 0; + list_for_each_entry(def, &pad_handler_list, node) { + /* Read padconf value based on cpu type */ + if (cpu_is_omap34xx()) + val = omap_ctrl_readw(def->pad); + + if (cpu_is_omap44xx()) + val = omap4_ctrl_pad_readw(def->pad); + + /* if pad wakeupevent is active, fire registered IRQ */ + if (val & OMAP3_PADCONF_WAKEUPEVENT0) + generic_handle_irq(def->irq); + } +} + /* * PRCM Interrupt Handler * @@ -106,6 +137,9 @@ static void prcm_irq_handler(unsigned int irq, struct irq_desc *desc) unsigned long pending[OMAP_PRCM_MAX_NR_PENDING_REG]; struct irq_chip *chip = irq_desc_get_chip(desc); + /* Handle PAD events first, we don't want to ack them before parse */ + omap_prcm_handle_pad_irqs(); + /* * Loop until all pending irqs are handled, since * generic_handle_irq(), called by prcm_irq_handle_virtirqs() @@ -153,6 +187,25 @@ int omap_prcm_event_to_irq(const char *name) } /* + * Register interrupt handler for a given pad. When the PRCM interrupt + * handler detects wakeupevent on the corresponding pad, the IRQ will + * be triggered. + */ +int omap_prcm_register_pad_irq(u32 pad, unsigned int irq) +{ + struct pad_def *def; + + def = kmalloc(sizeof(struct pad_def), GFP_ATOMIC); + if (!def) + return -ENOMEM; + + def->pad = pad; + def->irq = irq; + list_add(&def->node, &pad_handler_list); + return 0; +} + +/* * Prepare the array of PRCM events corresponding to the current SoC, * and set-up the chained interrupt handler mechanism. */ diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h index 578..854b2de 100644 --- a/arch/arm/plat-omap/include/plat/prcm.h +++ b/arch/arm/plat-omap/include/plat/prcm.h @@ -72,6 +74,7 @@ void omap4_prcm_pending_events(unsigned long *pending); int omap_prcm_event_to_irq(const char *name); int omap_prcm_irq_init(void); void omap_prcm_irq_cleanup(void); +int omap_prcm_register_pad_irq(u32 pad, unsigned int irq); u32 omap_prcm_get_reset_sources(void); int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest, const char *name); -- 1.7.4.1 Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] omap: prcm: switch to a chained IRQ handler mechanism
Introduce a chained interrupt handler mechanism for the PRCM interrupt, so that individual PRCM event can cleanly be handled by handlers in separate drivers. We do this by introducing PRCM event names, which are then matched to the particular PRCM interrupt bit depending on the specific OMAP SoC being used. arch/arm/mach-omap2/prcm.c implements the chained interrupt mechanism itself, with individual PRCM events for OMAP3 and OMAP4 being described in arch/arm/mach-omap2/prcm3xxx.c and arch/arm/mach-omap2/prcm4xxx.c respectively. At initialization time, the set of PRCM events is filtered against the SoC on which we are running, keeping only the ones that are actually useful. All the logic is written to be generic with regard to OMAP3/OMAP4, even though OMAP3 has single PRCM event registers and OMAP4 has two PRCM event registers. The wakeup and I/O PRCM events are now handled as two separate interrupts, and their handler is registered with IRQF_NO_SUSPEND, otherwise the IRQ gets disabled during suspend, which prevents resume. Patch tested on OMAP4 blaze board, no testing done on OMAP3. Signed-off-by: Tero Kristo Cc: Thomas Petazzoni Cc: Avinash.H.M Cc: Kevin Hilman Cc: Cousson, Benoit --- arch/arm/mach-omap2/Makefile |4 + arch/arm/mach-omap2/pm34xx.c | 104 ++ arch/arm/mach-omap2/pm44xx.c | 18 +++- arch/arm/mach-omap2/prcm.c | 187 arch/arm/mach-omap2/prcm3xxx.c | 117 arch/arm/mach-omap2/prcm4xxx.c | 146 + arch/arm/plat-omap/include/plat/irqs.h |9 ++- arch/arm/plat-omap/include/plat/prcm.h | 45 8 files changed, 554 insertions(+), 76 deletions(-) create mode 100644 arch/arm/mach-omap2/prcm3xxx.c create mode 100644 arch/arm/mach-omap2/prcm4xxx.c diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 52dcc1d..6d3d527 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -40,6 +40,10 @@ AFLAGS_sram242x.o:=-Wa,-march=armv6 AFLAGS_sram243x.o :=-Wa,-march=armv6 AFLAGS_sram34xx.o :=-Wa,-march=armv7-a +# PRCM +obj-$(CONFIG_ARCH_OMAP3)+= prcm3xxx.o +obj-$(CONFIG_ARCH_OMAP4)+= prcm4xxx.o + # Pin multiplexing obj-$(CONFIG_SOC_OMAP2420) += mux2420.o obj-$(CONFIG_SOC_OMAP2430) += mux2430.o diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index dc045cc..8da13df 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -240,7 +240,7 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs) return c; } -static int _prcm_int_handle_wakeup(void) +static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused) { int c; @@ -252,64 +252,10 @@ static int _prcm_int_handle_wakeup(void) c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1); } - return c; -} - -/* - * PRCM Interrupt Handler - * - * The PRM_IRQSTATUS_MPU register indicates if there are any pending - * interrupts from the PRCM for the MPU. These bits must be cleared in - * order to clear the PRCM interrupt. The PRCM interrupt handler is - * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear - * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU - * register indicates that a wake-up event is pending for the MPU and - * this bit can only be cleared if the all the wake-up events latched - * in the various PM_WKST_x registers have been cleared. The interrupt - * handler is implemented using a do-while loop so that if a wake-up - * event occurred during the processing of the prcm interrupt handler - * (setting a bit in the corresponding PM_WKST_x register and thus - * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register) - * this would be handled. - */ -static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) -{ - u32 irqenable_mpu, irqstatus_mpu; - int c = 0; - - irqenable_mpu = omap2_prm_read_mod_reg(OCP_MOD, -OMAP3_PRM_IRQENABLE_MPU_OFFSET); - irqstatus_mpu = omap2_prm_read_mod_reg(OCP_MOD, -OMAP3_PRM_IRQSTATUS_MPU_OFFSET); - irqstatus_mpu &= irqenable_mpu; - - do { - if (irqstatus_mpu & (OMAP3430_WKUP_ST_MASK | -OMAP3430_IO_ST_MASK)) { - c = _prcm_int_handle_wakeup(); - - /* -* Is the MPU PRCM interrupt handler racing with the -* IVA2 PRCM interrupt handler ? -*/ - WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup " -"but no wakeup sources are marked\n"); - } else { - /* XXX we need to exp
[PATCH 0/3] PRCM chain interrupt handler
Hello, Following set contains PRCM chain interrupt handling for OMAP3/4. Contents of this set: - Patch 1 was initially made by Thomas Petazzoni I believe, I made some OMAP4 specific fixes on that one and updated this to conform to latest kernel APIs. This patch contains the main logic for the PRCM chain handling. - Patch 2 adds a support for chaining PRCM IO wakeup events to interrupts. This is accomplished by simply registering pad -> irq relationship and launching the interrupt handler from PRCM hardirq with generic_handle_irq(). - Patch 3 is just a hack to enable serial to work with PRCM IO wakeups, this should be written properly by someone when the initial framework (patch 1 & 2) are okay. Any comments welcome. -Tero Texas Instruments Oy, Tekniikantie 12, 02150 Espoo. Y-tunnus: 0115040-6. Kotipaikka: Helsinki -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC] dmaengine: add new api for preparing simple slave transfer
Can you please re-post with sensible wrapping at or before column 72. I'm not manually reformatting your entire message just so I can find the relevant bits to reply to. Thanks. -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC] dmaengine: add new api for preparing simple slave transfer
SDMA and EDMA are TI SoC specific DMA controllers. Their drivers have been maintained in the respective SoC folders till now. arch/arm/plat-omap/dma.c arch/arm/mach-davinci/dma.c I have gone through the existing offload engine (DMA) drivers in drivers/dma which do slave transfers. I would like to move SDMA and EDMA also to dmaengine framework. I believe that even though the dmaengine framework addresses and supports most of the required use cases of a client driver to a DMA controller, some extensions are required in it to make it still more generic. Current framework contains two APIs to prepare for slave transfers: struct dma_async_tx_descriptor *(*device_prep_slave_sg)( struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len, enum dma_data_direction direction, unsigned long flags); struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); and one control API. int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg); A simple single buffer transfer (i.e. non sg transfer) can be done only as a trivial case of the device_prep_slave_sg API. The client driver is expected to prepare a sg list and provide to the dmaengine API for that single buffer also. In a slave transfer, the client has to define all the buffer related attributes and the peripheral related attributes. The above 2 APIs in the dmaengine framework expect all the peripheral/slave related attributes to be filled in the dma_slave_config data structure. struct dma_slave_config { enum dma_data_direction direction; dma_addr_t src_addr; dma_addr_t dst_addr; enum dma_slave_buswidth src_addr_width; enum dma_slave_buswidth dst_addr_width; u32 src_maxburst; u32 dst_maxburst; }; This data structure is passed to the offload engine via the dma_chan data structure in its private pointer. Now coming to the buffer related attributes, sg list is a nice way to represent a disjoint buffer; all the offload engines in drivers/dma create a descriptor for each of the contiguous chunk in the sg list buffer and pass it to the controller. But many a times a client may want to transfer from a single buffer to the peripheral and most of the DMA controllers have the capability to transfer data in chunks/frames directly at a stretch. All the attributes of a buffer, which are required for the transfer can be programmed in single descriptor and submitted to the DMA controller. So I think the slave transfer API must also have a provision to pass the buffer configuration. The buffer attributes have to be passed directly as an argument in the prepare API, unlike dma_slave_config as they will be different for each buffer that is going to be transferred. It is a stretch and impractical to use a highly segmented buffer (like the one described below) in a sglist. This is because sg list itself is a representation of a disjoint buffer collection in terms of smaller buffers. Now then each of these smaller buffers can have different buffer configurations (like described below) and we are not going to go down that road now. Hence it makes sense to pass these buffer attributes for only a single buffer transfer and not a sg list. This can be done by OPTION #1 1. Adding a pointer of the dma_buffer_config data structure in the device_prep_slave_sg API 2. Ensuring that it will be ignored if a sg list passed. Only when a single buffer is passed (in the sg list) then this buffer configuration will be used. 3. Any client that wants to do a sg transfer can simply ignore this buffer configuration and pass NULL. The main disadvantage of this option is that all the existing drivers need to be updated since the API signature is changed. Now it might even be better to have a separate API for non sg transfers. This is OPTION #2 Advantages of this option are 1. No change required in the existing drivers that use device_prep_slave_sg API. 2. If any offload engine wants to prepare a simple buffer transfer differently and not as a trivial case of a sg list, this will be useful. I know this can be done using 2 different implementations inside the device_prep_slave_sg itself, but I think it's cleaner to have different APIs. I have provided the generic buffer configuration I can think of, here and also a new API definition, if it makes sense to have one. This buffer configuration might not be completely generic, and hence I ask all of you to please provide comments to improve it. Generic buffer description: A generic buffer can be split into number of frames which contain number of chunks inside them. The frames need not be contiguous, nor do the chunks inside a frame. -
[PATCH 7/8] OMAP: clock: Add flags to identify optional clock nodes
There is a need to identify optional clock nodes in the clock framework, so some specific sequence to enable them can be supported, which should be evident in the subsequent patches. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/clock44xx_data.c| 34 +++ arch/arm/plat-omap/include/plat/clock.h |1 + 2 files changed, 35 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 8c96567..58564fd 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -1394,6 +1394,7 @@ static struct clk bandgap_fclk = { .clkdm_name = "l4_wkup_clkdm", .parent = &sys_32k_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk des3des_fck = { @@ -1464,6 +1465,7 @@ static struct clk dss_sys_clk = { .clkdm_name = "l3_dss_clkdm", .parent = &syc_clk_div_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk dss_tv_clk = { @@ -1474,6 +1476,7 @@ static struct clk dss_tv_clk = { .clkdm_name = "l3_dss_clkdm", .parent = &extalt_clkin_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk dss_dss_clk = { @@ -1484,6 +1487,7 @@ static struct clk dss_dss_clk = { .clkdm_name = "l3_dss_clkdm", .parent = &dpll_per_m5x2_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk dss_48mhz_clk = { @@ -1494,6 +1498,7 @@ static struct clk dss_48mhz_clk = { .clkdm_name = "l3_dss_clkdm", .parent = &func_48mc_fclk, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk dss_fck = { @@ -1577,6 +1582,7 @@ static struct clk gpio1_dbclk = { .clkdm_name = "l4_wkup_clkdm", .parent = &sys_32k_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk gpio1_ick = { @@ -1597,6 +1603,7 @@ static struct clk gpio2_dbclk = { .clkdm_name = "l4_per_clkdm", .parent = &sys_32k_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk gpio2_ick = { @@ -1617,6 +1624,7 @@ static struct clk gpio3_dbclk = { .clkdm_name = "l4_per_clkdm", .parent = &sys_32k_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk gpio3_ick = { @@ -1637,6 +1645,7 @@ static struct clk gpio4_dbclk = { .clkdm_name = "l4_per_clkdm", .parent = &sys_32k_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk gpio4_ick = { @@ -1657,6 +1666,7 @@ static struct clk gpio5_dbclk = { .clkdm_name = "l4_per_clkdm", .parent = &sys_32k_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk gpio5_ick = { @@ -1677,6 +1687,7 @@ static struct clk gpio6_dbclk = { .clkdm_name = "l4_per_clkdm", .parent = &sys_32k_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk gpio6_ick = { @@ -1809,6 +1820,7 @@ static struct clk iss_ctrlclk = { .clkdm_name = "iss_clkdm", .parent = &func_96m_fclk, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk iss_fck = { @@ -2145,6 +2157,7 @@ static struct clk ocp2scp_usb_phy_phy_48m = { .clkdm_name = "l3_init_clkdm", .parent = &func_48m_fclk, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk ocp2scp_usb_phy_ick = { @@ -2206,6 +2219,7 @@ static struct clk slimbus1_fclk_1 = { .clkdm_name = "abe_clkdm", .parent = &func_24m_clk, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk slimbus1_fclk_0 = { @@ -2216,6 +2230,7 @@ static struct clk slimbus1_fclk_0 = { .clkdm_name = "abe_clkdm", .parent = &abe_24m_fclk, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk slimbus1_fclk_2 = { @@ -2226,6 +2241,7 @@ static struct clk slimbus1_fclk_2 = { .clkdm_name = "abe_clkdm", .parent = &pad_clks_ck, .recalc = &followparent_recalc, + .flags = CLOCK_OPTCLK, }; static struct clk slimbus1_slimbus_clk = { @@ -2236,6 +2252,7 @@ static struct clk slimbus1_slimbus_clk = { .clkdm_nam
[PATCH 0/8] Fix module-mode enable sequence on OMAP4
Hi, On OMAP4, the PRCM recommended sequence for enabling a module after power-on-reset is -1- Force clkdm to SW_WKUP -2- Configure desired module mode to "enable" or "auto" -3- Wait for the desired module idle status to be FUNC -4- Program clkdm in HW_AUTO(if supported) This sequence applies to all older OMAPs' as well, however since they use 'autodeps', it makes sure that no clkdm is in IDLE, and hence not requiring a force SW_WKUP when a module is being enabled. OMAP4 does not need to support autodeps, because of the dynamic dependency feature, wherein the HW takes care of waking up a clockdomain from idle and hence the module, whenever an interconnect access happens to the given module. Implementing the sequence for OMAP4 requires some of the clockdomain handling that is currently done in clock framework to be done as part of hwmod framework since the step -3- above to "Wait for the desired module idle status to be FUNC" is done as part of hwmod framework. This series moves the clockdomain handling into hwmod framework and implements the above sequence for OMAP4. The above sequence is expected to be followed even for optional clocks (steps -1-, -2- and -4- only) and that makes handling it difficult as optional clocks are enabled by drivers using direct clock framework calls and hence do not go through the hwmod framework. Hence this series also adds the handling of the sequence *only for optional clocks* in clock framework. Lastly, with this series drivers which are yet to be adapted to PM runtime and still rely on clock calls to enable/disable the respective *main* clocks are expected to be broken. MMC is one such which even breaks boot, and hence the series has a TEMP workaround patch added which keeps l3init clockdomain always force-enabled. This TEMP patch will gate all CORE low power transitions but should atleast allow MPU low power transitions to work. The series is tested for low power state transitions (RET/OFF) on OMAP3sdp and boot tested on OMAP4sdp. Applies on 3.0-rc2 Rajendra Nayak (8): OMAP2+: clockdomain: Add an api to read idle mode OMAP2+: clockdomain: Add SoC support for clkdm_is_idle OMAP2+: PM: Initialise sleep_switch to a non-valid value OMAP2+: PM: idle clkdms only if already in idle OMAP4: PM: TEMP: Prevent l3init from idling/force sleep OMAP2+: hwmod: Follow the recomended PRCM clock enable sequence OMAP: clock: Add flags to identify optional clock nodes OMAP: clock: Enable clockdomain only for optional clocks arch/arm/mach-omap2/clock.c | 30 arch/arm/mach-omap2/clock44xx_data.c| 34 +++ arch/arm/mach-omap2/clockdomain.c | 28 +- arch/arm/mach-omap2/clockdomain.h |3 ++ arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 12 + arch/arm/mach-omap2/clockdomain44xx.c | 16 ++-- arch/arm/mach-omap2/clockdomains44xx_data.c |2 +- arch/arm/mach-omap2/omap_hwmod.c| 20 +++- arch/arm/mach-omap2/pm.c|6 +++- arch/arm/plat-omap/include/plat/clock.h |1 + 10 files changed, 124 insertions(+), 28 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 8/8] OMAP: clock: Enable clockdomain only for optional clocks
Optional clocks have a requirement to have the clockdomain force enabled (SW_WKUP) before the optional clock itself is enabled. Since optional clocks are currently handled directly by drivers using the clock framework, this needs to be handled at the clock framework. This sequence is already handled in the omap_hwmod framework for the essential/main clocks. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/clock.c | 15 +++ 1 files changed, 15 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 2828d29..ff71ff7 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -286,6 +286,7 @@ void omap2_clk_disable(struct clk *clk) int omap2_clk_enable(struct clk *clk) { int ret; + int hwsup = 0; pr_debug("clock: %s: incrementing usecount\n", clk->name); @@ -304,6 +305,17 @@ int omap2_clk_enable(struct clk *clk) goto oce_err1; } } + /* +* TODO: This is needed here only as long as drivers use +* clock framework to enable optional clocks. For all the +* essential clocks, this sequence is handled in the +* omap_hwmod framework. +*/ + /* Enable the clockdomain, if its an optional clock */ + if ((clk->flags & CLOCK_OPTCLK) && (clk->clkdm)) { + hwsup = clkdm_is_idle(clk->clkdm); + clkdm_wakeup(clk->clkdm); + } if (clk->ops && clk->ops->enable) { trace_clock_enable(clk->name, 1, smp_processor_id()); @@ -315,6 +327,9 @@ int omap2_clk_enable(struct clk *clk) } } + if ((clk->flags & CLOCK_OPTCLK) && (clk->clkdm) && hwsup) + clkdm_allow_idle(clk->clkdm); + return 0; oce_err2: -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/8] OMAP2+: hwmod: Follow the recomended PRCM clock enable sequence
On OMAP4, the PRCM recommended sequence for enabling a module after power-on-reset is -1- Force clkdm to SW_WKUP -2- Configure desired module mode to "enable" or "auto" -3- Wait for the desired module idle status to be FUNC -4- Program clkdm in HW_AUTO(if supported) This sequence applies to all older OMAPs' as well, however since they use autodeps, it makes sure that no clkdm is in IDLE, and hence not requiring a force SW_WKUP when a module is being enabled. OMAP4 does not need to support autodeps, because of the dyanamic dependency feature, wherein the HW takes care of waking up a clockdomain from idle and hence the module, whenever an interconnect access happens to the given module. Implementing the sequence for OMAP4 requires the clockdomain handling that is currently done in clock framework to be done as part of hwmod framework since the step -3- above to "Wait for the desired module idle status to be FUNC" is done as part of hwmod framework. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/clock.c | 17 + arch/arm/mach-omap2/clockdomain.c |7 ++- arch/arm/mach-omap2/clockdomain44xx.c |9 + arch/arm/mach-omap2/omap_hwmod.c | 20 +++- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 180299e..2828d29 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -268,9 +268,6 @@ void omap2_clk_disable(struct clk *clk) clk->ops->disable(clk); } - if (clk->clkdm) - clkdm_clk_disable(clk->clkdm, clk); - if (clk->parent) omap2_clk_disable(clk->parent); } @@ -308,30 +305,18 @@ int omap2_clk_enable(struct clk *clk) } } - if (clk->clkdm) { - ret = clkdm_clk_enable(clk->clkdm, clk); - if (ret) { - WARN(1, "clock: %s: could not enable clockdomain %s: " -"%d\n", clk->name, clk->clkdm->name, ret); - goto oce_err2; - } - } - if (clk->ops && clk->ops->enable) { trace_clock_enable(clk->name, 1, smp_processor_id()); ret = clk->ops->enable(clk); if (ret) { WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret); - goto oce_err3; + goto oce_err2; } } return 0; -oce_err3: - if (clk->clkdm) - clkdm_clk_disable(clk->clkdm, clk); oce_err2: if (clk->parent) omap2_clk_disable(clk->parent); diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 2ab3686..b98a972 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -846,7 +846,12 @@ int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk) if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable) return -EINVAL; - if (atomic_inc_return(&clkdm->usecount) > 1) + /* +* For arch's with no autodeps, clkcm_clk_enable +* should be called for every clock instance that is +* enabled, so the clkdm can be force woken up. +*/ + if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) return 0; /* Clockdomain now has one enabled downstream clock */ diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index 4b10727..e4b8e06 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -101,14 +101,7 @@ static int omap4_clkdm_is_idle(struct clockdomain *clkdm) static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) { - bool hwsup = false; - - hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, - clkdm->cm_inst, clkdm->clkdm_offs); - - if (!hwsup) - clkdm_wakeup(clkdm); - + clkdm_wakeup(clkdm); return 0; } diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index e034294..ef709a5 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -1223,6 +1223,7 @@ static int _reset(struct omap_hwmod *oh) static int _enable(struct omap_hwmod *oh) { int r; + int hwsup = 0; if (oh->_state != _HWMOD_STATE_INITIALIZED && oh->_state != _HWMOD_STATE_IDLE && @@ -1250,10 +1251,21 @@ static int _enable(struct omap_hwmod *oh) omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED); _add_initiator_dep(oh, mpu_oh); + if (oh->_clk && oh->_clk->clkdm) { + hwsup = clkdm_is_idle(oh->_clk->clkdm); + r = clkdm_clk_enable(oh->_clk->clkdm, oh->_clk); + if (r) { + W
[PATCH 2/8] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
Add the SoC specific implemenation for clkdm_is_idle for OMAP2/3 and OMAP4. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 12 arch/arm/mach-omap2/clockdomain44xx.c |7 +++ 2 files changed, 19 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c index 48d0db7..e0c393f 100644 --- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c +++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c @@ -13,6 +13,7 @@ */ #include +#include #include #include "prm.h" #include "prm2xxx_3xxx.h" @@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm) _clkdm_del_autodeps(clkdm); } +static int omap2_clkdm_is_idle(struct clockdomain *clkdm) +{ + if (!clkdm->clktrctrl_mask) + return -EINVAL; + + return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs, + clkdm->clktrctrl_mask); +} + static void _enable_hwsup(struct clockdomain *clkdm) { if (cpu_is_omap24xx()) @@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = { .clkdm_wakeup = omap2_clkdm_wakeup, .clkdm_allow_idle = omap2_clkdm_allow_idle, .clkdm_deny_idle= omap2_clkdm_deny_idle, + .clkdm_is_idle = omap2_clkdm_is_idle, .clkdm_clk_enable = omap2_clkdm_clk_enable, .clkdm_clk_disable = omap2_clkdm_clk_disable, }; @@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = { .clkdm_wakeup = omap3_clkdm_wakeup, .clkdm_allow_idle = omap3_clkdm_allow_idle, .clkdm_deny_idle= omap3_clkdm_deny_idle, + .clkdm_is_idle = omap2_clkdm_is_idle, .clkdm_clk_enable = omap2_clkdm_clk_enable, .clkdm_clk_disable = omap2_clkdm_clk_disable, }; diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c index a1a4ecd..4b10727 100644 --- a/arch/arm/mach-omap2/clockdomain44xx.c +++ b/arch/arm/mach-omap2/clockdomain44xx.c @@ -93,6 +93,12 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm) clkdm->cm_inst, clkdm->clkdm_offs); } +static int omap4_clkdm_is_idle(struct clockdomain *clkdm) +{ + return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition, + clkdm->cm_inst, clkdm->clkdm_offs); +} + static int omap4_clkdm_clk_enable(struct clockdomain *clkdm) { bool hwsup = false; @@ -132,6 +138,7 @@ struct clkdm_ops omap4_clkdm_operations = { .clkdm_wakeup = omap4_clkdm_wakeup, .clkdm_allow_idle = omap4_clkdm_allow_idle, .clkdm_deny_idle= omap4_clkdm_deny_idle, + .clkdm_is_idle = omap4_clkdm_is_idle, .clkdm_clk_enable = omap4_clkdm_clk_enable, .clkdm_clk_disable = omap4_clkdm_clk_disable, }; -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/8] OMAP2+: clockdomain: Add an api to read idle mode
Add a clockdomain api to check if hardware supervised idle transitions are enabled on a clockdomain. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/clockdomain.c | 21 + arch/arm/mach-omap2/clockdomain.h |3 +++ 2 files changed, 24 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c index 6cb6c03..2ab3686 100644 --- a/arch/arm/mach-omap2/clockdomain.c +++ b/arch/arm/mach-omap2/clockdomain.c @@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm) arch_clkdm->clkdm_deny_idle(clkdm); } +/** + * clkdm_is_idle - Check if the clkdm hwsup/autoidle is enabled + * @clkdm: struct clockdomain * + * + * Returns true if the clockdomain is in hardware-supervised + * idle mode, or 0 otherwise. + * + */ +int clkdm_is_idle(struct clockdomain *clkdm) +{ + if (!clkdm) + return -EINVAL; + + if (!arch_clkdm || !arch_clkdm->clkdm_is_idle) + return -EINVAL; + + pr_debug("clockdomain: reading idle state for %s\n", clkdm->name); + + return arch_clkdm->clkdm_is_idle(clkdm); +} + /* Clockdomain-to-clock framework interface code */ diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h index 5823584..085ed82 100644 --- a/arch/arm/mach-omap2/clockdomain.h +++ b/arch/arm/mach-omap2/clockdomain.h @@ -138,6 +138,7 @@ struct clockdomain { * @clkdm_wakeup: Force a clockdomain to wakeup * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain + * @clkdm_is_idle: Check if hw supervised idle transitions are enabled * @clkdm_clk_enable: Put the clkdm in right state for a clock enable * @clkdm_clk_disable: Put the clkdm in right state for a clock disable */ @@ -154,6 +155,7 @@ struct clkdm_ops { int (*clkdm_wakeup)(struct clockdomain *clkdm); void(*clkdm_allow_idle)(struct clockdomain *clkdm); void(*clkdm_deny_idle)(struct clockdomain *clkdm); + int (*clkdm_is_idle)(struct clockdomain *clkdm); int (*clkdm_clk_enable)(struct clockdomain *clkdm); int (*clkdm_clk_disable)(struct clockdomain *clkdm); }; @@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); void clkdm_allow_idle(struct clockdomain *clkdm); void clkdm_deny_idle(struct clockdomain *clkdm); +int clkdm_is_idle(struct clockdomain *clkdm); int clkdm_wakeup(struct clockdomain *clkdm); int clkdm_sleep(struct clockdomain *clkdm); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/8] OMAP4: PM: TEMP: Prevent l3init from idling/force sleep
Since MMC driver is yet to be adapted to runtime PM and still uses direct clock calls to enable/disable module, its needed that the clockdomain (for MMC) is always kept force enabled since the next few patches move the clockdomain handling from clock framework to hwmod framework and break MMC. This will certainlly gate any CORE low power transitions. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/clockdomains44xx_data.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c index a607ec1..ff38764 100644 --- a/arch/arm/mach-omap2/clockdomains44xx_data.c +++ b/arch/arm/mach-omap2/clockdomains44xx_data.c @@ -493,7 +493,7 @@ static struct clockdomain l3_init_44xx_clkdm = { .dep_bit = OMAP4430_L3INIT_STATDEP_SHIFT, .wkdep_srcs = l3_init_wkup_sleep_deps, .sleepdep_srcs= l3_init_wkup_sleep_deps, - .flags= CLKDM_CAN_HWSUP_SWSUP, + .flags= CLKDM_CAN_FORCE_WAKEUP, .omap_chip= OMAP_CHIP_INIT(CHIP_IS_OMAP4430), }; -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/8] OMAP2+: PM: Initialise sleep_switch to a non-valid value
sleep_switch which is initialised to 0 in omap_set_pwrdm_state happens to be a valid sleep_switch type (FORCEWAKEUP_SWITCH) which are defined as #define FORCEWAKEUP_SWITCH 0 #define LOWPOWERSTATE_SWITCH1 This causes the function to wrongly program some clock domains even when the Powerdomain is in ON state. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/pm.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 49486f5..d48813f 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -106,7 +106,7 @@ static void omap2_init_processor_devices(void) int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) { u32 cur_state; - int sleep_switch = 0; + int sleep_switch = -1; int ret = 0; if (pwrdm == NULL || IS_ERR(pwrdm)) -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/8] OMAP2+: PM: idle clkdms only if already in idle
The omap_set_pwrdm_state function forces clockdomains to idle, without checking the existing idle state programmed, instead based solely on the HW capability of the clockdomain to support idle. This is wrong and the clockdomains should be idled post a state_switch *only* if idle transitions on the clockdomain were already enabled. Signed-off-by: Rajendra Nayak --- arch/arm/mach-omap2/pm.c |4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index d48813f..840b0e1 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -108,6 +108,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) u32 cur_state; int sleep_switch = -1; int ret = 0; + int hwsup = 0; if (pwrdm == NULL || IS_ERR(pwrdm)) return -EINVAL; @@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) { sleep_switch = LOWPOWERSTATE_SWITCH; } else { + hwsup = clkdm_is_idle(pwrdm->pwrdm_clkdms[0]); clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); pwrdm_wait_transition(pwrdm); sleep_switch = FORCEWAKEUP_SWITCH; @@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state) switch (sleep_switch) { case FORCEWAKEUP_SWITCH: - if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO) + if (hwsup) clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); else clkdm_sleep(pwrdm->pwrdm_clkdms[0]); -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] arm: omap3: beagle: Ensure msecure is mux'd to be able to set the RTC
Hello, Am 09.06.2011 09:40, schrieb Igor Grinberg: On 06/09/11 03:21, Alexander Holler wrote: I see. Is the new patch version somehow provides better functionality? You configure the gpio for output, this means that the pin is actually driven and not just relies on internal pullup (which can vary from chip to chip). I know nothing about that msecure stuff, but may be it is better to drive the pin, then just configuring the mux (enabling internal pullup)... Just using the internal pullup was enough with my BeagleBoard C4. Below is an updated version. The gpio_export() might be removed too. The original patch version is already in Linus' tree, so this one will not apply as it is. If you decide it is better then the original one, then it must be rebased. Otherwise, looks OK. I'm fine with either version, so no new patch is necessary. ;) Regards, Alexander -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] arm: omap3: beagle: Ensure msecure is mux'd to be able to set the RTC
On 06/09/11 03:21, Alexander Holler wrote: > On 08.06.2011 23:57, Igor Grinberg wrote: >> On 06/07/11 14:15, Alexander Holler wrote: >>> Am 07.06.2011 11:50, schrieb Igor Grinberg: On 06/07/11 11:01, Alexander Holler wrote: > Am 31.05.2011 12:29, schrieb Tony Lindgren: >> * Alexander Holler [110405 06:38]: >>> Without msecure beeing high it isn't possible to set (or start) >>> the RTC. >>> >>> Tested with a BeagleBoard C4. >> Adding this into fixes. >> >> Tony >> >>> Signed-off-by: Alexander Holler >>> --- >>>arch/arm/mach-omap2/board-omap3beagle.c |3 +++ >>>1 files changed, 3 insertions(+), 0 deletions(-) >>> >>> diff --git a/arch/arm/mach-omap2/board-omap3beagle.c >>> b/arch/arm/mach-omap2/board-omap3beagle.c >>> index 46d814a..ebe3a7e 100644 >>> --- a/arch/arm/mach-omap2/board-omap3beagle.c >>> +++ b/arch/arm/mach-omap2/board-omap3beagle.c >>> @@ -628,6 +628,9 @@ static void __init omap3_beagle_init(void) >>>usb_ehci_init(&ehci_pdata); >>>omap3beagle_flash_init(); >>> >>> +/* Ensure msecure is mux'd to be able to set the RTC. */ >>> +omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH); >>> + >>>/* Ensure SDRC pins are mux'd for self-refresh */ >>>omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); >>>omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT); >>> -- >>> 1.7.3.4 >>> > I've later switched to the following patch which muxes msecure as GPIO > (the drm-mode isn't explained in the TRM) and also exports the GPIO, so > root could easily switch it to prevent modifications on the RTC. > > (Warning, either my clipboard or the version of Thunderbird I'm currently > using replaces the tabs with spaces in the pasted patch and I'm currently > too lazy to search a workaround). > > --- > arch/arm/mach-omap2/board-omap3beagle.c |6 ++ > 1 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-omap2/board-omap3beagle.c > b/arch/arm/mach-omap2/board-omap3beagle.c > index 33007fd..24b4417 100644 > --- a/arch/arm/mach-omap2/board-omap3beagle.c > +++ b/arch/arm/mach-omap2/board-omap3beagle.c > @@ -673,6 +673,12 @@ static void __init omap3_beagle_init(void) > usbhs_init(&usbhs_bdata); > omap3beagle_flash_init(); > > + /* Ensure msecure is high to be able to set the RTC. */ > + omap_mux_init_signal("gpio_22", OMAP_PIN_OFF_OUTPUT_HIGH); > + gpio_request(22, "msecure"); > + gpio_direction_output(22, true); Can this be gpio_request_one() instead, please? Also, it will be nice to make a define for the magic 22. >>> You need the "gpio_22" in the mux_init, so using a define would imho >>> introduce a potential source for an error, at least when the define would >>> not be anywhere near the "gpio_22" and someone would forget change the >>> string too, when he changes the define. So I don't think a define adds much >>> value there. >> Why not leave "sys_drm_msecure" for mux_init, or does it make troubles on XM? > There is nothing wrong with the small patch which uses sys_drm_msecure. > It's short and does everything which is needed to use the RTC. I've > posted the solution with the use of the GPIO-mode only as an alternative > because the drm-mode isn't explained in the TRM (I assume one has to > sign a NDA to get more informations on that). > So it is not obvious what my first patch does. Using sys_drm_msecure > works because it seems to be always off, at least on the BeagleBoards. > The additional functionality in my second patch to turn off possible > modifications on the RTC through switching the GPIO is most likely just > an educational feature, I don't think someone will ever use that. > I don't have any preferences which solution will end in the kernel, I > just wanted to offer the second one too. I see. Is the new patch version somehow provides better functionality? You configure the gpio for output, this means that the pin is actually driven and not just relies on internal pullup (which can vary from chip to chip). I know nothing about that msecure stuff, but may be it is better to drive the pin, then just configuring the mux (enabling internal pullup)... >> What about gpio_request_one()? To conform with the rest of the file and >> mach-omap2/*. > Below is an updated version. The gpio_export() might be removed too. The original patch version is already in Linus' tree, so this one will not apply as it is. If you decide it is better then the original one, then it must be rebased. Otherwise, looks OK. > Regards, > > Alexander > > > From: Alexander Holler > Date: Thu, 19 May 2011 11:42:05 +0200 > Subject: [PATCH v3] arm: omap3: beagle: Ensure msecure is mux'd and high > to be able to set the RTC > > Witho