Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 3/3] ARM: tegra: move debug-macro.S to include/debug
From: Stephen Warren @ 2012-10-19 16:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5080088C.9090607@gmail.com>

On 10/18/2012 07:47 AM, Rob Herring wrote:
...
> Here is what I mentioned previously. This removes the static mapping from 
> the platforms. This is untested and probably breaks on different DEBUG_LL 
> options. For now, platforms call debug_ll_io_init, but once all platforms 
> are converted, this can be called from devicemaps_init.

> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c

> +void __init debug_ll_io_init(void)
> +{
> +	struct map_desc map;
> +
> +	if (!IS_ENABLED(CONFIG_DEBUG_LL))
> +		return;
> +
> +	debug_ll_addr(&map.pfn, &map.virtual);
> +	map.pfn = __phys_to_pfn(map.pfn);
> +	map.length = PAGE_SIZE;
> +	map.type = MT_DEVICE;
> +	create_mapping(&map);
> +}

OK, so I just call this new function from Tegra's tegra_map_common_io().
That looks pretty neat. I'll give it a try.

^ permalink raw reply

* [RFC PATCH v3 00/16] DMA Engine support for AM33XX
From: Matt Porter @ 2012-10-19 16:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <B5906170F1614E41A8A28DE3B8D121433EBD2CE1@DBDE01.ent.ti.com>

On Fri, Oct 19, 2012 at 12:02:42PM +0000, Bedia, Vaibhav wrote:
> On Fri, Oct 19, 2012 at 16:45:58, Porter, Matt wrote:
> > On Fri, Oct 19, 2012 at 10:26:20AM +0000, Bedia, Vaibhav wrote:
> [...]
> > > 
> > > I didn't see all the patches that you posted on edma-dmaengine-v3
> > > but I do seem them on edma-dmaengine-am33xx-v3 branch.
> > 
> > I see I referenced the wrong branch in the cover letter. Thanks for
> > testing and noticing this. Sorry to make you hunt for the correct
> > branch in that repo. ;) 
> > 
> 
> No problem.
> 
> > https://github.com/ohporter/linux/tree/edma-dmaengine-am33xx-v3
> > is indeed the correct branch for those wanting to pull this in or
> > grab some of the not-to-be-merged drivers I used for testing.
> > 
> > > I added a couple of patches to enable earlyprintk and build the DTB
> > > appended kernel image uImage-dtb.am335x-evm
> > > 
> > > Here's what i see
> > > 
> > > [...]
> > 
> > <snip>
> > 
> > > [    0.175354] edma: probe of 49000000.edma failed with error -16
> > 
> > I missed an uninitialized pdata case in the bug fixes mentioned in
> > the changelog and the folks previously failing the same way didn't
> > hit the case I suspect you are hitting. Can you try this and let me
> > know how it works?
> > 
> 
> That doesn't help :(

Ok, so I dumped my Linaro toolchain which was masking this issue that
you got unlucky with on EVM, whereas I was lucky. Switching toolchains I
was able to reproduce the problem. Pantelis Antoniou suggested some
changes and the following fixes this issue for me...verified on both
BeagleBone and EVM. Let me know if that works on your end and I'll
incorporate some version of it in the next update.

diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
index b761b7a..6ed394f 100644
--- a/arch/arm/common/edma.c
+++ b/arch/arm/common/edma.c
@@ -1598,6 +1598,8 @@ static struct of_dma_filter_info edma_filter_info = {
 static int __init edma_probe(struct platform_device *pdev)
 {
 	struct edma_soc_info	**info = pdev->dev.platform_data;
+	struct edma_soc_info	*ninfo[EDMA_MAX_CC] = {NULL, NULL};
+	struct edma_soc_info	tmpinfo;
 	s8			(*queue_priority_mapping)[2];
 	s8			(*queue_tc_mapping)[2];
 	int			i, j, off, ln, found = 0;
@@ -1614,15 +1616,13 @@ static int __init edma_probe(struct platform_device *pdev)
 	char			irq_name[10];
 	struct device_node	*node = pdev->dev.of_node;
 	struct device		*dev = &pdev->dev;
-	struct edma_soc_info	*pdata;
 	int			ret;
 
 	if (node) {
-		pdata = devm_kzalloc(dev,
-				     sizeof(struct edma_soc_info),
-				     GFP_KERNEL);
-		edma_of_parse_dt(dev, node, pdata);
-		info = &pdata;
+		info = ninfo;
+		edma_of_parse_dt(dev, node, &tmpinfo);
+		info[0] = &tmpinfo;
+
 		dma_cap_set(DMA_SLAVE, edma_filter_info.dma_cap);
 		of_dma_controller_register(dev->of_node,
 					   of_dma_simple_xlate,

> Looking at the original crash log, I suspect something is not correct
> with the irq portion, probably in the DT or the driver. 
> 
> "genirq: Flags mismatch irq 28. 00000000 (edma) vs. 00000000 (edma)"
> 
> The warning below that is coming due to fail case in edma_probe not tracking
> the request_irq status properly and but IMO that's a separate issue.

It is a separate issue, indeed. My ideal goal was to avoid changing
anything in this existing davinci dma implementation, that's why the
error paths were unmodified. Since I'm having to rework a few more things
I'll look at those and generate an improved version.

Russ Dill also made some good simplification/cleanup suggestions for the
of parsing on irc which I'll incorporate in the next version.

-Matt

^ permalink raw reply related

* OMAP baseline test results for v3.7-rc1
From: Paul Walmsley @ 2012-10-19 16:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1210180517450.8674@utopia.booyaka.com>

On Thu, 18 Oct 2012, Paul Walmsley wrote:

> Here are some basic OMAP test results for Linux v3.7-rc1.
> Logs and other details at http://www.pwsan.com/omap/testlogs/test_v3.7-rc1/

And here's two more.

> Failing tests: needing investigation
> ------------------------------------
> 
>
> Boot tests:
>
> * 2420n800: boot hangs during UART initialization
>  - http://lkml.org/lkml/2012/9/11/454
>  - Various attempts at fixes posted; etiology known; issue still unresolved
>
> * CM-T3517: L3 in-band error with IPSS during boot
>  - Cause unknown but see http://marc.info/?l=linux-omap&m=134833869730129&w=2
>  - Longstanding issue; does not occur on the 3517EVM
>
> * 3517EVM & CM-T3517: boot hangs with NFS root
>  - Likely some Kconfig, board file, and PM issues with EMAC
>
> * CM-T3517: boot hangs with MMC boot
>  - Due to missing MMC setup in board file

* 3530ES3 Beagle: I2C timeouts during userspace init
  - May be related to the threaded IRQ conversion of the I2C driver
  - Unknown cause

> PM tests:
> 
> * 3530es3beagle, 37xxevm, 3730beaglexm: I2C fails during resume from suspend
>   - Causes MMC to become unusable since regulators are not reenabled
>   - Can be worked around by reverting the I2C driver conversion to
>     threaded IRQs:
>     - http://marc.info/?l=linux-i2c&m=135026587102887&w=2
>   - Appears to be due to an accounting problem; under discussion:
>     - http://marc.info/?l=linux-arm-kernel&m=135042360725821&w=2
> 
> * 3530es3beagle: hangs during off-mode dynamic idle test
>   - Unknown cause; not investigated
> 
> * 37xx EVM: CORE not entering dynamic off-idle
>   - Cause unknown; dynamic retention-idle seems to work; system suspend to 
>     off works
> 
> * 3730 Beagle XM: does not serial wake from off-idle suspend when console
>   UART doesn't clock gate ("debug ignore_loglevel")
>   - Not shown in the current test logs; cause unknown

* 3730 Beagle XM: OPPs do not initialize
  - Several "find_device_opp: Invalid parameters" messages appear on boot; 
    related warnings follow
  - Cause unknown


- Paul

^ permalink raw reply

* OMAP baseline test results for v3.7-rc1
From: Felipe Balbi @ 2012-10-19 17:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1210191645390.10773@utopia.booyaka.com>

Hi,

On Fri, Oct 19, 2012 at 04:55:38PM +0000, Paul Walmsley wrote:
> On Thu, 18 Oct 2012, Paul Walmsley wrote:
> 
> > Here are some basic OMAP test results for Linux v3.7-rc1.
> > Logs and other details at http://www.pwsan.com/omap/testlogs/test_v3.7-rc1/
> 
> And here's two more.
> 
> > Failing tests: needing investigation
> > ------------------------------------
> > 
> >
> > Boot tests:
> >
> > * 2420n800: boot hangs during UART initialization
> >  - http://lkml.org/lkml/2012/9/11/454
> >  - Various attempts at fixes posted; etiology known; issue still unresolved
> >
> > * CM-T3517: L3 in-band error with IPSS during boot
> >  - Cause unknown but see http://marc.info/?l=linux-omap&m=134833869730129&w=2
> >  - Longstanding issue; does not occur on the 3517EVM
> >
> > * 3517EVM & CM-T3517: boot hangs with NFS root
> >  - Likely some Kconfig, board file, and PM issues with EMAC
> >
> > * CM-T3517: boot hangs with MMC boot
> >  - Due to missing MMC setup in board file
> 
> * 3530ES3 Beagle: I2C timeouts during userspace init
>   - May be related to the threaded IRQ conversion of the I2C driver
>   - Unknown cause

Doesn't seem like it's related to threaded IRQ. It says:

[   23.673858] omap_i2c omap_i2c.1: timeout waiting for bus ready

at that time we didn't even program the transfer yet, meaning we're not
even on wait_for_completion_timeout() inside omap_i2c_xfer_msg(). This
happens before:

> static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
> {
> 	unsigned long timeout;
> 
> 	timeout = jiffies + OMAP_I2C_TIMEOUT;
> 	while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
> 		if (time_after(jiffies, timeout)) {
> 			dev_warn(dev->dev, "timeout waiting for bus ready\n");

it' stopping here. And that's called...

> 			return -ETIMEDOUT;
> 		}
> 		msleep(1);
> 	}
> 
> 	return 0;
> }

[...]

> static int
> omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
> {
> 	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
> 	int i;
> 	int r;
> 
> 	r = pm_runtime_get_sync(dev->dev);
> 	if (IS_ERR_VALUE(r))
> 		goto out;
> 
> 	r = omap_i2c_wait_for_bb(dev);

right here. For whatever reason, the bus is kept busy (or at least the
driver thinks so).

Looking closely at the logs I see that definitely I2C was working during
early boot (we managed to mount file system on SD card and twl got
initialized properly). But then we have a long time where I2C isn't
used, so it probably suspended in between.

Then RTC wanted to read a register, I2C woke up, restored context, but
bus was kept busy, for whatever reason.

Does it happen all the time on multiple boots or is it ramdom ?

> 	if (r < 0)
> 		goto out;
> 
> 	/*
> 	 * When waiting for completion of a i2c transfer, we need to
> 	 * set a wake up latency constraint for the MPU. This is to
> 	 * ensure quick enough wakeup from idle, when transfer
> 	 * completes.
> 	 */
> 	if (dev->latency)
> 		pm_qos_add_request(&dev->pm_qos_request,
> 				   PM_QOS_CPU_DMA_LATENCY,
> 				   dev->latency);
> 
> 	for (i = 0; i < num; i++) {
> 		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
> 		if (r != 0)
> 			break;
> 	}
> 
> 	if (dev->latency)
> 		pm_qos_remove_request(&dev->pm_qos_request);
> 
> 	if (r == 0)
> 		r = num;
> 
> 	omap_i2c_wait_for_bb(dev);
> out:
> 	pm_runtime_mark_last_busy(dev->dev);
> 	pm_runtime_put_autosuspend(dev->dev);
> 	return r;
> }

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121019/21c960e3/attachment.sig>

^ permalink raw reply

* [PATCH] Nokia N9/N900/N950 -- mention product names
From: Tony Lindgren @ 2012-10-19 17:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121017212112.GG1613@blackmetal.musicnaut.iki.fi>

* Aaro Koskinen <aaro.koskinen@iki.fi> [121017 14:22]:
> On Wed, Oct 17, 2012 at 11:03:00PM +0200, Pavel Machek wrote:
> > 
> > This adds product names (that most users know) to Kconfig and board
> > comments.
> >  
> > Signed-off-by: Pavel Machek <pavel@ucw.cz>
> 
> Reviewed-by: Aaro Koskinen <aaro.koskinen@iki.fi>

Thanks applying into omap-for-v3.8/board branch.

Regards,

Tony

^ permalink raw reply

* [PATCH 01/10] pinctrl: use postcore_initcall
From: Tony Lindgren @ 2012-10-19 17:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAN1soZw+EzFjEcxDJfi50BEhuQqDUwsB4DMGEXg+oyU-6gO_Jw@mail.gmail.com>

* Haojian Zhuang <haojian.zhuang@gmail.com> [121018 19:54]:
> On Fri, Oct 19, 2012 at 10:38 AM, Tony Lindgren <tony@atomide.com> wrote:
> > * Haojian Zhuang <haojian.zhuang@gmail.com> [121018 19:17]:
> >> On Fri, Oct 19, 2012 at 6:28 AM, Tony Lindgren <tony@atomide.com> wrote:
> >> >
> >> > Specifically could you decribe the cases where this issue happens?
> >> > Also check if one of your client drivers has some early initcall
> >> > that's no longer needed.
> >>
> >> Yes, the special case is PMIC. Most of PMIC are based on I2C/SPI bus.
> >> It means that I2C/SPI bus driver should be initialized firstly. For example,
> >> we could find that PMIC mfd driver are initialized in subsys init call level.
> >> It means that pinctrl should be initialized earlier than I2C/SPI bus driver.
> >> Otherwise, pins of I2C bus may not be configured as I2C function since
> >> pinctrl driver is module init call level.
> >
> > Hmm, the order in drivers/Makefile is already:
> >
> > pinctrl/
> > i2c/
> >
> > Maybe check that your i2c drivers don't have non-standard initcalls?
> >
> > Also the i2c drivers may need to return -EPROBE_DEFER?
> >
> > Regards,
> >
> > Tony
> 
> OK. I'll support -EPROBE_DEFER if failed to get pin from pinctrl system.
> This solution could also resolve the issue.

OK good to hear.

Regards,

Tony

^ permalink raw reply

* [PATCH 1/1] arm: KGDB support for PXA
From: Greg KH @ 2012-10-19 17:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAN1soZwZ9fNrtJ8VFy7Y3XZVtF=6=0iRXhS7m3OCmHUtk07kWg@mail.gmail.com>

On Fri, Oct 19, 2012 at 05:47:09PM +0800, Haojian Zhuang wrote:
> On Thu, Oct 18, 2012 at 5:38 PM, Marko Kati? <dromede@gmail.com> wrote:
> > I'm still not seeing this patch in arch-pxa, tty or mainline trees.
> > Has it been forgotten again? Is there a problem with this patch that
> > needs to be fixed?
> 
> Applied into arch-pxa now.
> 
> Greg,
> 
> If you have any comment, please let me know.

No, no objection at all, the other patches are all in Linus's tree
already, so feel free to send them in whenever you want.

greg k-h

^ permalink raw reply

* OMAP baseline test results for v3.7-rc1
From: Paul Walmsley @ 2012-10-19 17:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121019170149.GG1493@arwen.pp.htv.fi>

Hi Felipe,

On Fri, 19 Oct 2012, Felipe Balbi wrote:

> On Fri, Oct 19, 2012 at 04:55:38PM +0000, Paul Walmsley wrote:
> > On Thu, 18 Oct 2012, Paul Walmsley wrote:
> > 
> > > Here are some basic OMAP test results for Linux v3.7-rc1.
> > > Logs and other details at http://www.pwsan.com/omap/testlogs/test_v3.7-rc1/
> > 
> > > Failing tests: needing investigation
> > > ------------------------------------
> > >
> > > Boot tests:
> > 
> > * 3530ES3 Beagle: I2C timeouts during userspace init
> >   - May be related to the threaded IRQ conversion of the I2C driver
> >   - Unknown cause
> 
> Doesn't seem like it's related to threaded IRQ. It says:
> 
> [   23.673858] omap_i2c omap_i2c.1: timeout waiting for bus ready
> 
> at that time we didn't even program the transfer yet, meaning we're not
> even on wait_for_completion_timeout() inside omap_i2c_xfer_msg(). This
> happens before:
> 
> > static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
> > {
> > 	unsigned long timeout;
> > 
> > 	timeout = jiffies + OMAP_I2C_TIMEOUT;
> > 	while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
> > 		if (time_after(jiffies, timeout)) {
> > 			dev_warn(dev->dev, "timeout waiting for bus ready\n");
> 
> it' stopping here. And that's called...
> 
> > 			return -ETIMEDOUT;
> > 		}
> > 		msleep(1);
> > 	}
> > 
> > 	return 0;
> > }
> 
> [...]
> 
> > static int
> > omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
> > {
> > 	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
> > 	int i;
> > 	int r;
> > 
> > 	r = pm_runtime_get_sync(dev->dev);
> > 	if (IS_ERR_VALUE(r))
> > 		goto out;
> > 
> > 	r = omap_i2c_wait_for_bb(dev);
> 
> right here. For whatever reason, the bus is kept busy (or at least the
> driver thinks so).
> 
> Looking closely at the logs I see that definitely I2C was working during
> early boot (we managed to mount file system on SD card and twl got
> initialized properly). But then we have a long time where I2C isn't
> used, so it probably suspended in between.
> 
> Then RTC wanted to read a register, I2C woke up, restored context, but
> bus was kept busy, for whatever reason.
> 
> Does it happen all the time on multiple boots or is it ramdom ?

Just ran six boot tests here; it occurred in five of them.  Then tried 
five boot tests on v3.6 and the error didn't show up in any of them.  
Abbreviated log at the bottom.

Would be happy to send along a copy of the userspace that was used if it 
would be useful to you.


- Paul

paul at nozomi:~$ egrep '(version 3\.|timeout waiting)' 3530es3beagle_log.txt 
[    0.000000] Linux version 3.7.0-rc1 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:58:00 MDT 2012
[    0.000000] Linux version 3.7.0-rc1 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:58:00 MDT 2012
[   22.710418] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   23.726074] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    0.000000] Linux version 3.7.0-rc1 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:58:00 MDT 2012
[   22.804351] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   23.819976] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    0.000000] Linux version 3.7.0-rc1 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:58:00 MDT 2012
[   22.805419] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   23.821044] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    0.000000] Linux version 3.7.0-rc1 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:58:00 MDT 2012
[   22.820648] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   23.836273] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    0.000000] Linux version 3.7.0-rc1 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:58:00 MDT 2012
[   22.858978] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   23.874603] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    0.000000] Linux version 3.6.0 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:42:23 MDT 2012
[    0.000000] Linux version 3.6.0 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:42:23 MDT 2012
[    0.000000] Linux version 3.6.0 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:42:23 MDT 2012
[    0.000000] Linux version 3.6.0 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:42:23 MDT 2012
[    0.000000] Linux version 3.6.0 (paul at nozomi) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-50) ) #1 SMP Wed Oct 17 20:42:23 MDT 2012

^ permalink raw reply

* [PATCH RFC 02/15 v5] gpio: Add sysfs support to block GPIO API
From: Greg KH @ 2012-10-19 18:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <507FD4EB.1080204@antcom.de>

On Thu, Oct 18, 2012 at 12:07:39PM +0200, Roland Stigge wrote:
> On 10/17/2012 09:05 PM, Greg KH wrote:
> >> +static int gpio_block_value_unexport(struct gpio_block *block)
> >> +{
> >> +	struct device	*dev;
> >> +	int		i;
> >> +
> >> +	dev = class_find_device(&gpio_block_class, NULL, block, match_export);
> >> +	if (!dev)
> >> +		return -ENODEV;
> >> +
> >> +	for (i = 0; i < block->ngpio; i++)
> >> +		gpio_free(block->gpio[i]);
> >> +
> >> +	device_remove_file(dev, &dev_attr_block_value);
> >> +
> >> +	return 0;
> >> +}
> > 
> > Wait, what?  You are removing a sysfs file in this function, from within
> > a sysfs write:
> 
> Yes, exactly:
> 
> >> +static ssize_t gpio_block_exported_store(struct device *dev,
> >> +					 struct device_attribute *attr,
> >> +					 const char *buf, size_t size)
> >> +{
> >> +	long	value;
> >> +	int	status;
> >> +	struct	gpio_block *block = dev_get_drvdata(dev);
> >> +	int	exported = gpio_block_value_is_exported(block);
> >> +
> >> +	status = kstrtoul(buf, 0, &value);
> >> +	if (status < 0)
> >> +		goto err;
> >> +
> >> +	if (value != exported) {
> >> +		if (value)
> >> +			status = gpio_block_value_export(block);
> >> +		else
> >> +			status = gpio_block_value_unexport(block);
> > 
> > That looks like a recipie for disaster.  Why do you allow userspace to
> > do this?
> 
> Exporting for gpio blocks is done as follows: writing "1" to the
> "exported" _device_ attribute of the gpio block creates the "values"
> attribute and at the same time requests the whole block (including all
> of its gpios) as "sysfs".
> 
> This admittedly deviates from the exporting of gpios (with the "export"
> and "unexport" _class_ attributes) because blocks are not numbered. In
> contrast, they are registered in a list (as was requested). Now, I
> already had the idea of also having an "export" and "unexport" _class_
> attribute for blocks also, but from a userspace perspective you only see
> the presence and name of the gpio block if it is already being in sysfs
> (even if not exported yet). If it wouldn't be this way, a user couldn't
> guess how the required gpio block is called (or numbered), wouldn't even
> know about its presence.
> 
> Just for understanding your strong desire for the device attribute
> ("value") being always present (in contrast to being created and removed
> dynamically) - can you please give me any hint how the dynamic approach
> would lead to disaster?
> 
> One possibility would be to always have "value" as a default device
> attribute, but then it wouldn't be so obvious that it's useless until
> "exported" is "1".
> 
> What do you think?
> 
> For now, I would elaborate about my terse "only available if /exported
> is 1" like this:
> 
> "
> Block GPIO devices are visible in sysfs as soon as they are registered
> (e.g. via devicetree definition). For actual I/O use, their "exported"
> boolean attribute must be set to "1". Then, the attribute "values" is
> created and at the same time, the GPIOs in the block are requested for
> exclusive use by sysfs.
> "

Yes, that explanation makes it more obvious as to what is going on, it
caught me by supprise.

We used to have problems with attributes removing/adding devices or
attributes from their callbacks, but that has been fixed up now, and the
fact that the other gpio code works this way is good enough precedence
to keep me from objecting to it.

thanks,

greg k-h

^ permalink raw reply

* imx-sdma.c broken on imx53 for sound
From: Rick Bronson @ 2012-10-19 18:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

  On the iMX53, the sound chip sgtl5000 seems to get SDMA channel 0, but
this code in drivers/dma/imx-sdma.c:

	/* not interested in channel 0 interrupts */
	if (sdmac->channel == 0)
		return;

 causes the DMA to be ignored.  If I comment out the above, I still get no
sound...

  Anyone have any ideas?

  Thanks much for any help.

  Rick

^ permalink raw reply

* [PATCH v2] pinctrl: reserve pins when states are activated
From: Tony Lindgren @ 2012-10-19 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350651909-5337-1-git-send-email-linus.walleij@stericsson.com>

* Linus Walleij <linus.walleij@stericsson.com> [121019 06:09]:
> 
> Instead: let use reserve the pins when the state is activated
> and drop them when the state is disabled, i.e. when we move to
> another state. This way different devices/functions can use the
> same pins at different times.

Hmm doesn't this mean that we are now doing lots of extra
reserving and dropping of pins? Performance is important from
latency point of view for cases where we need to remux pins
constantly runtime PM.

Regards,

Tony

^ permalink raw reply

* OMAP baseline test results for v3.7-rc1
From: Felipe Balbi @ 2012-10-19 18:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1210191752210.14522@utopia.booyaka.com>

Hi,

On Fri, Oct 19, 2012 at 05:56:48PM +0000, Paul Walmsley wrote:
> Hi Felipe,
> 
> On Fri, 19 Oct 2012, Felipe Balbi wrote:
> 
> > On Fri, Oct 19, 2012 at 04:55:38PM +0000, Paul Walmsley wrote:
> > > On Thu, 18 Oct 2012, Paul Walmsley wrote:
> > > 
> > > > Here are some basic OMAP test results for Linux v3.7-rc1.
> > > > Logs and other details at http://www.pwsan.com/omap/testlogs/test_v3.7-rc1/
> > > 
> > > > Failing tests: needing investigation
> > > > ------------------------------------
> > > >
> > > > Boot tests:
> > > 
> > > * 3530ES3 Beagle: I2C timeouts during userspace init
> > >   - May be related to the threaded IRQ conversion of the I2C driver
> > >   - Unknown cause
> > 
> > Doesn't seem like it's related to threaded IRQ. It says:
> > 
> > [   23.673858] omap_i2c omap_i2c.1: timeout waiting for bus ready
> > 
> > at that time we didn't even program the transfer yet, meaning we're not
> > even on wait_for_completion_timeout() inside omap_i2c_xfer_msg(). This
> > happens before:
> > 
> > > static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
> > > {
> > > 	unsigned long timeout;
> > > 
> > > 	timeout = jiffies + OMAP_I2C_TIMEOUT;
> > > 	while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
> > > 		if (time_after(jiffies, timeout)) {
> > > 			dev_warn(dev->dev, "timeout waiting for bus ready\n");
> > 
> > it' stopping here. And that's called...
> > 
> > > 			return -ETIMEDOUT;
> > > 		}
> > > 		msleep(1);
> > > 	}
> > > 
> > > 	return 0;
> > > }
> > 
> > [...]
> > 
> > > static int
> > > omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
> > > {
> > > 	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
> > > 	int i;
> > > 	int r;
> > > 
> > > 	r = pm_runtime_get_sync(dev->dev);
> > > 	if (IS_ERR_VALUE(r))
> > > 		goto out;
> > > 
> > > 	r = omap_i2c_wait_for_bb(dev);
> > 
> > right here. For whatever reason, the bus is kept busy (or at least the
> > driver thinks so).
> > 
> > Looking closely at the logs I see that definitely I2C was working during
> > early boot (we managed to mount file system on SD card and twl got
> > initialized properly). But then we have a long time where I2C isn't
> > used, so it probably suspended in between.
> > 
> > Then RTC wanted to read a register, I2C woke up, restored context, but
> > bus was kept busy, for whatever reason.
> > 
> > Does it happen all the time on multiple boots or is it ramdom ?
> 
> Just ran six boot tests here; it occurred in five of them.  Then tried 
> five boot tests on v3.6 and the error didn't show up in any of them.  
> Abbreviated log at the bottom.
> 
> Would be happy to send along a copy of the userspace that was used if it 
> would be useful to you.

no need for the userspace, I don't believe it will matter as the problem
happens when RTC is used somehow. I'll see if I can reproduce it here in
any way possible on my beagleXM (different OMAP, I know, but still.
Hopefully I'll trigger it, which means it's not a missing workaround).

cheers

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121019/6b962a95/attachment.sig>

^ permalink raw reply

* [PATCH 08/10] pinctrl: single: support pinconf generic
From: Tony Lindgren @ 2012-10-19 18:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121019024012.GP30550@atomide.com>

* Tony Lindgren <tony@atomide.com> [121018 19:41]:
> * Haojian Zhuang <haojian.zhuang@gmail.com> [121018 19:25]:
> > 
> > I wonder whether gpio function in OMAP is also configured in the pinmux
> > register. For example, the function is 3bit field in pinmux register
> > of Marvell's
> > PXA/MMP silicon. GPIO function is the one of function.
> > 
> > If the usage case is same in OMAP silicon, I can merge
> > "pinctrl-single,gpio-mask"
> > with "pinctrl-single,function-mask".
> > 
> > Do we need "pinctrl-single,gpio-disable" at here? I want to remove it,
> > but I don't
> > know whether it's necessary in OMAP case.
> 
> Maybe.. I'll take a look at at that tomorrow.

This one does not apply to v3.7-rc1 because of the pinctrl,bits
support merged from Peter Ujfalusi. Can you please update and
repost?

Thanks,

Tony

^ permalink raw reply

* [PATCH 08/10] pinctrl: single: support pinconf generic
From: Tony Lindgren @ 2012-10-19 18:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAN1soZzsruhWt7VFgf5Fi79npcjLiMSUEVwnE3hR5iWEh+9GRw@mail.gmail.com>

* Haojian Zhuang <haojian.zhuang@gmail.com> [121018 19:25]:
> 
> I wonder whether gpio function in OMAP is also configured in the pinmux
> register. For example, the function is 3bit field in pinmux register
> of Marvell's
> PXA/MMP silicon. GPIO function is the one of function.

For omaps, the mux registers in padconf area just control
the routing of the signal, pulls and wake-up events. So
gpio mode is a number in the mode bits [2:0]. It's mode 3
for some omaps and mode 4 for some omaps. All the other GPIO
related registers are elsewhere.

Sounds like this is different from what you are describing,
but if you want to compare it, the register bits in the
legacy mach-omap2/mux.h are:

/* 34xx mux mode options for each pin. See TRM for options */
#define OMAP_MUX_MODE0      0
#define OMAP_MUX_MODE1      1
#define OMAP_MUX_MODE2      2
#define OMAP_MUX_MODE3      3
#define OMAP_MUX_MODE4      4
#define OMAP_MUX_MODE5      5
#define OMAP_MUX_MODE6      6
#define OMAP_MUX_MODE7      7
               
/* 24xx/34xx mux bit defines */
#define OMAP_PULL_ENA                   (1 << 3)
#define OMAP_PULL_UP                    (1 << 4)
#define OMAP_ALTELECTRICALSEL           (1 << 5)
               
/* 34xx specific mux bit defines */
#define OMAP_INPUT_EN                   (1 << 8)
#define OMAP_OFF_EN                     (1 << 9)
#define OMAP_OFFOUT_EN                  (1 << 10)
#define OMAP_OFFOUT_VAL                 (1 << 11)
#define OMAP_OFF_PULL_EN                (1 << 12)
#define OMAP_OFF_PULL_UP                (1 << 13)
#define OMAP_WAKEUP_EN                  (1 << 14)
       
/* 44xx specific mux bit defines */
#define OMAP_WAKEUP_EVENT               (1 << 15)

Regards,

Tony

^ permalink raw reply

* OMAP baseline test results for v3.7-rc1
From: Felipe Balbi @ 2012-10-19 19:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121019190358.GI1613@blackmetal.musicnaut.iki.fi>

On Fri, Oct 19, 2012 at 10:03:58PM +0300, Aaro Koskinen wrote:
> Hi,
> 
> On Fri, Oct 19, 2012 at 04:55:38PM +0000, Paul Walmsley wrote:
> > On Thu, 18 Oct 2012, Paul Walmsley wrote:
> > 
> > > Here are some basic OMAP test results for Linux v3.7-rc1.
> > > Logs and other details at http://www.pwsan.com/omap/testlogs/test_v3.7-rc1/
> > 
> > And here's two more.
> 
> [...]
> 
> > * 3530ES3 Beagle: I2C timeouts during userspace init
> >   - May be related to the threaded IRQ conversion of the I2C driver
> >   - Unknown cause
> 
> FYI, I saw I2C hangs also on Nokia N900 with v3.7-rc1 (omap_i2c
> omap_i2c.1: timeout waiting for bus ready). After several reboots they
> disappered (kernel binary was the same), and I have been unable to
> reproduce them since.

any change you have those logs saved somewhere ? Want to see if it's the
same problem triggered by RTC.

-- 
balbi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20121019/0b494aa5/attachment-0001.sig>

^ permalink raw reply

* OMAP baseline test results for v3.7-rc1
From: Aaro Koskinen @ 2012-10-19 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1210191645390.10773@utopia.booyaka.com>

Hi,

On Fri, Oct 19, 2012 at 04:55:38PM +0000, Paul Walmsley wrote:
> On Thu, 18 Oct 2012, Paul Walmsley wrote:
> 
> > Here are some basic OMAP test results for Linux v3.7-rc1.
> > Logs and other details at http://www.pwsan.com/omap/testlogs/test_v3.7-rc1/
> 
> And here's two more.

[...]

> * 3530ES3 Beagle: I2C timeouts during userspace init
>   - May be related to the threaded IRQ conversion of the I2C driver
>   - Unknown cause

FYI, I saw I2C hangs also on Nokia N900 with v3.7-rc1 (omap_i2c
omap_i2c.1: timeout waiting for bus ready). After several reboots they
disappered (kernel binary was the same), and I have been unable to
reproduce them since.

A.

^ permalink raw reply

* [PATCH 08/10] pinctrl: single: support pinconf generic
From: Tony Lindgren @ 2012-10-19 19:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350551224-12857-8-git-send-email-haojian.zhuang@gmail.com>

* Haojian Zhuang <haojian.zhuang@gmail.com> [121018 02:08]:
> Add pinconf generic support with POWER SOURCE, BIAS PULL.
...

> +	case PIN_CONFIG_POWER_SOURCE:
> +		if (pcs->psmask == PCS_OFF_DISABLED
> +			|| pcs->psshift == PCS_OFF_DISABLED)
> +			return -ENOTSUPP;
> +		data &= pcs->psmask;
> +		data = data >> pcs->psshift;
> +		*config = data;
> +		return 0;
> +		break;

Hmm, only slightly related to this patch, mostly a generic
question to others: Do others have any mux registers with
status bits for things like PIN_CONFIG_POWER_SOURCE?

I could use PIN_CONFIG_POWER_SOURCE for controlling the PBIAS
for omap MMC. But there's also a status bit that needs to be
checked for that. I think there was some other similar mux
register for USB PHY that has a status register.

So I'm wondering should the checking for status bit be handled
in the pinctrl consume driver? Or should we have some bindings
for that?

Regards,

Tony

^ permalink raw reply

* OMAP baseline test results for v3.7-rc1
From: Aaro Koskinen @ 2012-10-19 19:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121019190136.GA4229@arwen.pp.htv.fi>

Hi,

On Fri, Oct 19, 2012 at 10:01:36PM +0300, Felipe Balbi wrote:
> On Fri, Oct 19, 2012 at 10:03:58PM +0300, Aaro Koskinen wrote:
> > FYI, I saw I2C hangs also on Nokia N900 with v3.7-rc1 (omap_i2c
> > omap_i2c.1: timeout waiting for bus ready). After several reboots they
> > disappered (kernel binary was the same), and I have been unable to
> > reproduce them since.
> 
> any change you have those logs saved somewhere ? Want to see if it's the
> same problem triggered by RTC.

I did not save the logs, but now I tried again, I managed to reproduce
it after couple boots. The log is below, and after that the there's also
one from OK boot for comparison.

In the error case, the boot never reaches userspace, just silently hangs
(or maybe I just didn't wait enough long).

...

Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0
[    0.000000] Linux version 3.7.0-rc1-n9xx (aaro at blackmetal) (gcc version 4.7.2 (GCC) ) #1 Wed Oct 17 00:28:59 EEST 2012
[    0.000000] Ignoring unrecognised tag 0x414f4d50
[    0.000000] Reserving 16777216 bytes SDRAM for VRAM
[    0.000000] OMAP3430/3530 ES3.1 (l2cache iva sgx neon isp )
[    0.000000] Clocking rate (Crystal/Core/MPU): 19.2/332/500 MHz
[    0.000000] Kernel command line: console=tty console=ttyO2,115200
[    0.000000] PID hash table entries: 1024 (order: 0, 4096 bytes)
[    0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
[    0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] Memory: 239MB = 239MB total
[    0.000000] Memory: 233420k/233420k available, 28724k reserved, 0K highmem
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
[    0.000000]     vmalloc : 0xd0800000 - 0xff000000   ( 744 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xd0000000   ( 256 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
[    0.000000]       .text : 0xc0008000 - 0xc03c0000   (3808 kB)
[    0.000000]       .init : 0xc03c0000 - 0xc078569c   (3862 kB)
[    0.000000]       .data : 0xc0786000 - 0xc07b9880   ( 207 kB)
[    0.000000]        .bss : 0xc07b98a4 - 0xc08ced10   (1110 kB)
[    0.000000] SLUB: Genslabs=11, HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] IRQ: Found an INTC at 0xfa200000 (revision 4.0) with 96 interrupts
[    0.000000] Total of 96 interrupts on 1 active controller
[    0.000000] OMAP clockevent source: GPTIMER1 at 32768 Hz
[    0.000000] sched_clock: 32 bits at 32kHz, resolution 30517ns, wraps every 131071999ms
[    0.000000] OMAP clocksource: 32k_counter at 32768 Hz
[    0.000000] Console: colour dummy device 80x30
[    0.000000] console [tty0] enabled
[    0.000854] Calibrating delay loop... 331.40 BogoMIPS (lpj=1296384)
[    0.054687] pid_max: default: 32768 minimum: 301
[    0.054901] Mount-cache hash table entries: 512
[    0.055664] CPU: Testing write buffer coherency: ok
[    0.056060] Setting up static identity map for 0x802d23e8 - 0x802d2440
[    0.057128] devtmpfs: initialized
[    0.063995] omap_hwmod: mcbsp2: cannot be enabled for reset (3)
[    0.069488] pinctrl core: initialized pinctrl subsystem
[    0.070953] regulator-dummy: no parameters
[    0.071380] NET: Registered protocol family 16
[    0.072875] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.073699] omap-gpmc omap-gpmc: GPMC revision 5.0
[    0.078308] OMAP GPIO hardware version 2.5
[    0.085357] omap_mux_init: Add partition: #1: core, flags: 0
[    0.089172] Reprogramming SDRC clock to 332000000 Hz
[    0.095092] hw-breakpoint: debug architecture 0x4 unsupported.
[    0.100860] Reserving DMA channels 0 and 1 for HS ROM code
[    0.100891] OMAP DMA hardware revision 4.0
[    0.103057]  arm-pmu: alias fck already exists
[    0.121765] bio: create slab <bio-0> at 0
[    0.160278] omap-dma-engine omap-dma-engine: OMAP DMA engine driver
[    0.162811] SCSI subsystem initialized
[    0.163360] usbcore: registered new interface driver usbfs
[    0.163665] usbcore: registered new interface driver hub
[    0.164031] usbcore: registered new device driver usb
[    0.164733] musb-omap2430 musb-omap2430: invalid resource
[    0.190460] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
[    0.190612] twl 1-0048: power (irq 343) chaining IRQs 346..353
[    0.191833] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
[    1.203124] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    2.218749] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    2.218780] twl: i2c_write failed to transfer all messages
[    3.234374] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    3.234405] twl: i2c_write failed to transfer all messages
[    3.235748] VUSB1V5: 1500 mV normal standby
[    4.249999] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    4.250030] twl: i2c_write failed to transfer all messages
[    4.250701] VUSB1V8: 1800 mV normal standby
[    5.265624] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    5.265655] twl: i2c_write failed to transfer all messages
[    5.266296] VUSB3V1: 3100 mV normal standby
[    6.281249] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    6.281280] twl: i2c_write failed to transfer all messages
[    7.296874] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    7.296905] twl: i2c_write failed to transfer all messages
[    8.312499] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    8.312530] twl: i2c_write failed to transfer all messages
[    9.328124] omap_i2c omap_i2c.1: timeout waiting for bus ready
[    9.328155] twl: i2c_write failed to transfer all messages
[   10.343749] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   10.343780] twl: i2c_write failed to transfer all messages
[   11.359374] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   11.359405] twl: i2c_write failed to transfer all messages
[   12.374999] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   12.375030] twl: i2c_write failed to transfer all messages
[   13.390624] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   13.390655] twl: i2c_write failed to transfer all messages
[   14.406249] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   14.406280] twl: i2c_write failed to transfer all messages
[   15.421874] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   15.421905] twl: i2c_write failed to transfer all messages
[   16.437499] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   16.437530] twl: i2c_write failed to transfer all messages
[   17.453124] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   17.453155] twl: i2c_write failed to transfer all messages
[   17.453186] twl4030: twl4030_sih_bus_sync_unlock, write --> -110
[   18.468749] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   18.468780] twl: i2c_read failed to transfer all messages
[   18.468811] twl4030: twl4030_sih_bus_sync_unlock, read --> -110
[   19.484374] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   19.484405] twl: i2c_read failed to transfer all messages
[   19.484466] twl4030_usb twl4030_usb: USB link status err -110
[   19.484497] twl4030_usb twl4030_usb: Initialized TWL4030 USB module
[   20.499999] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   20.500030] twl: i2c_read failed to transfer all messages
[   21.515624] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   21.515655] twl: i2c_write failed to transfer all messages
[   21.515686] VPLL: failed to apply 1800000uV constraint
[   21.516021] twl_reg twl_reg.4: can't register VPLL1, -110
[   21.516052] twl_reg: probe of twl_reg.4 failed with error -110
[   22.531249] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   22.531280] twl: i2c_read failed to transfer all messages
[   22.531311] VIO: failed to enable
[   22.531616] twl_reg twl_reg.2: can't register VIO, -110
[   22.531646] twl_reg: probe of twl_reg.2 failed with error -110
[   22.532287] vdd_mpu_iva: 600 <--> 1450 mV normal 
[   23.546874] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   23.546905] twl: i2c_write failed to transfer all messages
[   23.547546] vdd_core: 600 <--> 1450 mV normal 
[   24.562499] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   24.562530] twl: i2c_write failed to transfer all messages
[   25.578124] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   25.578155] twl: i2c_read failed to transfer all messages
[   25.578186] VMMC1: 1850 <--> 3150 mV normal standby
[   26.593749] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   26.593780] twl: i2c_read failed to transfer all messages
[   27.609374] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   27.609405] twl: i2c_write failed to transfer all messages
[   28.624999] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   28.625030] twl: i2c_read failed to transfer all messages
[   29.640624] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   29.640655] twl: i2c_write failed to transfer all messages
[   29.640686] VDAC: failed to apply 1800000uV constraint
[   29.640991] twl_reg twl_reg.3: can't register VDAC, -110
[   29.641021] twl_reg: probe of twl_reg.3 failed with error -110
[   29.641662] VCSI: 1800 mV normal standby
[   30.656249] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   30.656280] twl: i2c_read failed to transfer all messages
[   31.671874] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   31.671905] twl: i2c_write failed to transfer all messages
[   32.687499] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   32.687530] twl: i2c_read failed to transfer all messages
[   32.687561] VINTANA1: failed to enable
[   32.687835] twl_reg twl_reg.14: can't register VINTANA1, -110
[   32.687896] twl_reg: probe of twl_reg.14 failed with error -110
[   33.703124] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   33.703155] twl: i2c_read failed to transfer all messages
[   34.718749] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   34.718780] twl: i2c_write failed to transfer all messages
[   34.718811] VINTANA2: failed to apply 2750000uV constraint
[   34.719085] twl_reg twl_reg.15: can't register VINTANA2, -110
[   34.719146] twl_reg: probe of twl_reg.15 failed with error -110
[   35.734374] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   35.734405] twl: i2c_read failed to transfer all messages
[   35.734436] VINTDIG: failed to enable
[   35.734710] twl_reg twl_reg.16: can't register VINTDIG, -110
[   35.734771] twl_reg: probe of twl_reg.16 failed with error -110
[   36.749999] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   36.750030] twl: i2c_read failed to transfer all messages
[   37.765624] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   37.765655] twl: i2c_write failed to transfer all messages
[   37.765686] VSDI_CSI: failed to apply 1800000uV constraint
[   37.765960] twl_reg twl_reg.5: can't register VPLL2, -110
[   37.766021] twl_reg: probe of twl_reg.5 failed with error -110
[   38.781249] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   38.781280] twl: i2c_read failed to transfer all messages
[   38.781311] V28_A: failed to enable
[   38.781585] twl_reg twl_reg.7: can't register VMMC2, -110
[   38.781646] twl_reg: probe of twl_reg.7 failed with error -110
[   39.796874] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   39.796905] twl: i2c_read failed to transfer all messages
[   40.812499] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   40.812530] twl: i2c_write failed to transfer all messages
[   40.812561] VMMC2_IO_18: failed to apply 1800000uV constraint
[   40.812835] twl_reg twl_reg.8: can't register VSIM, -110
[   40.812896] twl_reg: probe of twl_reg.8 failed with error -110
[   41.828124] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   41.828155] twl: i2c_read failed to transfer all messages
[   41.828186] V28: failed to enable
[   41.828460] twl_reg twl_reg.9: can't register VAUX1, -110
[   41.828521] twl_reg: probe of twl_reg.9 failed with error -110
[   42.843749] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   42.843780] twl: i2c_read failed to transfer all messages
[   42.843811] VMMC2_30: 2800 <--> 3000 mV normal standby
[   43.859374] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   43.859405] twl: i2c_read failed to transfer all messages
[   44.874999] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   44.875030] twl: i2c_write failed to transfer all messages
[   45.890624] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   45.890655] twl: i2c_read failed to transfer all messages
[   46.906249] omap_i2c omap_i2c.1: timeout waiting for bus ready
[   46.906280] twl: i2c_write failed to transfer all messages
[   46.906311] VCAM_ANA_28: failed to apply 2800000uV constraint
[   46.906585] twl_reg twl_reg.13: can't register VAUX4, -110
[   46.906646] twl_reg: probe of twl_reg.13 failed with error -110
[   46.906707] omap_i2c omap_i2c.1: bus 1 rev1.3.12 at 2200 kHz
[   46.908630] omap_i2c omap_i2c.2: bus 2 rev1.3.12 at 100 kHz
[   46.909271] omap_i2c omap_i2c.3: bus 3 rev1.3.12 at 400 kHz
[   46.912200] Switching to clocksource 32k_counter
[   46.938690] NET: Registered protocol family 2
[   46.939422] TCP established hash table entries: 8192 (order: 4, 65536 bytes)
[   46.939666] TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
[   46.939819] TCP: Hash tables configured (established 8192 bind 8192)
[   46.939971] TCP: reno registered
[   46.940032] UDP hash table entries: 256 (order: 0, 4096 bytes)
[   46.940063] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[   46.984313] CPU PMU: probing PMU on CPU 0
[   46.984374] hw perfevents: enabled with ARMv7 Cortex-A8 PMU driver, 5 counters available
[   47.340698] msgmni has been set to 455
[   47.349639] io scheduler noop registered
[   47.350799] io scheduler cfq registered (default)
[   47.371429] OMAP DSS rev 2.0
[   47.382049] omapdss SDI error: can't get VDDS_SDI regulator
[   47.382110] omapdss SDI error: device lcd init failed: -517
[   47.392883] omapdss VENC error: can't get VDDA_DAC regulator
[   47.392944] omapdss VENC error: device tv init failed: -517
[   47.403137] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[   47.438934] omap_uart.0: ttyO0 at MMIO 0x4806a000 (irq = 88) is a OMAP UART0
[   47.443847] omap_uart.1: ttyO1 at MMIO 0x4806c000 (irq = 89) is a OMAP UART1
[   47.450317] omap_uart.2: ttyO2 at MMIO 0x49020000 (irq = 90) is a OMAP UART2
[   48.737792] console [ttyO2] enabled
[   48.777343] mtdoops: mtd device (mtddev=name/number) must be supplied
[   48.793426] OneNAND driver initializing
[   48.798004] omap2-onenand omap2-onenand: initializing on CS0, phys base 0x04000000, virtual base d0880000, freq 66 MHz
[   48.809417] Muxed OneNAND 256MB 1.8V 16-bit (0x40)
[   48.814514] OneNAND version = 0x0121
[   48.820068] Scanning device for bad blocks
[   48.903167] OneNAND eraseblock 1229 is an initial bad block
[   48.965820] Creating 6 MTD partitions on "omap2-onenand":
[   48.971679] 0x000000000000-0x000000020000 : "bootloader"
[   48.994049] 0x000000020000-0x000000080000 : "config"
[   49.020263] 0x000000080000-0x0000000c0000 : "log"
[   49.046173] 0x0000000c0000-0x0000002c0000 : "kernel"
[   49.072509] 0x0000002c0000-0x0000004c0000 : "initfs"
[   49.098693] 0x0000004c0000-0x000010000000 : "rootfs"
[   49.140594] omap-dma-engine omap-dma-engine: allocating channel for 40
[   49.147644] omap-dma-engine omap-dma-engine: allocating channel for 39
[   49.159637] omap-dma-engine omap-dma-engine: allocating channel for 36
[   49.166656] omap-dma-engine omap-dma-engine: allocating channel for 35
[   49.193847] omap-dma-engine omap-dma-engine: allocating channel for 71
[   49.200805] omap-dma-engine omap-dma-engine: allocating channel for 70
[   49.214599] musb-hdrc: version 6.0, ?dma?, otg (peripheral+host)
[   49.245239] mousedev: PS/2 mouse device common for all mice
[   49.261505] input: TWL4030 Keypad as /devices/platform/omap_i2c.1/i2c-1/1-004a/twl4030_keypad/input/input0
[   49.298553] input: TSC2005 touchscreen as /devices/platform/omap2_mcspi.1/spi_master/spi1/spi1.0/input/input1

The good case:

Uncompressing Linux... done, booting the kernel.
[    0.000000] Booting Linux on physical CPU 0
[    0.000000] Linux version 3.7.0-rc1-n9xx (aaro at blackmetal) (gcc version 4.7.2 (GCC) ) #1 Wed Oct 17 00:28:59 EEST 2012
[    0.000000] Ignoring unrecognised tag 0x414f4d50
[    0.000000] Reserving 16777216 bytes SDRAM for VRAM
[    0.000000] OMAP3430/3530 ES3.1 (l2cache iva sgx neon isp )
[    0.000000] Clocking rate (Crystal/Core/MPU): 19.2/332/500 MHz
[    0.000000] Kernel command line: console=tty console=ttyO2,115200
[    0.000000] PID hash table entries: 1024 (order: 0, 4096 bytes)
[    0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
[    0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] Memory: 239MB = 239MB total
[    0.000000] Memory: 233420k/233420k available, 28724k reserved, 0K highmem
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
[    0.000000]     vmalloc : 0xd0800000 - 0xff000000   ( 744 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xd0000000   ( 256 MB)
[    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
[    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
[    0.000000]       .text : 0xc0008000 - 0xc03c0000   (3808 kB)
[    0.000000]       .init : 0xc03c0000 - 0xc078569c   (3862 kB)
[    0.000000]       .data : 0xc0786000 - 0xc07b9880   ( 207 kB)
[    0.000000]        .bss : 0xc07b98a4 - 0xc08ced10   (1110 kB)
[    0.000000] SLUB: Genslabs=11, HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS:16 nr_irqs:16 16
[    0.000000] IRQ: Found an INTC at 0xfa200000 (revision 4.0) with 96 interrupts
[    0.000000] Total of 96 interrupts on 1 active controller
[    0.000000] OMAP clockevent source: GPTIMER1 at 32768 Hz
[    0.000000] sched_clock: 32 bits at 32kHz, resolution 30517ns, wraps every 131071999ms
[    0.000000] OMAP clocksource: 32k_counter at 32768 Hz
[    0.000000] Console: colour dummy device 80x30
[    0.000000] console [tty0] enabled
[    0.000823] Calibrating delay loop... 331.40 BogoMIPS (lpj=1296384)
[    0.054656] pid_max: default: 32768 minimum: 301
[    0.054870] Mount-cache hash table entries: 512
[    0.055633] CPU: Testing write buffer coherency: ok
[    0.056060] Setting up static identity map for 0x802d23e8 - 0x802d2440
[    0.057128] devtmpfs: initialized
[    0.063995] omap_hwmod: mcbsp2: cannot be enabled for reset (3)
[    0.067474] pinctrl core: initialized pinctrl subsystem
[    0.068878] regulator-dummy: no parameters
[    0.069305] NET: Registered protocol family 16
[    0.070831] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.071685] omap-gpmc omap-gpmc: GPMC revision 5.0
[    0.076263] OMAP GPIO hardware version 2.5
[    0.083374] omap_mux_init: Add partition: #1: core, flags: 0
[    0.087158] Reprogramming SDRC clock to 332000000 Hz
[    0.092987] hw-breakpoint: debug architecture 0x4 unsupported.
[    0.098846] Reserving DMA channels 0 and 1 for HS ROM code
[    0.098907] OMAP DMA hardware revision 4.0
[    0.101013]  arm-pmu: alias fck already exists
[    0.119781] bio: create slab <bio-0> at 0
[    0.158294] omap-dma-engine omap-dma-engine: OMAP DMA engine driver
[    0.160827] SCSI subsystem initialized
[    0.161407] usbcore: registered new interface driver usbfs
[    0.161682] usbcore: registered new interface driver hub
[    0.162017] usbcore: registered new device driver usb
[    0.162689] musb-omap2430 musb-omap2430: invalid resource
[    0.188476] twl 1-0048: PIH (irq 23) chaining IRQs 338..346
[    0.188659] twl 1-0048: power (irq 343) chaining IRQs 346..353
[    0.189849] twl4030_gpio twl4030_gpio: gpio (irq 338) chaining IRQs 354..371
[    0.192382] VUSB1V5: 1500 mV normal standby
[    0.193176] VUSB1V8: 1800 mV normal standby
[    0.193969] VUSB3V1: 3100 mV normal standby
[    0.198425] musb-omap2430 musb-omap2430: musb core is not yet ready
[    0.198486] twl4030_usb twl4030_usb: Initialized TWL4030 USB module
[    0.200286] VPLL: 1800 mV normal standby
[    0.201354] VIO: 1800 mV normal standby
[    0.202239] vdd_mpu_iva: 600 <--> 1450 mV normal 
[    0.203033] vdd_core: 600 <--> 1450 mV normal 
[    0.203979] VMMC1: 1850 <--> 3150 mV at 3000 mV normal standby
[    0.205139] VDAC: 1800 mV normal standby
[    0.206024] VCSI: 1800 mV normal standby
[    0.207122] VINTANA1: 1500 mV normal standby
[    0.208404] VINTANA2: 2750 mV normal standby
[    0.209503] VINTDIG: 1500 mV normal standby
[    0.210754] VSDI_CSI: 1800 mV normal standby
[    0.211975] V28_A: 2800 <--> 3000 mV at 2600 mV normal standby
[    0.213195] VMMC2_IO_18: 1800 mV normal standby
[    0.214294] V28: 2800 mV normal standby
[    0.215332] VMMC2_30: 2800 <--> 3000 mV at 2800 mV normal standby
[    0.216552] VCAM_ANA_28: 2800 mV normal standby
[    0.216857] omap_i2c omap_i2c.1: bus 1 rev1.3.12 at 2200 kHz
[    0.218841] omap_i2c omap_i2c.2: bus 2 rev1.3.12 at 100 kHz
[    0.219543] omap_i2c omap_i2c.3: bus 3 rev1.3.12 at 400 kHz
[    0.222442] Switching to clocksource 32k_counter
[    0.248962] NET: Registered protocol family 2
[    0.249725] TCP established hash table entries: 8192 (order: 4, 65536 bytes)
[    0.250000] TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
[    0.250152] TCP: Hash tables configured (established 8192 bind 8192)
[    0.250305] TCP: reno registered
[    0.250335] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.250396] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.294677] CPU PMU: probing PMU on CPU 0
[    0.294769] hw perfevents: enabled with ARMv7 Cortex-A8 PMU driver, 5 counters available
[    0.650421] msgmni has been set to 455
[    0.659210] io scheduler noop registered
[    0.660369] io scheduler cfq registered (default)
[    0.681091] OMAP DSS rev 2.0
[    0.722259] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[    0.757598] omap_uart.0: ttyO0 at MMIO 0x4806a000 (irq = 88) is a OMAP UART0
[    0.763275] omap_uart.1: ttyO1 at MMIO 0x4806c000 (irq = 89) is a OMAP UART1
[    0.768859] omap_uart.2: ttyO2 at MMIO 0x49020000 (irq = 90) is a OMAP UART2
[    1.345886] console [ttyO2] enabled
[    1.385345] mtdoops: mtd device (mtddev=name/number) must be supplied
[    1.401428] OneNAND driver initializing
[    1.405975] omap2-onenand omap2-onenand: initializing on CS0, phys base 0x04000000, virtual base d0880000, freq 66 MHz
[    1.417388] Muxed OneNAND 256MB 1.8V 16-bit (0x40)
[    1.422485] OneNAND version = 0x0121
[    1.428039] Scanning device for bad blocks
[    1.510833] OneNAND eraseblock 1229 is an initial bad block
[    1.573272] Creating 6 MTD partitions on "omap2-onenand":
[    1.579101] 0x000000000000-0x000000020000 : "bootloader"
[    1.601562] 0x000000020000-0x000000080000 : "config"
[    1.627746] 0x000000080000-0x0000000c0000 : "log"
[    1.653228] 0x0000000c0000-0x0000002c0000 : "kernel"
[    1.679840] 0x0000002c0000-0x0000004c0000 : "initfs"
[    1.705993] 0x0000004c0000-0x000010000000 : "rootfs"
[    1.747772] omap-dma-engine omap-dma-engine: allocating channel for 40
[    1.754791] omap-dma-engine omap-dma-engine: allocating channel for 39
[    1.766784] omap-dma-engine omap-dma-engine: allocating channel for 36
[    1.773803] omap-dma-engine omap-dma-engine: allocating channel for 35
[    1.800994] omap-dma-engine omap-dma-engine: allocating channel for 71
[    1.807983] omap-dma-engine omap-dma-engine: allocating channel for 70
[    1.821685] musb-hdrc: version 6.0, ?dma?, otg (peripheral+host)
[    1.850494] mousedev: PS/2 mouse device common for all mice
[    1.866729] input: TWL4030 Keypad as /devices/platform/omap_i2c.1/i2c-1/1-004a/twl4030_keypad/input/input0
[    1.903717] input: TSC2005 touchscreen as /devices/platform/omap2_mcspi.1/spi_master/spi1/spi1.0/input/input1
[    1.935546] input: twl4030_pwrbutton as /devices/platform/omap_i2c.1/i2c-1/1-0049/twl4030_pwrbutton/input/input2
[    1.957153] twl_rtc twl_rtc: Enabling TWL-RTC
[    1.974426] twl_rtc twl_rtc: rtc core: registered twl_rtc as rtc0
[    1.986541] i2c /dev entries driver
[    2.010467] Driver for 1-wire Dallas network protocol.
[    2.041320] omap_wdt: OMAP Watchdog Timer Rev 0x31: initial timeout 60 sec
[    2.058074] twl4030_wdt twl4030_wdt: Failed to register misc device
[    2.064819] twl4030_wdt: probe of twl4030_wdt failed with error -16
[    2.087432] omap_hsmmc omap_hsmmc.0: Failed to get debounce clk
[    2.093872] omap-dma-engine omap-dma-engine: allocating channel for 62
[    2.100860] omap-dma-engine omap-dma-engine: allocating channel for 61
[    2.324615] omap_hsmmc omap_hsmmc.0: mmc0: cover is open, card is now inaccessible
[    2.488739] omap_hsmmc omap_hsmmc.1: Failed to get debounce clk
[    2.495086] omap-dma-engine omap-dma-engine: allocating channel for 48
[    2.502075] omap-dma-engine omap-dma-engine: allocating channel for 47
[    2.574462] usbcore: registered new interface driver usbhid
[    2.580383] usbhid: USB HID core driver
[    2.594512] oprofile: using arm/armv7
[    2.598815] TCP: cubic registered
[    2.602355] NET: Registered protocol family 17
[    2.607177] VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 1
[    2.626220] ThumbEE CPU extension supported.
[    2.630889] clock: disabling unused clocks to save power
[    2.650207] VCSI: disabling
[    2.676544] input: gpio-keys as /devices/platform/gpio-keys/input/input3
[    2.696746] twl_rtc twl_rtc: setting system clock to 2000-01-01 00:00:12 UTC (946684812)
[    2.716003] Freeing init memory: 3860K
[    2.848114] acx565akm spi1.2: omapfb: acx565akm rev 8a LCD detected
[    2.868896] mmc1: new high speed MMC card at address 0001
[    2.894683] mmcblk0: mmc1:0001 MMC32G 29.8 GiB 
[    2.902282] mmcblk0boot0: mmc1:0001 MMC32G partition 1 512 KiB
[    2.923126] mmcblk0boot1: mmc1:0001 MMC32G partition 2 512 KiB
[    2.947784]  mmcblk0: p1 p2 p3
[    2.952819] Console: switching to colour frame buffer device 100x30
[    2.994689]  mmcblk0boot1: unknown partition table
[    3.020538]  mmcblk0boot0: unknown partition table
[    3.120727]  gadget: using random self ethernet address
[    3.129394]  gadget: using random host ethernet address
[    3.148956] usb0: MAC a6:c2:85:ce:e5:0b
[    3.155944] usb0: HOST MAC ee:48:89:41:f9:74
[    3.163299]  gadget: Ethernet Gadget, version: Memorial Day 2008
[    3.172271]  gadget: g_ether ready
[    3.190399] musb-hdrc musb-hdrc.0: MUSB HDRC host driver
[    3.198913] musb-hdrc musb-hdrc.0: new USB bus registered, assigned bus number 1
[    3.209655] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
[    3.219604] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    3.230041] usb usb1: Product: MUSB HDRC host driver
[    3.238067] usb usb1: Manufacturer: Linux 3.7.0-rc1-n9xx musb-hcd
[    3.247283] usb usb1: SerialNumber: musb-hdrc.0
[    3.261840] hub 1-0:1.0: USB hub found
[    3.268707] hub 1-0:1.0: 1 port detected
[719] Jan 01 00:00:13 Not backgrounding
[    3.706481]  gadget: high-speed config #1: CDC Ethernet (ECM)

A.

^ permalink raw reply

* [PATCH 1/2] cpufreq: return early from __cpufreq_driver_getavg()
From: Viresh Kumar @ 2012-10-19 20:12 UTC (permalink / raw)
  To: linux-arm-kernel

There is no need to do cpufreq_get_cpu() and cpufreq_put_cpu() for drivers that
don't support getavg() routine.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/cpufreq/cpufreq.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 85df538..f552d5f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1511,12 +1511,14 @@ int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
 {
 	int ret = 0;
 
+	if (!(cpu_online(cpu) && cpufreq_driver->getavg))
+		return 0;
+
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
 
-	if (cpu_online(cpu) && cpufreq_driver->getavg)
-		ret = cpufreq_driver->getavg(policy, cpu);
+	ret = cpufreq_driver->getavg(policy, cpu);
 
 	cpufreq_cpu_put(policy);
 	return ret;
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH 2/2] cpufreq: governors: remove redundant code
From: Viresh Kumar @ 2012-10-19 20:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <32e5bed743cc6cc4e614291a7080299f5f0d0933.1350677395.git.viresh.kumar@linaro.org>

Initially ondemand governor was written and then using its code conservative
governor is written. It used a lot of code from ondemand governor, but copy of
code was created instead of using the same routines from both governors. Which
increased code redundancy, which is difficult to manage.

This patch is an attempt to move common part of both the governors to
cpufreq_governor.c file to come over above mentioned issues.

This shouldn't change anything from functionality point of view.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---

Hi Rafael,

This patch is *NOT TESTED*... (only compiled)
Out of office now, so can't test it on board.

Floated it, so that i can get some early comments if possible.

 drivers/cpufreq/Makefile               |   4 +-
 drivers/cpufreq/cpufreq_conservative.c | 558 +++++++------------------
 drivers/cpufreq/cpufreq_governor.c     | 314 ++++++++++++++
 drivers/cpufreq/cpufreq_governor.h     | 177 ++++++++
 drivers/cpufreq/cpufreq_ondemand.c     | 728 ++++++++++-----------------------
 include/linux/cpufreq.h                |   2 +-
 6 files changed, 864 insertions(+), 919 deletions(-)
 create mode 100644 drivers/cpufreq/cpufreq_governor.c
 create mode 100644 drivers/cpufreq/cpufreq_governor.h

diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 19c42f0..df4cfc8 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -11,8 +11,8 @@ obj-$(CONFIG_CPU_FREQ_STAT)             += cpufreq_stats.o
 obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE)	+= cpufreq_performance.o
 obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE)	+= cpufreq_powersave.o
 obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)	+= cpufreq_userspace.o
-obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)	+= cpufreq_ondemand.o
-obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o
+obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)	+= cpufreq_ondemand.o cpufreq_governor.o
+obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)	+= cpufreq_conservative.o cpufreq_governor.o
 
 # CPUfreq cross-arch helpers
 obj-$(CONFIG_CPU_FREQ_TABLE)		+= freq_table.o
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index a152af7..64ef737 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -11,83 +11,30 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/hrtimer.h>
-#include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
 
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
 
+/* Conservative governor macors */
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_FREQUENCY_DOWN_THRESHOLD		(20)
-
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO			(2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER			(1000)
-#define MIN_LATENCY_MULTIPLIER			(100)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(10)
-#define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
-
-static void do_dbs_timer(struct work_struct *work);
-
-struct cpu_dbs_info_s {
-	cputime64_t prev_cpu_idle;
-	cputime64_t prev_cpu_wall;
-	cputime64_t prev_cpu_nice;
-	struct cpufreq_policy *cur_policy;
-	struct delayed_work work;
-	unsigned int down_skip;
-	unsigned int requested_freq;
-	int cpu;
-	unsigned int enable:1;
-	/*
-	 * percpu mutex that serializes governor limit change with
-	 * do_dbs_timer invocation. We do not want do_dbs_timer to run
-	 * when user is changing the governor or limits.
-	 */
-	struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, cs_cpu_dbs_info);
 
-static unsigned int dbs_enable;	/* number of CPUs using this policy */
+static struct dbs_data cs_dbs_data;
+static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
 
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
-	unsigned int sampling_rate;
-	unsigned int sampling_down_factor;
-	unsigned int up_threshold;
-	unsigned int down_threshold;
-	unsigned int ignore_nice;
-	unsigned int freq_step;
-} dbs_tuners_ins = {
+static struct cs_dbs_tuners cs_tuners = {
 	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
 	.down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
 	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
@@ -95,95 +42,121 @@ static struct dbs_tuners {
 	.freq_step = 5,
 };
 
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate *
+ * sampling_down_factor, we check, if current idle time is more than 80%, then
+ * we try to decrease frequency
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of maximum frequency
+ */
+static void cs_check_cpu(int cpu, unsigned int load)
 {
-	u64 idle_time;
-	u64 cur_wall_time;
-	u64 busy_time;
+	struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
+	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+	unsigned int freq_target;
+
+	/*
+	 * break out if we 'cannot' reduce the speed as the user might
+	 * want freq_step to be zero
+	 */
+	if (cs_tuners.freq_step == 0)
+		return;
 
-	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+	/* Check for frequency increase */
+	if (load > cs_tuners.up_threshold) {
+		dbs_info->down_skip = 0;
 
-	busy_time  = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
+		/* if we are already at full speed then break out early */
+		if (dbs_info->requested_freq == policy->max)
+			return;
 
-	idle_time = cur_wall_time - busy_time;
-	if (wall)
-		*wall = jiffies_to_usecs(cur_wall_time);
+		freq_target = (cs_tuners.freq_step * policy->max) / 100;
 
-	return jiffies_to_usecs(idle_time);
+		/* max freq cannot be less than 100. But who knows.... */
+		if (unlikely(freq_target == 0))
+			freq_target = 5;
+
+		dbs_info->requested_freq += freq_target;
+		if (dbs_info->requested_freq > policy->max)
+			dbs_info->requested_freq = policy->max;
+
+		__cpufreq_driver_target(policy, dbs_info->requested_freq,
+			CPUFREQ_RELATION_H);
+		return;
+	}
+
+	/*
+	 * The optimal frequency is the frequency that is the lowest that can
+	 * support the current CPU usage without triggering the up policy. To be
+	 * safe, we focus 10 points under the threshold.
+	 */
+	if (load < (cs_tuners.down_threshold - 10)) {
+		freq_target = (cs_tuners.freq_step * policy->max) / 100;
+
+		dbs_info->requested_freq -= freq_target;
+		if (dbs_info->requested_freq < policy->min)
+			dbs_info->requested_freq = policy->min;
+
+		/*
+		 * if we cannot reduce the frequency anymore, break out early
+		 */
+		if (policy->cur == policy->min)
+			return;
+
+		__cpufreq_driver_target(policy, dbs_info->requested_freq,
+				CPUFREQ_RELATION_H);
+		return;
+	}
 }
 
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+static void cs_dbs_timer(struct work_struct *work)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+	struct cs_cpu_dbs_info_s *dbs_info = container_of(work,
+			struct cs_cpu_dbs_info_s, cdbs.work.work);
+	unsigned int cpu = dbs_info->cdbs.cpu;
+	int delay = delay_for_sampling_rate(cs_tuners.sampling_rate);
 
-	if (idle_time == -1ULL)
-		return get_cpu_idle_time_jiffy(cpu, wall);
-	else
-		idle_time += get_cpu_iowait_time_us(cpu, wall);
+	mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-	return idle_time;
+	dbs_check_cpu(&cs_dbs_data, cpu);
+
+	schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+	mutex_unlock(&dbs_info->cdbs.timer_mutex);
 }
 
-/* keep track of frequency transitions */
-static int
-dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-		     void *data)
+static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+		void *data)
 {
 	struct cpufreq_freqs *freq = data;
-	struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cs_cpu_dbs_info,
-							freq->cpu);
-
+	struct cs_cpu_dbs_info_s *dbs_info =
+					&per_cpu(cs_cpu_dbs_info, freq->cpu);
 	struct cpufreq_policy *policy;
 
-	if (!this_dbs_info->enable)
+	if (!dbs_info->enable)
 		return 0;
 
-	policy = this_dbs_info->cur_policy;
+	policy = dbs_info->cdbs.cur_policy;
 
 	/*
-	 * we only care if our internally tracked freq moves outside
-	 * the 'valid' ranges of freqency available to us otherwise
-	 * we do not change it
+	 * we only care if our internally tracked freq moves outside the 'valid'
+	 * ranges of freqency available to us otherwise we do not change it
 	*/
-	if (this_dbs_info->requested_freq > policy->max
-			|| this_dbs_info->requested_freq < policy->min)
-		this_dbs_info->requested_freq = freq->new;
+	if (dbs_info->requested_freq > policy->max
+			|| dbs_info->requested_freq < policy->min)
+		dbs_info->requested_freq = freq->new;
 
 	return 0;
 }
 
-static struct notifier_block dbs_cpufreq_notifier_block = {
-	.notifier_call = dbs_cpufreq_notifier
-};
-
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_min(struct kobject *kobj,
 				      struct attribute *attr, char *buf)
 {
-	return sprintf(buf, "%u\n", min_sampling_rate);
+	return sprintf(buf, "%u\n", cs_dbs_data.min_sampling_rate);
 }
 
-define_one_global_ro(sampling_rate_min);
-
-/* cpufreq_conservative Governor Tunables */
-#define show_one(file_name, object)					\
-static ssize_t show_##file_name						\
-(struct kobject *kobj, struct attribute *attr, char *buf)		\
-{									\
-	return sprintf(buf, "%u\n", dbs_tuners_ins.object);		\
-}
-show_one(sampling_rate, sampling_rate);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(up_threshold, up_threshold);
-show_one(down_threshold, down_threshold);
-show_one(ignore_nice_load, ignore_nice);
-show_one(freq_step, freq_step);
-
 static ssize_t store_sampling_down_factor(struct kobject *a,
 					  struct attribute *b,
 					  const char *buf, size_t count)
@@ -195,7 +168,7 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
 
-	dbs_tuners_ins.sampling_down_factor = input;
+	cs_tuners.sampling_down_factor = input;
 	return count;
 }
 
@@ -209,7 +182,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 	if (ret != 1)
 		return -EINVAL;
 
-	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
+	cs_tuners.sampling_rate = max(input, cs_dbs_data.min_sampling_rate);
 	return count;
 }
 
@@ -220,11 +193,10 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	if (ret != 1 || input > 100 ||
-			input <= dbs_tuners_ins.down_threshold)
+	if (ret != 1 || input > 100 || input <= cs_tuners.down_threshold)
 		return -EINVAL;
 
-	dbs_tuners_ins.up_threshold = input;
+	cs_tuners.up_threshold = input;
 	return count;
 }
 
@@ -237,21 +209,19 @@ static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
 
 	/* cannot be lower than 11 otherwise freq will not fall */
 	if (ret != 1 || input < 11 || input > 100 ||
-			input >= dbs_tuners_ins.up_threshold)
+			input >= cs_tuners.up_threshold)
 		return -EINVAL;
 
-	dbs_tuners_ins.down_threshold = input;
+	cs_tuners.down_threshold = input;
 	return count;
 }
 
 static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 				      const char *buf, size_t count)
 {
-	unsigned int input;
+	unsigned int input, j;
 	int ret;
 
-	unsigned int j;
-
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
@@ -259,19 +229,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	if (input == dbs_tuners_ins.ignore_nice) /* nothing to do */
+	if (input == cs_tuners.ignore_nice) /* nothing to do */
 		return count;
 
-	dbs_tuners_ins.ignore_nice = input;
+	cs_tuners.ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
-		struct cpu_dbs_info_s *dbs_info;
+		struct cs_cpu_dbs_info_s *dbs_info;
 		dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-		dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&dbs_info->prev_cpu_wall);
-		if (dbs_tuners_ins.ignore_nice)
-			dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+						&dbs_info->cdbs.prev_cpu_wall);
+		if (cs_tuners.ignore_nice)
+			dbs_info->cdbs.prev_cpu_nice =
+				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 	}
 	return count;
 }
@@ -289,18 +260,28 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b,
 	if (input > 100)
 		input = 100;
 
-	/* no need to test here if freq_step is zero as the user might actually
-	 * want this, they would be crazy though :) */
-	dbs_tuners_ins.freq_step = input;
+	/*
+	 * no need to test here if freq_step is zero as the user might actually
+	 * want this, they would be crazy though :)
+	 */
+	cs_tuners.freq_step = input;
 	return count;
 }
 
+show_one(cs, sampling_rate, sampling_rate);
+show_one(cs, sampling_down_factor, sampling_down_factor);
+show_one(cs, up_threshold, up_threshold);
+show_one(cs, down_threshold, down_threshold);
+show_one(cs, ignore_nice_load, ignore_nice);
+show_one(cs, freq_step, freq_step);
+
 define_one_global_rw(sampling_rate);
 define_one_global_rw(sampling_down_factor);
 define_one_global_rw(up_threshold);
 define_one_global_rw(down_threshold);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(freq_step);
+define_one_global_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
 	&sampling_rate_min.attr,
@@ -313,283 +294,38 @@ static struct attribute *dbs_attributes[] = {
 	NULL
 };
 
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group cs_attr_group = {
 	.attrs = dbs_attributes,
 	.name = "conservative",
 };
 
 /************************** sysfs end ************************/
 
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
-	unsigned int load = 0;
-	unsigned int max_load = 0;
-	unsigned int freq_target;
-
-	struct cpufreq_policy *policy;
-	unsigned int j;
-
-	policy = this_dbs_info->cur_policy;
-
-	/*
-	 * Every sampling_rate, we check, if current idle time is less
-	 * than 20% (default), then we try to increase frequency
-	 * Every sampling_rate*sampling_down_factor, we check, if current
-	 * idle time is more than 80%, then we try to decrease frequency
-	 *
-	 * Any frequency increase takes it to the maximum frequency.
-	 * Frequency reduction happens at minimum steps of
-	 * 5% (default) of maximum frequency
-	 */
-
-	/* Get Absolute Load */
-	for_each_cpu(j, policy->cpus) {
-		struct cpu_dbs_info_s *j_dbs_info;
-		cputime64_t cur_wall_time, cur_idle_time;
-		unsigned int idle_time, wall_time;
-
-		j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-
-		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
-
-		wall_time = (unsigned int)
-			(cur_wall_time - j_dbs_info->prev_cpu_wall);
-		j_dbs_info->prev_cpu_wall = cur_wall_time;
-
-		idle_time = (unsigned int)
-			(cur_idle_time - j_dbs_info->prev_cpu_idle);
-		j_dbs_info->prev_cpu_idle = cur_idle_time;
-
-		if (dbs_tuners_ins.ignore_nice) {
-			u64 cur_nice;
-			unsigned long cur_nice_jiffies;
-
-			cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
-					 j_dbs_info->prev_cpu_nice;
-			/*
-			 * Assumption: nice time between sampling periods will
-			 * be less than 2^32 jiffies for 32 bit sys
-			 */
-			cur_nice_jiffies = (unsigned long)
-					cputime64_to_jiffies64(cur_nice);
-
-			j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-			idle_time += jiffies_to_usecs(cur_nice_jiffies);
-		}
+define_get_cpu_dbs_routines(cs_cpu_dbs_info);
 
-		if (unlikely(!wall_time || wall_time < idle_time))
-			continue;
-
-		load = 100 * (wall_time - idle_time) / wall_time;
-
-		if (load > max_load)
-			max_load = load;
-	}
-
-	/*
-	 * break out if we 'cannot' reduce the speed as the user might
-	 * want freq_step to be zero
-	 */
-	if (dbs_tuners_ins.freq_step == 0)
-		return;
-
-	/* Check for frequency increase */
-	if (max_load > dbs_tuners_ins.up_threshold) {
-		this_dbs_info->down_skip = 0;
-
-		/* if we are already at full speed then break out early */
-		if (this_dbs_info->requested_freq == policy->max)
-			return;
-
-		freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
-		/* max freq cannot be less than 100. But who knows.... */
-		if (unlikely(freq_target == 0))
-			freq_target = 5;
-
-		this_dbs_info->requested_freq += freq_target;
-		if (this_dbs_info->requested_freq > policy->max)
-			this_dbs_info->requested_freq = policy->max;
-
-		__cpufreq_driver_target(policy, this_dbs_info->requested_freq,
-			CPUFREQ_RELATION_H);
-		return;
-	}
-
-	/*
-	 * The optimal frequency is the frequency that is the lowest that
-	 * can support the current CPU usage without triggering the up
-	 * policy. To be safe, we focus 10 points under the threshold.
-	 */
-	if (max_load < (dbs_tuners_ins.down_threshold - 10)) {
-		freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
-		this_dbs_info->requested_freq -= freq_target;
-		if (this_dbs_info->requested_freq < policy->min)
-			this_dbs_info->requested_freq = policy->min;
-
-		/*
-		 * if we cannot reduce the frequency anymore, break out early
-		 */
-		if (policy->cur == policy->min)
-			return;
-
-		__cpufreq_driver_target(policy, this_dbs_info->requested_freq,
-				CPUFREQ_RELATION_H);
-		return;
-	}
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
-	struct cpu_dbs_info_s *dbs_info =
-		container_of(work, struct cpu_dbs_info_s, work.work);
-	unsigned int cpu = dbs_info->cpu;
-
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
-	delay -= jiffies % delay;
-
-	mutex_lock(&dbs_info->timer_mutex);
-
-	dbs_check_cpu(dbs_info);
-
-	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
-	mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-	delay -= jiffies % delay;
+static struct notifier_block cs_cpufreq_notifier_block = {
+	.notifier_call = dbs_cpufreq_notifier,
+};
 
-	dbs_info->enable = 1;
-	INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
-	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct cs_ops cs_ops = {
+	.notifier_block = &cs_cpufreq_notifier_block,
+};
 
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
-{
-	dbs_info->enable = 0;
-	cancel_delayed_work_sync(&dbs_info->work);
-}
+static struct dbs_data cs_dbs_data = {
+	.governor = GOV_CONSERVATIVE,
+	.attr_group = &cs_attr_group,
+	.tuners = &cs_tuners,
+	.get_cpu_cdbs = get_cpu_cdbs,
+	.get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+	.gov_dbs_timer = cs_dbs_timer,
+	.gov_check_cpu = cs_check_cpu,
+	.gov_ops = &cs_ops,
+};
 
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
 				   unsigned int event)
 {
-	unsigned int cpu = policy->cpu;
-	struct cpu_dbs_info_s *this_dbs_info;
-	unsigned int j;
-	int rc;
-
-	this_dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
-
-	switch (event) {
-	case CPUFREQ_GOV_START:
-		if ((!cpu_online(cpu)) || (!policy->cur))
-			return -EINVAL;
-
-		mutex_lock(&dbs_mutex);
-
-		for_each_cpu(j, policy->cpus) {
-			struct cpu_dbs_info_s *j_dbs_info;
-			j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-			j_dbs_info->cur_policy = policy;
-
-			j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&j_dbs_info->prev_cpu_wall);
-			if (dbs_tuners_ins.ignore_nice)
-				j_dbs_info->prev_cpu_nice =
-						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-		}
-		this_dbs_info->cpu = cpu;
-		this_dbs_info->down_skip = 0;
-		this_dbs_info->requested_freq = policy->cur;
-
-		mutex_init(&this_dbs_info->timer_mutex);
-		dbs_enable++;
-		/*
-		 * Start the timerschedule work, when this governor
-		 * is used for first time
-		 */
-		if (dbs_enable == 1) {
-			unsigned int latency;
-			/* policy latency is in nS. Convert it to uS first */
-			latency = policy->cpuinfo.transition_latency / 1000;
-			if (latency == 0)
-				latency = 1;
-
-			rc = sysfs_create_group(cpufreq_global_kobject,
-						&dbs_attr_group);
-			if (rc) {
-				mutex_unlock(&dbs_mutex);
-				return rc;
-			}
-
-			/*
-			 * conservative does not implement micro like ondemand
-			 * governor, thus we are bound to jiffes/HZ
-			 */
-			min_sampling_rate =
-				MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
-			/* Bring kernel and HW constraints together */
-			min_sampling_rate = max(min_sampling_rate,
-					MIN_LATENCY_MULTIPLIER * latency);
-			dbs_tuners_ins.sampling_rate =
-				max(min_sampling_rate,
-				    latency * LATENCY_MULTIPLIER);
-
-			cpufreq_register_notifier(
-					&dbs_cpufreq_notifier_block,
-					CPUFREQ_TRANSITION_NOTIFIER);
-		}
-		mutex_unlock(&dbs_mutex);
-
-		dbs_timer_init(this_dbs_info);
-
-		break;
-
-	case CPUFREQ_GOV_STOP:
-		dbs_timer_exit(this_dbs_info);
-
-		mutex_lock(&dbs_mutex);
-		dbs_enable--;
-		mutex_destroy(&this_dbs_info->timer_mutex);
-
-		/*
-		 * Stop the timerschedule work, when this governor
-		 * is used for first time
-		 */
-		if (dbs_enable == 0)
-			cpufreq_unregister_notifier(
-					&dbs_cpufreq_notifier_block,
-					CPUFREQ_TRANSITION_NOTIFIER);
-
-		mutex_unlock(&dbs_mutex);
-		if (!dbs_enable)
-			sysfs_remove_group(cpufreq_global_kobject,
-					   &dbs_attr_group);
-
-		break;
-
-	case CPUFREQ_GOV_LIMITS:
-		mutex_lock(&this_dbs_info->timer_mutex);
-		if (policy->max < this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(
-					this_dbs_info->cur_policy,
-					policy->max, CPUFREQ_RELATION_H);
-		else if (policy->min > this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(
-					this_dbs_info->cur_policy,
-					policy->min, CPUFREQ_RELATION_L);
-		dbs_check_cpu(this_dbs_info);
-		mutex_unlock(&this_dbs_info->timer_mutex);
-
-		break;
-	}
-	return 0;
+	return cpufreq_governor_dbs(&cs_dbs_data, policy, event);
 }
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
@@ -597,13 +333,14 @@ static
 #endif
 struct cpufreq_governor cpufreq_gov_conservative = {
 	.name			= "conservative",
-	.governor		= cpufreq_governor_dbs,
+	.governor		= cs_cpufreq_governor_dbs,
 	.max_transition_latency	= TRANSITION_LATENCY_LIMIT,
 	.owner			= THIS_MODULE,
 };
 
 static int __init cpufreq_gov_dbs_init(void)
 {
+	mutex_init(&cs_dbs_data.mutex);
 	return cpufreq_register_governor(&cpufreq_gov_conservative);
 }
 
@@ -612,7 +349,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
 	cpufreq_unregister_governor(&cpufreq_gov_conservative);
 }
 
-
 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
 		"Low Latency Frequency Transition capable processors "
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
new file mode 100644
index 0000000..cd5fe57
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -0,0 +1,314 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.c
+ *
+ * CPUFREQ governors common code
+ *
+ * Copyright	(C) 2001 Russell King
+ *		(C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *		(C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ *		(C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *		(c) 2012 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/cputime.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/kernel_stat.h>
+#include <linux/mutex.h>
+#include <linux/tick.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "cpufreq_governor.h"
+
+static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+{
+	u64 idle_time;
+	u64 cur_wall_time;
+	u64 busy_time;
+
+	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+
+	busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
+	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
+
+	idle_time = cur_wall_time - busy_time;
+	if (wall)
+		*wall = jiffies_to_usecs(cur_wall_time);
+
+	return jiffies_to_usecs(idle_time);
+}
+
+cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+{
+	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+
+	if (idle_time == -1ULL)
+		return get_cpu_idle_time_jiffy(cpu, wall);
+	else
+		idle_time += get_cpu_iowait_time_us(cpu, wall);
+
+	return idle_time;
+}
+
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
+{
+	struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu);
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+	struct cpufreq_policy *policy;
+	unsigned int max_load = 0;
+	unsigned int ignore_nice;
+	unsigned int j;
+
+	if (dbs_data->governor == GOV_ONDEMAND)
+		ignore_nice = od_tuners->ignore_nice;
+	else
+		ignore_nice = cs_tuners->ignore_nice;
+
+	policy = cdbs->cur_policy;
+
+	/* Get Absolute Load (in terms of freq for ondemand gov) */
+	for_each_cpu(j, policy->cpus) {
+		struct cpu_dbs_common_info *j_cdbs;
+		cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time;
+		unsigned int idle_time, wall_time, iowait_time;
+		unsigned int load;
+
+		j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+
+		wall_time = (unsigned int)
+			(cur_wall_time - j_cdbs->prev_cpu_wall);
+		j_cdbs->prev_cpu_wall = cur_wall_time;
+
+		idle_time = (unsigned int)
+			(cur_idle_time - j_cdbs->prev_cpu_idle);
+		j_cdbs->prev_cpu_idle = cur_idle_time;
+
+		if (ignore_nice) {
+			u64 cur_nice;
+			unsigned long cur_nice_jiffies;
+
+			cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
+					 cdbs->prev_cpu_nice;
+			/*
+			 * Assumption: nice time between sampling periods will
+			 * be less than 2^32 jiffies for 32 bit sys
+			 */
+			cur_nice_jiffies = (unsigned long)
+					cputime64_to_jiffies64(cur_nice);
+
+			cdbs->prev_cpu_nice =
+				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+			idle_time += jiffies_to_usecs(cur_nice_jiffies);
+		}
+
+		if (dbs_data->governor == GOV_ONDEMAND) {
+			struct od_cpu_dbs_info_s *od_j_dbs_info =
+				dbs_data->get_cpu_dbs_info_s(cpu);
+
+			cur_iowait_time = get_cpu_iowait_time_us(j,
+					&cur_wall_time);
+			if (cur_iowait_time == -1ULL)
+				cur_iowait_time = 0;
+
+			iowait_time = (unsigned int) (cur_iowait_time -
+					od_j_dbs_info->prev_cpu_iowait);
+			od_j_dbs_info->prev_cpu_iowait = cur_iowait_time;
+
+			/*
+			 * For the purpose of ondemand, waiting for disk IO is
+			 * an indication that you're performance critical, and
+			 * not that the system is actually idle. So subtract the
+			 * iowait time from the cpu idle time.
+			 */
+			if (od_tuners->io_is_busy && idle_time >= iowait_time)
+				idle_time -= iowait_time;
+		}
+
+		if (unlikely(!wall_time || wall_time < idle_time))
+			continue;
+
+		load = 100 * (wall_time - idle_time) / wall_time;
+
+		if (dbs_data->governor == GOV_ONDEMAND) {
+			int freq_avg = __cpufreq_driver_getavg(policy, j);
+			if (freq_avg <= 0)
+				freq_avg = policy->cur;
+
+			load *= freq_avg;
+		}
+
+		if (load > max_load)
+			max_load = load;
+	}
+
+	dbs_data->gov_check_cpu(cpu, max_load);
+}
+
+static inline void dbs_timer_init(struct dbs_data *dbs_data,
+		struct cpu_dbs_common_info *cdbs, unsigned int sampling_rate)
+{
+	int delay = delay_for_sampling_rate(sampling_rate);
+
+	INIT_DEFERRABLE_WORK(&cdbs->work, dbs_data->gov_dbs_timer);
+	schedule_delayed_work_on(cdbs->cpu, &cdbs->work, delay);
+}
+
+static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs)
+{
+	cancel_delayed_work_sync(&cdbs->work);
+}
+
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+		struct cpufreq_policy *policy, unsigned int event)
+{
+	struct od_cpu_dbs_info_s *od_dbs_info = NULL;
+	struct cs_cpu_dbs_info_s *cs_dbs_info = NULL;
+	struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+	struct cpu_dbs_common_info *cpu_cdbs;
+	unsigned int *sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
+	int rc;
+
+	cpu_cdbs = dbs_data->get_cpu_cdbs(cpu);
+
+	if (dbs_data->governor == GOV_CONSERVATIVE) {
+		cs_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+		sampling_rate = &cs_tuners->sampling_rate;
+		ignore_nice = cs_tuners->ignore_nice;
+	} else {
+		od_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+		sampling_rate = &od_tuners->sampling_rate;
+		ignore_nice = od_tuners->ignore_nice;
+	}
+
+	switch (event) {
+	case CPUFREQ_GOV_START:
+		if ((!cpu_online(cpu)) || (!policy->cur))
+			return -EINVAL;
+
+		mutex_lock(&dbs_data->mutex);
+
+		dbs_data->enable++;
+		cpu_cdbs->cpu = cpu;
+		for_each_cpu(j, policy->cpus) {
+			struct cpu_dbs_common_info *j_cdbs;
+			j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+			j_cdbs->cur_policy = policy;
+			j_cdbs->prev_cpu_idle = get_cpu_idle_time(j,
+					&j_cdbs->prev_cpu_wall);
+			if (ignore_nice)
+				j_cdbs->prev_cpu_nice =
+					kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+		}
+
+		/*
+		 * Start the timerschedule work, when this governor is used for
+		 * first time
+		 */
+		if (dbs_data->enable != 1)
+			goto second_time;
+
+		rc = sysfs_create_group(cpufreq_global_kobject,
+				dbs_data->attr_group);
+		if (rc) {
+			mutex_unlock(&dbs_data->mutex);
+			return rc;
+		}
+
+		/* policy latency is in nS. Convert it to uS first */
+		latency = policy->cpuinfo.transition_latency / 1000;
+		if (latency == 0)
+			latency = 1;
+
+		/*
+		 * conservative does not implement micro like ondemand
+		 * governor, thus we are bound to jiffes/HZ
+		 */
+		if (dbs_data->governor == GOV_CONSERVATIVE) {
+			struct cs_ops *ops = dbs_data->gov_ops;
+
+			cpufreq_register_notifier(ops->notifier_block,
+					CPUFREQ_TRANSITION_NOTIFIER);
+
+			dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+				jiffies_to_usecs(10);
+		} else {
+			struct od_ops *ops = dbs_data->gov_ops;
+
+			od_tuners->io_is_busy = ops->io_busy();
+		}
+
+		/* Bring kernel and HW constraints together */
+		dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
+				MIN_LATENCY_MULTIPLIER * latency);
+		*sampling_rate = max(dbs_data->min_sampling_rate, latency *
+				LATENCY_MULTIPLIER);
+
+second_time:
+		if (dbs_data->governor == GOV_CONSERVATIVE) {
+			cs_dbs_info->down_skip = 0;
+			cs_dbs_info->enable = 1;
+			cs_dbs_info->requested_freq = policy->cur;
+		} else {
+			struct od_ops *ops = dbs_data->gov_ops;
+			od_dbs_info->rate_mult = 1;
+			od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+			ops->powersave_bias_init_cpu(cpu);
+		}
+		mutex_unlock(&dbs_data->mutex);
+
+		mutex_init(&cpu_cdbs->timer_mutex);
+		dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate);
+		break;
+
+	case CPUFREQ_GOV_STOP:
+		if (dbs_data->governor == GOV_CONSERVATIVE)
+			cs_dbs_info->enable = 0;
+
+		dbs_timer_exit(cpu_cdbs);
+
+		mutex_lock(&dbs_data->mutex);
+		mutex_destroy(&cpu_cdbs->timer_mutex);
+		dbs_data->enable--;
+		if (!dbs_data->enable) {
+			struct cs_ops *ops = dbs_data->gov_ops;
+
+			sysfs_remove_group(cpufreq_global_kobject,
+					dbs_data->attr_group);
+			if (dbs_data->governor == GOV_CONSERVATIVE)
+				cpufreq_unregister_notifier(ops->notifier_block,
+						CPUFREQ_TRANSITION_NOTIFIER);
+		}
+		mutex_unlock(&dbs_data->mutex);
+
+		break;
+
+	case CPUFREQ_GOV_LIMITS:
+		mutex_lock(&cpu_cdbs->timer_mutex);
+		if (policy->max < cpu_cdbs->cur_policy->cur)
+			__cpufreq_driver_target(cpu_cdbs->cur_policy,
+					policy->max, CPUFREQ_RELATION_H);
+		else if (policy->min > cpu_cdbs->cur_policy->cur)
+			__cpufreq_driver_target(cpu_cdbs->cur_policy,
+					policy->min, CPUFREQ_RELATION_L);
+		dbs_check_cpu(dbs_data, cpu);
+		mutex_unlock(&cpu_cdbs->timer_mutex);
+		break;
+	}
+	return 0;
+}
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
new file mode 100644
index 0000000..34e14ad
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -0,0 +1,177 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.h
+ *
+ * Header file for CPUFreq governors common code
+ *
+ * Copyright	(C) 2001 Russell King
+ *		(C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *		(C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ *		(C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *		(c) 2012 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * 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.
+ */
+
+#ifndef _CPUFREQ_GOVERNER_H
+#define _CPUFREQ_GOVERNER_H
+
+#include <asm/cputime.h>
+#include <linux/cpufreq.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+
+/*
+ * The polling frequency depends on the capability of the processor. Default
+ * polling frequency is 1000 times the transition latency of the processor. The
+ * governor will work on any processor with transition latency <= 10mS, using
+ * appropriate sampling rate.
+ *
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work. All times here are in uS.
+ */
+#define MIN_SAMPLING_RATE_RATIO			(2)
+#define LATENCY_MULTIPLIER			(1000)
+#define MIN_LATENCY_MULTIPLIER			(100)
+#define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
+
+/* Ondemand Sampling types */
+enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
+
+/* Macro creating sysfs show routines */
+#define show_one(_gov, file_name, object)				\
+static ssize_t show_##file_name						\
+(struct kobject *kobj, struct attribute *attr, char *buf)		\
+{									\
+	return sprintf(buf, "%u\n", _gov##_tuners.object);		\
+}
+
+#define define_get_cpu_dbs_routines(_dbs_info)				\
+static struct cpu_dbs_common_info *get_cpu_cdbs(int cpu)		\
+{									\
+	return &per_cpu(_dbs_info, cpu).cdbs;				\
+}									\
+									\
+static void *get_cpu_dbs_info_s(int cpu)				\
+{									\
+	return &per_cpu(_dbs_info, cpu);				\
+}
+
+/*
+ * Abbreviations:
+ * dbs: used as a shortform for demand based switching It helps to keep variable
+ *	names smaller, simpler
+ * cdbs: common dbs
+ * on_*: On-demand governor
+ * cs_*: Conservative governor
+ */
+
+/* Per cpu structures */
+struct cpu_dbs_common_info {
+	int cpu;
+	cputime64_t prev_cpu_idle;
+	cputime64_t prev_cpu_wall;
+	cputime64_t prev_cpu_nice;
+	struct cpufreq_policy *cur_policy;
+	struct delayed_work work;
+	/*
+	 * percpu mutex that serializes governor limit change with gov_dbs_timer
+	 * invocation. We do not want gov_dbs_timer to run when user is changing
+	 * the governor or limits.
+	 */
+	struct mutex timer_mutex;
+};
+
+struct od_cpu_dbs_info_s {
+	struct cpu_dbs_common_info cdbs;
+	cputime64_t prev_cpu_iowait;
+	struct cpufreq_frequency_table *freq_table;
+	unsigned int freq_lo;
+	unsigned int freq_lo_jiffies;
+	unsigned int freq_hi_jiffies;
+	unsigned int rate_mult;
+	unsigned int sample_type:1;
+};
+
+struct cs_cpu_dbs_info_s {
+	struct cpu_dbs_common_info cdbs;
+	unsigned int down_skip;
+	unsigned int requested_freq;
+	unsigned int enable:1;
+};
+
+/* Governers sysfs tunables */
+struct od_dbs_tuners {
+	unsigned int ignore_nice;
+	unsigned int sampling_rate;
+	unsigned int sampling_down_factor;
+	unsigned int up_threshold;
+	unsigned int down_differential;
+	unsigned int powersave_bias;
+	unsigned int io_is_busy;
+};
+
+struct cs_dbs_tuners {
+	unsigned int ignore_nice;
+	unsigned int sampling_rate;
+	unsigned int sampling_down_factor;
+	unsigned int up_threshold;
+	unsigned int down_threshold;
+	unsigned int freq_step;
+};
+
+/* Per Governer data */
+struct dbs_data {
+	/* Common across governors */
+	#define GOV_ONDEMAND		0
+	#define GOV_CONSERVATIVE	1
+	int governor;
+	unsigned int min_sampling_rate;
+	unsigned int enable; /* number of CPUs using this policy */
+	struct attribute_group *attr_group;
+	void *tuners;
+
+	/* dbs_mutex protects dbs_enable in governor start/stop */
+	struct mutex mutex;
+
+	struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu);
+	void *(*get_cpu_dbs_info_s)(int cpu);
+	void (*gov_dbs_timer)(struct work_struct *work);
+	void (*gov_check_cpu)(int cpu, unsigned int load);
+
+	/* Governor specific ops, see below */
+	void *gov_ops;
+};
+
+/* Governor specific ops, will be passed to dbs_data->gov_ops */
+struct od_ops {
+	int (*io_busy)(void);
+	void (*powersave_bias_init_cpu)(int cpu);
+	unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
+			unsigned int freq_next, unsigned int relation);
+	void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq);
+};
+
+struct cs_ops {
+	struct notifier_block *notifier_block;
+};
+
+static inline int delay_for_sampling_rate(unsigned int sampling_rate)
+{
+	int delay = usecs_to_jiffies(sampling_rate);
+
+	/* We want all CPUs to do sampling nearly on same jiffy */
+	if (num_online_cpus() > 1)
+		delay -= jiffies % delay;
+
+	return delay;
+}
+
+cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall);
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+		struct cpufreq_policy *policy, unsigned int event);
+#endif /* _CPUFREQ_GOVERNER_H */
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 396322f..bdaab92 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -10,24 +10,23 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/hrtimer.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
 #include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/types.h>
 
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
 
+/* On-demand governor macors */
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL		(10)
 #define DEF_FREQUENCY_UP_THRESHOLD		(80)
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
@@ -38,80 +37,10 @@
 #define MIN_FREQUENCY_UP_THRESHOLD		(11)
 #define MAX_FREQUENCY_UP_THRESHOLD		(100)
 
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO			(2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER			(1000)
-#define MIN_LATENCY_MULTIPLIER			(100)
-#define TRANSITION_LATENCY_LIMIT		(10 * 1000 * 1000)
+static struct dbs_data od_dbs_data;
+static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info);
 
-static void do_dbs_timer(struct work_struct *work);
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-				unsigned int event);
-
-#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
-static
-#endif
-struct cpufreq_governor cpufreq_gov_ondemand = {
-       .name                   = "ondemand",
-       .governor               = cpufreq_governor_dbs,
-       .max_transition_latency = TRANSITION_LATENCY_LIMIT,
-       .owner                  = THIS_MODULE,
-};
-
-/* Sampling types */
-enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
-
-struct cpu_dbs_info_s {
-	cputime64_t prev_cpu_idle;
-	cputime64_t prev_cpu_iowait;
-	cputime64_t prev_cpu_wall;
-	cputime64_t prev_cpu_nice;
-	struct cpufreq_policy *cur_policy;
-	struct delayed_work work;
-	struct cpufreq_frequency_table *freq_table;
-	unsigned int freq_lo;
-	unsigned int freq_lo_jiffies;
-	unsigned int freq_hi_jiffies;
-	unsigned int rate_mult;
-	int cpu;
-	unsigned int sample_type:1;
-	/*
-	 * percpu mutex that serializes governor limit change with
-	 * do_dbs_timer invocation. We do not want do_dbs_timer to run
-	 * when user is changing the governor or limits.
-	 */
-	struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info);
-
-static unsigned int dbs_enable;	/* number of CPUs using this policy */
-
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
-	unsigned int sampling_rate;
-	unsigned int up_threshold;
-	unsigned int down_differential;
-	unsigned int ignore_nice;
-	unsigned int sampling_down_factor;
-	unsigned int powersave_bias;
-	unsigned int io_is_busy;
-} dbs_tuners_ins = {
+static struct od_dbs_tuners od_tuners = {
 	.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
 	.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
 	.down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
@@ -119,48 +48,35 @@ static struct dbs_tuners {
 	.powersave_bias = 0,
 };
 
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
-{
-	u64 idle_time;
-	u64 cur_wall_time;
-	u64 busy_time;
-
-	cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
-
-	busy_time  = kcpustat_cpu(cpu).cpustat[CPUTIME_USER];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL];
-	busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE];
-
-	idle_time = cur_wall_time - busy_time;
-	if (wall)
-		*wall = jiffies_to_usecs(cur_wall_time);
-
-	return jiffies_to_usecs(idle_time);
-}
-
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+static void ondemand_powersave_bias_init_cpu(int cpu)
 {
-	u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
-
-	if (idle_time == -1ULL)
-		return get_cpu_idle_time_jiffy(cpu, wall);
-	else
-		idle_time += get_cpu_iowait_time_us(cpu, wall);
+	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
 
-	return idle_time;
+	dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
+	dbs_info->freq_lo = 0;
 }
 
-static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall)
+/*
+ * Not all CPUs want IO time to be accounted as busy; this depends on how
+ * efficient idling at a higher frequency/voltage is.
+ * Pavel Machek says this is not so for various generations of AMD and old
+ * Intel systems.
+ * Mike Chan (androidlcom) calis this is also not true for ARM.
+ * Because of this, whitelist specific known (series) of CPUs by default, and
+ * leave all others up to the user.
+ */
+static int should_io_be_busy(void)
 {
-	u64 iowait_time = get_cpu_iowait_time_us(cpu, wall);
-
-	if (iowait_time == -1ULL)
-		return 0;
-
-	return iowait_time;
+#if defined(CONFIG_X86)
+	/*
+	 * For Intel, Core 2 (model 15) andl later have an efficient idle.
+	 */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+			boot_cpu_data.x86 == 6 &&
+			boot_cpu_data.x86_model >= 15)
+		return 1;
+#endif
+	return 0;
 }
 
 /*
@@ -169,14 +85,13 @@ static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wal
  * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs.
  */
 static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
-					  unsigned int freq_next,
-					  unsigned int relation)
+		unsigned int freq_next, unsigned int relation)
 {
 	unsigned int freq_req, freq_reduc, freq_avg;
 	unsigned int freq_hi, freq_lo;
 	unsigned int index = 0;
 	unsigned int jiffies_total, jiffies_hi, jiffies_lo;
-	struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
 						   policy->cpu);
 
 	if (!dbs_info->freq_table) {
@@ -188,7 +103,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 	cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next,
 			relation, &index);
 	freq_req = dbs_info->freq_table[index].frequency;
-	freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000;
+	freq_reduc = freq_req * od_tuners.powersave_bias / 1000;
 	freq_avg = freq_req - freq_reduc;
 
 	/* Find freq bounds for freq_avg in freq_table */
@@ -207,7 +122,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 		dbs_info->freq_lo_jiffies = 0;
 		return freq_lo;
 	}
-	jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+	jiffies_total = usecs_to_jiffies(od_tuners.sampling_rate);
 	jiffies_hi = (freq_avg - freq_lo) * jiffies_total;
 	jiffies_hi += ((freq_hi - freq_lo) / 2);
 	jiffies_hi /= (freq_hi - freq_lo);
@@ -218,13 +133,6 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
 	return freq_hi;
 }
 
-static void ondemand_powersave_bias_init_cpu(int cpu)
-{
-	struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-	dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
-	dbs_info->freq_lo = 0;
-}
-
 static void ondemand_powersave_bias_init(void)
 {
 	int i;
@@ -233,53 +141,138 @@ static void ondemand_powersave_bias_init(void)
 	}
 }
 
-/************************** sysfs interface ************************/
+static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
+{
+	if (od_tuners.powersave_bias)
+		freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
+	else if (p->cur == p->max)
+		return;
 
-static ssize_t show_sampling_rate_min(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
+	__cpufreq_driver_target(p, freq, od_tuners.powersave_bias ?
+			CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
+}
+
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate, we look for
+ * a the lowest frequency which can sustain the load while keeping idle time
+ * over 30%. If such a frequency exist, we try to decrease to this frequency.
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of current frequency
+ */
+static void od_check_cpu(int cpu, unsigned int load_freq)
 {
-	return sprintf(buf, "%u\n", min_sampling_rate);
+	struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+	struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+
+	dbs_info->freq_lo = 0;
+
+	/* Check for frequency increase */
+	if (load_freq > od_tuners.up_threshold * policy->cur) {
+		/* If switching to max speed, apply sampling_down_factor */
+		if (policy->cur < policy->max)
+			dbs_info->rate_mult =
+				od_tuners.sampling_down_factor;
+		dbs_freq_increase(policy, policy->max);
+		return;
+	}
+
+	/* Check for frequency decrease */
+	/* if we cannot reduce the frequency anymore, break out early */
+	if (policy->cur == policy->min)
+		return;
+
+	/*
+	 * The optimal frequency is the frequency that is the lowest that can
+	 * support the current CPU usage without triggering the up policy. To be
+	 * safe, we focus 10 points under the threshold.
+	 */
+	if (load_freq < (od_tuners.up_threshold - od_tuners.down_differential) *
+			policy->cur) {
+		unsigned int freq_next;
+		freq_next = load_freq / (od_tuners.up_threshold -
+				od_tuners.down_differential);
+
+		/* No longer fully busy, reset rate_mult */
+		dbs_info->rate_mult = 1;
+
+		if (freq_next < policy->min)
+			freq_next = policy->min;
+
+		if (!od_tuners.powersave_bias) {
+			__cpufreq_driver_target(policy, freq_next,
+					CPUFREQ_RELATION_L);
+		} else {
+			int freq = powersave_bias_target(policy, freq_next,
+					CPUFREQ_RELATION_L);
+			__cpufreq_driver_target(policy, freq,
+					CPUFREQ_RELATION_L);
+		}
+	}
 }
 
-define_one_global_ro(sampling_rate_min);
+static void od_dbs_timer(struct work_struct *work)
+{
+	struct od_cpu_dbs_info_s *dbs_info =
+		container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work);
+	unsigned int cpu = dbs_info->cdbs.cpu;
+	int delay, sample_type = dbs_info->sample_type;
+
+	mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-/* cpufreq_ondemand Governor Tunables */
-#define show_one(file_name, object)					\
-static ssize_t show_##file_name						\
-(struct kobject *kobj, struct attribute *attr, char *buf)              \
-{									\
-	return sprintf(buf, "%u\n", dbs_tuners_ins.object);		\
+	/* Common NORMAL_SAMPLE setup */
+	dbs_info->sample_type = OD_NORMAL_SAMPLE;
+	if (sample_type == OD_SUB_SAMPLE) {
+		delay = dbs_info->freq_lo_jiffies;
+		__cpufreq_driver_target(dbs_info->cdbs.cur_policy,
+			dbs_info->freq_lo, CPUFREQ_RELATION_H);
+	} else {
+		dbs_check_cpu(&od_dbs_data, cpu);
+		if (dbs_info->freq_lo) {
+			/* Setup timer for SUB_SAMPLE */
+			dbs_info->sample_type = OD_SUB_SAMPLE;
+			delay = dbs_info->freq_hi_jiffies;
+		} else {
+			delay = delay_for_sampling_rate(dbs_info->rate_mult);
+		}
+	}
+
+	schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+	mutex_unlock(&dbs_info->cdbs.timer_mutex);
+}
+
+/************************** sysfs interface ************************/
+
+static ssize_t show_sampling_rate_min(struct kobject *kobj,
+				      struct attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u\n", od_dbs_data.min_sampling_rate);
 }
-show_one(sampling_rate, sampling_rate);
-show_one(io_is_busy, io_is_busy);
-show_one(up_threshold, up_threshold);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(ignore_nice_load, ignore_nice);
-show_one(powersave_bias, powersave_bias);
 
 /**
  * update_sampling_rate - update sampling rate effective immediately if needed.
  * @new_rate: new sampling rate
  *
  * If new rate is smaller than the old, simply updaing
- * dbs_tuners_int.sampling_rate might not be appropriate. For example,
- * if the original sampling_rate was 1 second and the requested new sampling
- * rate is 10 ms because the user needs immediate reaction from ondemand
- * governor, but not sure if higher frequency will be required or not,
- * then, the governor may change the sampling rate too late; up to 1 second
- * later. Thus, if we are reducing the sampling rate, we need to make the
- * new value effective immediately.
+ * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the
+ * original sampling_rate was 1 second and the requested new sampling rate is 10
+ * ms because the user needs immediate reaction from ondemand governor, but not
+ * sure if higher frequency will be required or not, then, the governor may
+ * change the sampling rate too late; up to 1 second later. Thus, if we are
+ * reducing the sampling rate, we need to make the new value effective
+ * immediately.
  */
 static void update_sampling_rate(unsigned int new_rate)
 {
 	int cpu;
 
-	dbs_tuners_ins.sampling_rate = new_rate
-				     = max(new_rate, min_sampling_rate);
+	od_tuners.sampling_rate = new_rate = max(new_rate,
+			od_dbs_data.min_sampling_rate);
 
 	for_each_online_cpu(cpu) {
 		struct cpufreq_policy *policy;
-		struct cpu_dbs_info_s *dbs_info;
+		struct od_cpu_dbs_info_s *dbs_info;
 		unsigned long next_sampling, appointed_at;
 
 		policy = cpufreq_cpu_get(cpu);
@@ -288,28 +281,28 @@ static void update_sampling_rate(unsigned int new_rate)
 		dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu);
 		cpufreq_cpu_put(policy);
 
-		mutex_lock(&dbs_info->timer_mutex);
+		mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-		if (!delayed_work_pending(&dbs_info->work)) {
-			mutex_unlock(&dbs_info->timer_mutex);
+		if (!delayed_work_pending(&dbs_info->cdbs.work)) {
+			mutex_unlock(&dbs_info->cdbs.timer_mutex);
 			continue;
 		}
 
-		next_sampling  = jiffies + usecs_to_jiffies(new_rate);
-		appointed_at = dbs_info->work.timer.expires;
-
+		next_sampling = jiffies + usecs_to_jiffies(new_rate);
+		appointed_at = dbs_info->cdbs.work.timer.expires;
 
 		if (time_before(next_sampling, appointed_at)) {
 
-			mutex_unlock(&dbs_info->timer_mutex);
-			cancel_delayed_work_sync(&dbs_info->work);
-			mutex_lock(&dbs_info->timer_mutex);
+			mutex_unlock(&dbs_info->cdbs.timer_mutex);
+			cancel_delayed_work_sync(&dbs_info->cdbs.work);
+			mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-			schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
-						 usecs_to_jiffies(new_rate));
+			schedule_delayed_work_on(dbs_info->cdbs.cpu,
+					&dbs_info->cdbs.work,
+					usecs_to_jiffies(new_rate));
 
 		}
-		mutex_unlock(&dbs_info->timer_mutex);
+		mutex_unlock(&dbs_info->cdbs.timer_mutex);
 	}
 }
 
@@ -334,7 +327,7 @@ static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-	dbs_tuners_ins.io_is_busy = !!input;
+	od_tuners.io_is_busy = !!input;
 	return count;
 }
 
@@ -349,7 +342,7 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 			input < MIN_FREQUENCY_UP_THRESHOLD) {
 		return -EINVAL;
 	}
-	dbs_tuners_ins.up_threshold = input;
+	od_tuners.up_threshold = input;
 	return count;
 }
 
@@ -362,12 +355,12 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
-	dbs_tuners_ins.sampling_down_factor = input;
+	od_tuners.sampling_down_factor = input;
 
 	/* Reset down sampling multiplier in case it was active */
 	for_each_online_cpu(j) {
-		struct cpu_dbs_info_s *dbs_info;
-		dbs_info = &per_cpu(od_cpu_dbs_info, j);
+		struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+				j);
 		dbs_info->rate_mult = 1;
 	}
 	return count;
@@ -388,19 +381,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
+	if (input == od_tuners.ignore_nice) { /* nothing to do */
 		return count;
 	}
-	dbs_tuners_ins.ignore_nice = input;
+	od_tuners.ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
 	for_each_online_cpu(j) {
-		struct cpu_dbs_info_s *dbs_info;
+		struct od_cpu_dbs_info_s *dbs_info;
 		dbs_info = &per_cpu(od_cpu_dbs_info, j);
-		dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&dbs_info->prev_cpu_wall);
-		if (dbs_tuners_ins.ignore_nice)
-			dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+		dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+						&dbs_info->cdbs.prev_cpu_wall);
+		if (od_tuners.ignore_nice)
+			dbs_info->cdbs.prev_cpu_nice =
+				kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
 	}
 	return count;
@@ -419,17 +413,25 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
 	if (input > 1000)
 		input = 1000;
 
-	dbs_tuners_ins.powersave_bias = input;
+	od_tuners.powersave_bias = input;
 	ondemand_powersave_bias_init();
 	return count;
 }
 
+show_one(od, sampling_rate, sampling_rate);
+show_one(od, io_is_busy, io_is_busy);
+show_one(od, up_threshold, up_threshold);
+show_one(od, sampling_down_factor, sampling_down_factor);
+show_one(od, ignore_nice_load, ignore_nice);
+show_one(od, powersave_bias, powersave_bias);
+
 define_one_global_rw(sampling_rate);
 define_one_global_rw(io_is_busy);
 define_one_global_rw(up_threshold);
 define_one_global_rw(sampling_down_factor);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(powersave_bias);
+define_one_global_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
 	&sampling_rate_min.attr,
@@ -442,354 +444,71 @@ static struct attribute *dbs_attributes[] = {
 	NULL
 };
 
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group od_attr_group = {
 	.attrs = dbs_attributes,
 	.name = "ondemand",
 };
 
 /************************** sysfs end ************************/
 
-static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
-{
-	if (dbs_tuners_ins.powersave_bias)
-		freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
-	else if (p->cur == p->max)
-		return;
-
-	__cpufreq_driver_target(p, freq, dbs_tuners_ins.powersave_bias ?
-			CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
-}
-
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
-	unsigned int max_load_freq;
-
-	struct cpufreq_policy *policy;
-	unsigned int j;
-
-	this_dbs_info->freq_lo = 0;
-	policy = this_dbs_info->cur_policy;
-
-	/*
-	 * Every sampling_rate, we check, if current idle time is less
-	 * than 20% (default), then we try to increase frequency
-	 * Every sampling_rate, we look for a the lowest
-	 * frequency which can sustain the load while keeping idle time over
-	 * 30%. If such a frequency exist, we try to decrease to this frequency.
-	 *
-	 * Any frequency increase takes it to the maximum frequency.
-	 * Frequency reduction happens at minimum steps of
-	 * 5% (default) of current frequency
-	 */
-
-	/* Get Absolute Load - in terms of freq */
-	max_load_freq = 0;
-
-	for_each_cpu(j, policy->cpus) {
-		struct cpu_dbs_info_s *j_dbs_info;
-		cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time;
-		unsigned int idle_time, wall_time, iowait_time;
-		unsigned int load, load_freq;
-		int freq_avg;
-
-		j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
-
-		cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
-		cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time);
-
-		wall_time = (unsigned int)
-			(cur_wall_time - j_dbs_info->prev_cpu_wall);
-		j_dbs_info->prev_cpu_wall = cur_wall_time;
-
-		idle_time = (unsigned int)
-			(cur_idle_time - j_dbs_info->prev_cpu_idle);
-		j_dbs_info->prev_cpu_idle = cur_idle_time;
-
-		iowait_time = (unsigned int)
-			(cur_iowait_time - j_dbs_info->prev_cpu_iowait);
-		j_dbs_info->prev_cpu_iowait = cur_iowait_time;
-
-		if (dbs_tuners_ins.ignore_nice) {
-			u64 cur_nice;
-			unsigned long cur_nice_jiffies;
-
-			cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
-					 j_dbs_info->prev_cpu_nice;
-			/*
-			 * Assumption: nice time between sampling periods will
-			 * be less than 2^32 jiffies for 32 bit sys
-			 */
-			cur_nice_jiffies = (unsigned long)
-					cputime64_to_jiffies64(cur_nice);
-
-			j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-			idle_time += jiffies_to_usecs(cur_nice_jiffies);
-		}
-
-		/*
-		 * For the purpose of ondemand, waiting for disk IO is an
-		 * indication that you're performance critical, and not that
-		 * the system is actually idle. So subtract the iowait time
-		 * from the cpu idle time.
-		 */
-
-		if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time)
-			idle_time -= iowait_time;
-
-		if (unlikely(!wall_time || wall_time < idle_time))
-			continue;
-
-		load = 100 * (wall_time - idle_time) / wall_time;
-
-		freq_avg = __cpufreq_driver_getavg(policy, j);
-		if (freq_avg <= 0)
-			freq_avg = policy->cur;
-
-		load_freq = load * freq_avg;
-		if (load_freq > max_load_freq)
-			max_load_freq = load_freq;
-	}
+define_get_cpu_dbs_routines(od_cpu_dbs_info);
 
-	/* Check for frequency increase */
-	if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
-		/* If switching to max speed, apply sampling_down_factor */
-		if (policy->cur < policy->max)
-			this_dbs_info->rate_mult =
-				dbs_tuners_ins.sampling_down_factor;
-		dbs_freq_increase(policy, policy->max);
-		return;
-	}
-
-	/* Check for frequency decrease */
-	/* if we cannot reduce the frequency anymore, break out early */
-	if (policy->cur == policy->min)
-		return;
-
-	/*
-	 * The optimal frequency is the frequency that is the lowest that
-	 * can support the current CPU usage without triggering the up
-	 * policy. To be safe, we focus 10 points under the threshold.
-	 */
-	if (max_load_freq <
-	    (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) *
-	     policy->cur) {
-		unsigned int freq_next;
-		freq_next = max_load_freq /
-				(dbs_tuners_ins.up_threshold -
-				 dbs_tuners_ins.down_differential);
-
-		/* No longer fully busy, reset rate_mult */
-		this_dbs_info->rate_mult = 1;
-
-		if (freq_next < policy->min)
-			freq_next = policy->min;
-
-		if (!dbs_tuners_ins.powersave_bias) {
-			__cpufreq_driver_target(policy, freq_next,
-					CPUFREQ_RELATION_L);
-		} else {
-			int freq = powersave_bias_target(policy, freq_next,
-					CPUFREQ_RELATION_L);
-			__cpufreq_driver_target(policy, freq,
-				CPUFREQ_RELATION_L);
-		}
-	}
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
-	struct cpu_dbs_info_s *dbs_info =
-		container_of(work, struct cpu_dbs_info_s, work.work);
-	unsigned int cpu = dbs_info->cpu;
-	int sample_type = dbs_info->sample_type;
-
-	int delay;
-
-	mutex_lock(&dbs_info->timer_mutex);
-
-	/* Common NORMAL_SAMPLE setup */
-	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-	if (!dbs_tuners_ins.powersave_bias ||
-	    sample_type == DBS_NORMAL_SAMPLE) {
-		dbs_check_cpu(dbs_info);
-		if (dbs_info->freq_lo) {
-			/* Setup timer for SUB_SAMPLE */
-			dbs_info->sample_type = DBS_SUB_SAMPLE;
-			delay = dbs_info->freq_hi_jiffies;
-		} else {
-			/* We want all CPUs to do sampling nearly on
-			 * same jiffy
-			 */
-			delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
-				* dbs_info->rate_mult);
-
-			if (num_online_cpus() > 1)
-				delay -= jiffies % delay;
-		}
-	} else {
-		__cpufreq_driver_target(dbs_info->cur_policy,
-			dbs_info->freq_lo, CPUFREQ_RELATION_H);
-		delay = dbs_info->freq_lo_jiffies;
-	}
-	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
-	mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
-	if (num_online_cpus() > 1)
-		delay -= jiffies % delay;
+static struct od_ops od_ops = {
+	.io_busy = should_io_be_busy,
+	.powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu,
+	.powersave_bias_target = powersave_bias_target,
+	.freq_increase = dbs_freq_increase,
+};
 
-	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-	INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
-	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct dbs_data od_dbs_data = {
+	.governor = GOV_ONDEMAND,
+	.attr_group = &od_attr_group,
+	.tuners = &od_tuners,
+	.get_cpu_cdbs = get_cpu_cdbs,
+	.get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+	.gov_dbs_timer = od_dbs_timer,
+	.gov_check_cpu = od_check_cpu,
+	.gov_ops = &od_ops,
+};
 
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
+static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy,
+		unsigned int event)
 {
-	cancel_delayed_work_sync(&dbs_info->work);
+	return cpufreq_governor_dbs(&od_dbs_data, policy, event);
 }
 
-/*
- * Not all CPUs want IO time to be accounted as busy; this dependson how
- * efficient idling at a higher frequency/voltage is.
- * Pavel Machek says this is not so for various generations of AMD and old
- * Intel systems.
- * Mike Chan (androidlcom) calis this is also not true for ARM.
- * Because of this, whitelist specific known (series) of CPUs by default, and
- * leave all others up to the user.
- */
-static int should_io_be_busy(void)
-{
-#if defined(CONFIG_X86)
-	/*
-	 * For Intel, Core 2 (model 15) andl later have an efficient idle.
-	 */
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
-	    boot_cpu_data.x86 == 6 &&
-	    boot_cpu_data.x86_model >= 15)
-		return 1;
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
+static
 #endif
-	return 0;
-}
-
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-				   unsigned int event)
-{
-	unsigned int cpu = policy->cpu;
-	struct cpu_dbs_info_s *this_dbs_info;
-	unsigned int j;
-	int rc;
-
-	this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-
-	switch (event) {
-	case CPUFREQ_GOV_START:
-		if ((!cpu_online(cpu)) || (!policy->cur))
-			return -EINVAL;
-
-		mutex_lock(&dbs_mutex);
-
-		dbs_enable++;
-		for_each_cpu(j, policy->cpus) {
-			struct cpu_dbs_info_s *j_dbs_info;
-			j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
-			j_dbs_info->cur_policy = policy;
-
-			j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-						&j_dbs_info->prev_cpu_wall);
-			if (dbs_tuners_ins.ignore_nice)
-				j_dbs_info->prev_cpu_nice =
-						kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-		}
-		this_dbs_info->cpu = cpu;
-		this_dbs_info->rate_mult = 1;
-		ondemand_powersave_bias_init_cpu(cpu);
-		/*
-		 * Start the timerschedule work, when this governor
-		 * is used for first time
-		 */
-		if (dbs_enable == 1) {
-			unsigned int latency;
-
-			rc = sysfs_create_group(cpufreq_global_kobject,
-						&dbs_attr_group);
-			if (rc) {
-				mutex_unlock(&dbs_mutex);
-				return rc;
-			}
-
-			/* policy latency is in nS. Convert it to uS first */
-			latency = policy->cpuinfo.transition_latency / 1000;
-			if (latency == 0)
-				latency = 1;
-			/* Bring kernel and HW constraints together */
-			min_sampling_rate = max(min_sampling_rate,
-					MIN_LATENCY_MULTIPLIER * latency);
-			dbs_tuners_ins.sampling_rate =
-				max(min_sampling_rate,
-				    latency * LATENCY_MULTIPLIER);
-			dbs_tuners_ins.io_is_busy = should_io_be_busy();
-		}
-		mutex_unlock(&dbs_mutex);
-
-		mutex_init(&this_dbs_info->timer_mutex);
-		dbs_timer_init(this_dbs_info);
-		break;
-
-	case CPUFREQ_GOV_STOP:
-		dbs_timer_exit(this_dbs_info);
-
-		mutex_lock(&dbs_mutex);
-		mutex_destroy(&this_dbs_info->timer_mutex);
-		dbs_enable--;
-		mutex_unlock(&dbs_mutex);
-		if (!dbs_enable)
-			sysfs_remove_group(cpufreq_global_kobject,
-					   &dbs_attr_group);
-
-		break;
-
-	case CPUFREQ_GOV_LIMITS:
-		mutex_lock(&this_dbs_info->timer_mutex);
-		if (policy->max < this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(this_dbs_info->cur_policy,
-				policy->max, CPUFREQ_RELATION_H);
-		else if (policy->min > this_dbs_info->cur_policy->cur)
-			__cpufreq_driver_target(this_dbs_info->cur_policy,
-				policy->min, CPUFREQ_RELATION_L);
-		dbs_check_cpu(this_dbs_info);
-		mutex_unlock(&this_dbs_info->timer_mutex);
-		break;
-	}
-	return 0;
-}
+struct cpufreq_governor cpufreq_gov_ondemand = {
+	.name			= "ondemand",
+	.governor		= od_cpufreq_governor_dbs,
+	.max_transition_latency	= TRANSITION_LATENCY_LIMIT,
+	.owner			= THIS_MODULE,
+};
 
 static int __init cpufreq_gov_dbs_init(void)
 {
 	u64 idle_time;
 	int cpu = get_cpu();
 
+	mutex_init(&od_dbs_data.mutex);
 	idle_time = get_cpu_idle_time_us(cpu, NULL);
 	put_cpu();
 	if (idle_time != -1ULL) {
 		/* Idle micro accounting is supported. Use finer thresholds */
-		dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
-		dbs_tuners_ins.down_differential =
-					MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+		od_tuners.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+		od_tuners.down_differential = MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
 		/*
 		 * In nohz/micro accounting case we set the minimum frequency
 		 * not depending on HZ, but fixed (very low). The deferred
 		 * timer might skip some samples if idle/sleeping as needed.
 		*/
-		min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
+		od_dbs_data.min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
 	} else {
 		/* For correct statistics, we need 10 ticks for each measure */
-		min_sampling_rate =
-			MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
+		od_dbs_data.min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+			jiffies_to_usecs(10);
 	}
 
 	return cpufreq_register_governor(&cpufreq_gov_ondemand);
@@ -800,7 +519,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
 	cpufreq_unregister_governor(&cpufreq_gov_ondemand);
 }
 
-
 MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
 MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>");
 MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index fc4b785..2f0f2da 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -11,6 +11,7 @@
 #ifndef _LINUX_CPUFREQ_H
 #define _LINUX_CPUFREQ_H
 
+#include <asm/cputime.h>
 #include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/threads.h>
@@ -407,5 +408,4 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
 
-
 #endif /* _LINUX_CPUFREQ_H */
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH] ARM: Kirkwood: new board USI Topkick
From: Jason Cooper @ 2012-10-19 20:49 UTC (permalink / raw)
  To: linux-arm-kernel

This is a new kirkwood box made by Universal Scientific Industrial, Inc.
The product description is here:

http://www.usish.com/english/products_topkick1281p2.php

It is very similar to the dreamplug and other plug devices, with the
exception that it has room for a 2.5" SATA HDD internally.

Signed-off-by: Jason Cooper <jason@lakedaemon.net>
---
 arch/arm/boot/dts/Makefile                 |  3 +-
 arch/arm/boot/dts/kirkwood-topkick.dts     | 85 +++++++++++++++++++++++++++
 arch/arm/mach-kirkwood/Kconfig             |  7 +++
 arch/arm/mach-kirkwood/Makefile            |  1 +
 arch/arm/mach-kirkwood/board-dt.c          |  4 ++
 arch/arm/mach-kirkwood/board-usi_topkick.c | 93 ++++++++++++++++++++++++++++++
 arch/arm/mach-kirkwood/common.h            |  6 ++
 7 files changed, 198 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/boot/dts/kirkwood-topkick.dts
 create mode 100644 arch/arm/mach-kirkwood/board-usi_topkick.c

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index c1ce813..04fffc7 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -38,7 +38,8 @@ dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
 	kirkwood-lschlv2.dtb \
 	kirkwood-lsxhl.dtb \
 	kirkwood-ts219-6281.dtb \
-	kirkwood-ts219-6282.dtb
+	kirkwood-ts219-6282.dtb \
+	kirkwood-topkick.dtb
 dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
 	msm8960-cdp.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
diff --git a/arch/arm/boot/dts/kirkwood-topkick.dts b/arch/arm/boot/dts/kirkwood-topkick.dts
new file mode 100644
index 0000000..08a0400
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-topkick.dts
@@ -0,0 +1,85 @@
+/dts-v1/;
+
+/include/ "kirkwood.dtsi"
+
+/ {
+	model = "Univeral Scientific Industrial Co. Topkick-1281P2";
+	compatible = "usi,topkick-1281P2", "usi,topkick", "marvell,kirkwood-88f6282", "marvell,kirkwood";
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+	};
+
+	ocp at f1000000 {
+		serial at 12000 {
+			clock-frequency = <200000000>;
+			status = "ok";
+		};
+
+		nand at 3000000 {
+			status = "okay";
+
+			partition at 0 {
+				label = "u-boot";
+				reg = <0x0000000 0x180000>;
+			};
+
+			partition at 180000 {
+				label = "u-boot env";
+				reg = <0x0180000 0x20000>;
+			};
+
+			partition at 200000 {
+				label = "uImage";
+				reg = <0x0200000 0x600000>;
+			};
+
+			partition at 800000 {
+				label = "uInitrd";
+				reg = <0x0800000 0x1000000>;
+			};
+
+			partition at 1800000 {
+				label = "rootfs";
+				reg = <0x1800000 0xe800000>;
+			};
+		};
+
+		sata at 80000 {
+			status = "okay";
+			nr-ports = <2>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		disk {
+			label = "topkick:yellow:disk";
+			gpios = <&gpio0 21 1>;
+			linux,default-trigger = "ide-disk";
+		};
+		system2 {
+			label = "topkick:red:system";
+			gpios = <&gpio1 5 1>;
+		};
+		system {
+			label = "topkick:blue:system";
+			gpios = <&gpio1 6 1>;
+			default-state = "on";
+		};
+		wifi {
+			label = "topkick:green:wifi";
+			gpios = <&gpio1 7 1>;
+		};
+		wifi2 {
+			label = "topkick:yellow:wifi";
+			gpios = <&gpio1 16 1>;
+		};
+	};
+};
diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig
index 50bca50..b8b5c22 100644
--- a/arch/arm/mach-kirkwood/Kconfig
+++ b/arch/arm/mach-kirkwood/Kconfig
@@ -130,6 +130,13 @@ config MACH_KM_KIRKWOOD_DT
 	  Say 'Y' here if you want your kernel to support the
 	  Keymile Kirkwood Reference Desgin, using Flattened Device Tree.
 
+config MACH_TOPKICK_DT
+	bool "USI Topkick (Flattened Device Tree)"
+	select ARCH_KIRKWOOD_DT
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  USI Topkick, using Flattened Device Tree
+
 config MACH_TS219
 	bool "QNAP TS-110, TS-119, TS-119P+, TS-210, TS-219, TS-219P and TS-219P+ Turbo NAS"
 	help
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 294779f..bd463df 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_MACH_GOFLEXNET_DT)		+= board-goflexnet.o
 obj-$(CONFIG_MACH_LSXL_DT)		+= board-lsxl.o
 obj-$(CONFIG_MACH_IOMEGA_IX2_200_DT)	+= board-iomega_ix2_200.o
 obj-$(CONFIG_MACH_KM_KIRKWOOD_DT)	+= board-km_kirkwood.o
+obj-$(CONFIG_MACH_TOPKICK_DT)		+= board-usi_topkick.o
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index 70c5a28..33e9217 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -96,6 +96,9 @@ static void __init kirkwood_dt_init(void)
 	if (of_machine_is_compatible("keymile,km_kirkwood"))
 		km_kirkwood_init();
 
+	if (of_machine_is_compatible("usi,topkick"))
+		usi_topkick_init();
+
 	of_platform_populate(NULL, kirkwood_dt_match_table,
 			     kirkwood_auxdata_lookup, NULL);
 }
@@ -112,6 +115,7 @@ static const char *kirkwood_dt_board_compat[] = {
 	"buffalo,lsxl",
 	"iom,ix2-200",
 	"keymile,km_kirkwood",
+	"usi,topkick",
 	NULL
 };
 
diff --git a/arch/arm/mach-kirkwood/board-usi_topkick.c b/arch/arm/mach-kirkwood/board-usi_topkick.c
new file mode 100644
index 0000000..02ba4aa
--- /dev/null
+++ b/arch/arm/mach-kirkwood/board-usi_topkick.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
+ *
+ * arch/arm/mach-kirkwood/board-dreamplug.c
+ *
+ * Marvell DreamPlug Reference Board Init for drivers not converted to
+ * flattened device tree yet.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <mach/kirkwood.h>
+#include <mach/bridge-regs.h>
+#include <linux/platform_data/mmc-mvsdio.h>
+#include "common.h"
+#include "mpp.h"
+
+static struct mv643xx_eth_platform_data topkick_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),
+};
+
+/*
+ * GPIO LED layout
+ *
+ *       /-SYS_LED(2)
+ *       |
+ *       |   /-DISK_LED
+ *       |   |
+ *       |   |   /-WLAN_LED(2)
+ *       |   |   |
+ * [SW] [*] [*] [*]
+ */
+
+/*
+ * Switch positions
+ *
+ *     /-SW_LEFT
+ *     |
+ *     |   /-SW_IDLE
+ *     |   |
+ *     |   |   /-SW_RIGHT
+ *     |   |   |
+ * PS [L] [I] [R] LEDS
+ */
+
+static unsigned int topkick_mpp_config[] __initdata = {
+	MPP21_GPIO,	/* DISK_LED           (low active) - yellow */
+	MPP36_GPIO,	/* SATA0 power enable (high active) */
+	MPP37_GPIO,	/* SYS_LED2           (low active) - red */
+	MPP38_GPIO,	/* SYS_LED            (low active) - blue */
+	MPP39_GPIO,	/* WLAN_LED           (low active) - green */
+	MPP43_GPIO,	/* SW_LEFT            (low active) */
+	MPP44_GPIO,     /* SW_RIGHT           (low active) */
+	MPP45_GPIO,	/* SW_IDLE            (low active) */
+	MPP46_GPIO,     /* SW_LEFT            (low active) */
+	MPP48_GPIO,	/* WLAN_LED2          (low active) - yellow */
+	0
+};
+
+#define TOPKICK_SATA0_PWR_ENABLE 36
+
+void __init usi_topkick_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_mpp_conf(topkick_mpp_config);
+
+	/* SATA0 power enable */
+	gpio_set_value(TOPKICK_SATA0_PWR_ENABLE, 1);
+
+	kirkwood_ehci_init();
+	kirkwood_ge00_init(&topkick_ge00_data);
+}
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index bcffd7c..46b47d1 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -112,6 +112,12 @@ void km_kirkwood_init(void);
 static inline void km_kirkwood_init(void) {};
 #endif
 
+#ifdef CONFIG_MACH_TOPKICK_DT
+void usi_topkick_init(void);
+#else
+static inline void usi_topkick_init(void) {};
+#endif
+
 /* early init functions not converted to fdt yet */
 char *kirkwood_id(void);
 void kirkwood_l2_init(void);
-- 
1.7.12.4

^ permalink raw reply related

* [GIT PULL v3] ARM architecture fixes for 3.7
From: Arnd Bergmann @ 2012-10-19 21:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

you never replied to the second version of the pull request, and it hasn't
shown up in linux-next or your git tree so far. I assume you've been busy
otherwise and missed it, so here is a friendly reminder.

The contents are still identical to what we had before after I fixed up
the changeset comment for the Xen patch.

	Arnd

---
The following changes since commit 0e51793e162ca432fc5f04178cf82b80a92c2659:

  Merge branch 'for-linus' of git://git.linaro.org/people/rmk/linux-arm (2012-10-07 21:20:57 +0900)

are available in the git repository at:


  git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git tags/fixes-for-rmk

for you to fetch changes up to 8e7fc18b5eacc37b6e6fcf486ec4eafbfef91738:

  ARM: warnings in arch/arm/include/asm/uaccess.h (2012-10-09 20:29:07 +0200)

----------------------------------------------------------------
These bug fixes all address problems found with automated build testing.
Some of them have been around for a long time, other bugs are
regressions since the merge window.

----------------------------------------------------------------
Arnd Bergmann (9):
      ARM: kprobes: make more tests conditional
      ARM: export set_irq_flags
      ARM: Fix another build warning in arch/arm/mm/alignment.c
      ARM: export default read_current_timer
      ARM: Xen: fix initial build problems
      ARM: pass -marm to gcc by default for both C and assembler
      ARM: be really quiet when building with 'make -s'
      ARM: binfmt_flat: unused variable 'persistent'
      ARM: warnings in arch/arm/include/asm/uaccess.h

 arch/arm/Kconfig                   |    1 +
 arch/arm/Makefile                  |   13 +++++++------
 arch/arm/boot/Makefile             |   10 +++++-----
 arch/arm/include/asm/flat.h        |    2 +-
 arch/arm/include/asm/uaccess.h     |    4 ++--
 arch/arm/kernel/irq.c              |    2 ++
 arch/arm/kernel/kprobes-test-arm.c |    4 ++++
 arch/arm/lib/delay.c               |    1 +
 arch/arm/mm/alignment.c            |    4 +++-
 arch/arm/tools/Makefile            |    2 +-
 drivers/xen/Kconfig                |    2 ++
 drivers/xen/sys-hypervisor.c       |    1 +
 12 files changed, 30 insertions(+), 16 deletions(-)

^ permalink raw reply

* [PATCH 0/7] crypto: omap-sham updates
From: Mark A. Greer @ 2012-10-19 21:53 UTC (permalink / raw)
  To: linux-arm-kernel

From: "Mark A. Greer" <mgreer@animalcreek.com>

This series updates the crypto omap-sham driver and supporting
infrastructure.

Notes:

a) Based on current k.o. c9623de (Merge branch 'v4l_for_linus'
   of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media)

b) These have only been tested on an omap2420 h4 and an am37x evm.  If you
   have different hardware available and a few minutes, please test them.
   A quick and easy test is to enable tcrypt as a module
   (CONFIG_CRYPTO_TEST=m), boot, then run 'modprobe tcrypt sec=2 mode=403'.
   'CONFIG_CRYPTO_SHA1' and 'CONFIG_CRYPTO_DEV_OMAP_SHAM' also have to be
   enabled.  A quick 'grep omap-sham /proc/interrupts' will tell you if
   the omap-sham driver was really used.

c) To test these patches, you will likely need...
   i) The patch included here:
	   http://marc.info/?l=kernel-janitors&m=134910841909057&w=2
   ii) This patch from linux-omap/master:
	   27615a9 (ARM: OMAP: Trivial driver changes to remove include
			   plat/cpu.h)
   iii) This patch from Paul Walmsley:
	   http://www.spinics.net/lists/linux-omap/msg79436.html

d) If you prefer, a version you can test is available at
   git at github.com:mgreeraz/linux-mag.git mag/wip/crypto-test

e) There is a reduction in DMA performance after switching to dmaengine
   (see http://www.spinics.net/lists/linux-omap/msg79855.html)

f) Many thanks to Jon Hunter for testing on his omap2420 h4.

Mark A. Greer (7):
  ARM: OMAP2xxx: hwmod: Convert SHAM crypto device data to hwmod
  ARM: OMAP2xxx: hwmod: Add DMA information for SHAM module
  ARM: OMAP3xxx: hwmod: Convert SHAM crypto device data to hwmod
  ARM: OMAP2+: Remove unnecessary message when no SHA IP is present
  crypto: omap-sham: Convert to use pm_runtime API
  crypto: omap-sham: Add code to use dmaengine API
  crypto: omap_sham: Remove usage of private DMA API

 arch/arm/mach-omap2/clock2420_data.c               |   1 +
 arch/arm/mach-omap2/clock2430_data.c               |   1 +
 arch/arm/mach-omap2/clock3xxx_data.c               |   1 +
 arch/arm/mach-omap2/devices.c                      |  81 +++------
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   1 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   1 +
 .../mach-omap2/omap_hwmod_2xxx_interconnect_data.c |  18 ++
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |  43 +++++
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |  60 +++++++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |   2 +
 drivers/crypto/omap-sham.c                         | 192 +++++++++++----------
 11 files changed, 250 insertions(+), 151 deletions(-)

-- 
1.7.12

^ permalink raw reply

* [PATCH 1/7] ARM: OMAP2xxx: hwmod: Convert SHAM crypto device data to hwmod
From: Mark A. Greer @ 2012-10-19 21:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350683640-15044-1-git-send-email-mgreer@animalcreek.com>

From: "Mark A. Greer" <mgreer@animalcreek.com>

Convert the device data for the OMAP2 SHAM crypto IP from
explicit platform_data to hwmod.  When bit 1 (OMAP24XX_ST_SHA_MASK)
of the CM_IDLEST4_CORE register is set, the SHA IP is present.

CC: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
---
 arch/arm/mach-omap2/clock2420_data.c               |  1 +
 arch/arm/mach-omap2/clock2430_data.c               |  1 +
 arch/arm/mach-omap2/devices.c                      | 38 +++++++++-------------
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |  1 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |  1 +
 .../mach-omap2/omap_hwmod_2xxx_interconnect_data.c | 18 ++++++++++
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c | 37 +++++++++++++++++++++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |  2 ++
 8 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index c3cde1a..a09603c 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1905,6 +1905,7 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
 	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
 	CLK(NULL,	"des_ick",	&des_ick,	CK_242X),
+	CLK(NULL,	"sha_ick",	&sha_ick,	CK_242X),
 	CLK("omap-sham",	"ick",	&sha_ick,	CK_242X),
 	CLK(NULL,	"sha_ick",	&sha_ick,	CK_242X),
 	CLK("omap_rng",	"ick",		&rng_ick,	CK_242X),
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index 22404fe..654e314 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1992,6 +1992,7 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_243X),
 	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_243X),
 	CLK(NULL,	"des_ick",	&des_ick,	CK_243X),
+	CLK(NULL,	"sha_ick",	&sha_ick,	CK_242X),
 	CLK("omap-sham",	"ick",	&sha_ick,	CK_243X),
 	CLK("omap_rng",	"ick",		&rng_ick,	CK_243X),
 	CLK(NULL,	"rng_ick",	&rng_ick,	CK_243X),
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index c8c2117..5b613fa 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -34,6 +34,8 @@
 #include "mux.h"
 #include "control.h"
 #include "devices.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
 
 #define L3_MODULES_MAX_LEN 12
 #define L3_MODULES 3
@@ -453,24 +455,6 @@ static void omap_init_rng(void)
 
 #if defined(CONFIG_CRYPTO_DEV_OMAP_SHAM) || defined(CONFIG_CRYPTO_DEV_OMAP_SHAM_MODULE)
 
-#ifdef CONFIG_ARCH_OMAP2
-static struct resource omap2_sham_resources[] = {
-	{
-		.start	= OMAP24XX_SEC_SHA1MD5_BASE,
-		.end	= OMAP24XX_SEC_SHA1MD5_BASE + 0x64,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= 51 + OMAP_INTC_START,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-static int omap2_sham_resources_sz = ARRAY_SIZE(omap2_sham_resources);
-#else
-#define omap2_sham_resources		NULL
-#define omap2_sham_resources_sz		0
-#endif
-
 #ifdef CONFIG_ARCH_OMAP3
 static struct resource omap3_sham_resources[] = {
 	{
@@ -500,17 +484,27 @@ static struct platform_device sham_device = {
 
 static void omap_init_sham(void)
 {
-	if (cpu_is_omap24xx()) {
-		sham_device.resource = omap2_sham_resources;
-		sham_device.num_resources = omap2_sham_resources_sz;
+	if (cpu_is_omap24xx() &&
+	    (omap2_cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_IDLEST4) &
+						 OMAP24XX_ST_SHA_MASK)) {
+		struct omap_hwmod *oh;
+		struct platform_device *pdev;
+
+		oh = omap_hwmod_lookup("sham");
+		if (!oh)
+			return;
+
+		pdev = omap_device_build("omap-sham", -1, oh, NULL, 0, NULL,
+					 0, 0);
+		WARN(IS_ERR(pdev), "Can't build omap_device for omap-sham\n");
 	} else if (cpu_is_omap34xx()) {
 		sham_device.resource = omap3_sham_resources;
 		sham_device.num_resources = omap3_sham_resources_sz;
+		platform_device_register(&sham_device);
 	} else {
 		pr_err("%s: platform not supported\n", __func__);
 		return;
 	}
-	platform_device_register(&sham_device);
 }
 #else
 static inline void omap_init_sham(void) { }
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index b5db600..b102a53 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -603,6 +603,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2420_l4_core__mcbsp2,
 	&omap2420_l4_core__msdi1,
 	&omap2xxx_l4_core__rng,
+	&omap2xxx_l4_core__sham,
 	&omap2420_l4_core__hdq1w,
 	&omap2420_l4_wkup__counter_32k,
 	&omap2420_l3__gpmc,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index c455e41..b1ce7b0 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -963,6 +963,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2430_l4_core__mcbsp5,
 	&omap2430_l4_core__hdq1w,
 	&omap2xxx_l4_core__rng,
+	&omap2xxx_l4_core__sham,
 	&omap2430_l4_wkup__counter_32k,
 	&omap2430_l3__gpmc,
 	NULL,
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
index 1a1287d..bb314c5 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -138,6 +138,15 @@ static struct omap_hwmod_addr_space omap2_rng_addr_space[] = {
 	{ }
 };
 
+struct omap_hwmod_addr_space omap2xxx_sham_addrs[] = {
+	{
+		.pa_start	= 0x480a4000,
+		.pa_end		= 0x480a4000 + 0x64 - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
 /*
  * Common interconnect data
  */
@@ -389,3 +398,12 @@ struct omap_hwmod_ocp_if omap2xxx_l4_core__rng = {
 	.addr		= omap2_rng_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
+
+/* l4 core -> sham interface */
+struct omap_hwmod_ocp_if omap2xxx_l4_core__sham = {
+	.master		= &omap2xxx_l4_core_hwmod,
+	.slave		= &omap2xxx_sham_hwmod,
+	.clk		= "sha_ick",
+	.addr		= omap2xxx_sham_addrs,
+	.user		= OCP_USER_MPU,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index bd9220e..a041670 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -851,3 +851,40 @@ struct omap_hwmod omap2xxx_rng_hwmod = {
 	.flags		= HWMOD_INIT_NO_RESET,
 	.class		= &omap2_rng_hwmod_class,
 };
+
+/* SHAM */
+
+static struct omap_hwmod_class_sysconfig omap2_sham_sysc = {
+	.rev_offs	= 0x5c,
+	.sysc_offs	= 0x60,
+	.syss_offs	= 0x64,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2xxx_sham_class = {
+	.name	= "sham",
+	.sysc	= &omap2_sham_sysc,
+};
+
+struct omap_hwmod_irq_info omap2_sham_mpu_irqs[] = {
+	{ .irq = 51 + OMAP_INTC_START, },
+	{ .irq = -1 }
+};
+
+struct omap_hwmod omap2xxx_sham_hwmod = {
+	.name		= "sham",
+	.mpu_irqs	= omap2_sham_mpu_irqs,
+	.main_clk	= "l4_ck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 4,
+			.module_bit = OMAP24XX_EN_SHA_SHIFT,
+			.idlest_reg_id = 4,
+			.idlest_idle_bit = OMAP24XX_ST_SHA_SHIFT,
+		},
+	},
+	.class		= &omap2xxx_sham_class,
+};
diff --git a/arch/arm/mach-omap2/omap_hwmod_common_data.h b/arch/arm/mach-omap2/omap_hwmod_common_data.h
index 2bc8f17..74a7b7a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_common_data.h
+++ b/arch/arm/mach-omap2/omap_hwmod_common_data.h
@@ -78,6 +78,7 @@ extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
 extern struct omap_hwmod omap2xxx_counter_32k_hwmod;
 extern struct omap_hwmod omap2xxx_gpmc_hwmod;
 extern struct omap_hwmod omap2xxx_rng_hwmod;
+extern struct omap_hwmod omap2xxx_sham_hwmod;
 
 /* Common interface data across OMAP2xxx */
 extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
@@ -105,6 +106,7 @@ extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_dispc;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc;
 extern struct omap_hwmod_ocp_if omap2xxx_l4_core__rng;
+extern struct omap_hwmod_ocp_if omap2xxx_l4_core__sham;
 
 /* Common IP block data */
 extern struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[];
-- 
1.7.12

^ permalink raw reply related

* [PATCH 2/7] ARM: OMAP2xxx: hwmod: Add DMA information for SHAM module
From: Mark A. Greer @ 2012-10-19 21:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1350683640-15044-1-git-send-email-mgreer@animalcreek.com>

From: "Mark A. Greer" <mgreer@animalcreek.com>

Add the DMA information for the OMAP2 SHA module.

CC: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Mark A. Greer <mgreer@animalcreek.com>
---
 arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c | 2 +-
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c      | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
index bb314c5..4b4fd5f 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
@@ -405,5 +405,5 @@ struct omap_hwmod_ocp_if omap2xxx_l4_core__sham = {
 	.slave		= &omap2xxx_sham_hwmod,
 	.clk		= "sha_ick",
 	.addr		= omap2xxx_sham_addrs,
-	.user		= OCP_USER_MPU,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index a041670..703b269 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -873,9 +873,15 @@ struct omap_hwmod_irq_info omap2_sham_mpu_irqs[] = {
 	{ .irq = -1 }
 };
 
+struct omap_hwmod_dma_info omap2_sham_sdma_chs[] = {
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_SHA1MD5_RX },
+	{ .dma_req = -1 }
+};
+
 struct omap_hwmod omap2xxx_sham_hwmod = {
 	.name		= "sham",
 	.mpu_irqs	= omap2_sham_mpu_irqs,
+	.sdma_reqs	= omap2_sham_sdma_chs,
 	.main_clk	= "l4_ck",
 	.prcm		= {
 		.omap2 = {
-- 
1.7.12

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox