Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3] ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
From: Paul Walmsley @ 2011-10-06 23:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111006222912.GA27281@n2100.arm.linux.org.uk>


The way that we detect which OMAP3 chips support I/O wakeup and
software I/O chain clock control is broken.

Currently, I/O wakeup is marked as present for all OMAP3 SoCs other
than the AM3505/3517.  The TI81xx family of SoCs are at present
considered to be OMAP3 SoCs, but don't support I/O wakeup.  To resolve
this, convert the existing blacklist approach to an explicit,
whitelist support, in which only SoCs which are known to support I/O
wakeup are listed.  (At present, this only includes OMAP34xx,
OMAP3503, OMAP3515, OMAP3525, OMAP3530, and OMAP36xx.)

Also, the current code incorrectly detects the presence of a
software-controllable I/O chain clock on several chips that don't
support it.  This results in writes to reserved bitfields, unnecessary
delays, and console messages on kernels running on those chips:

    http://www.spinics.net/lists/linux-omap/msg58735.html

Convert this test to a feature test with a chip-by-chip whitelist.

Thanks to Dave Hylands <dhylands@gmail.com> for reporting this problem
and doing some testing to help isolate the cause.  Thanks to Steve
Sakoman <sakoman@gmail.com> for catching a bug in the first version of
this patch.  Thanks to Russell King <linux@arm.linux.org.uk> for
comments.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@ti.com>
Cc: Dave Hylands <dhylands@gmail.com>
Cc: Steve Sakoman <sakoman@gmail.com>
Tested-by: Steve Sakoman <sakoman@gmail.com>
Cc: Russell King - ARM Linux <linux@arm.linux.org.uk>
---

This version incorporates some comments from RMK - an unnecessary 
set of parentheses are removed and a two-part error message string is 
joined.  Also, the printk(KERN_ERR has been converted into a pr_err(. 

 arch/arm/mach-omap2/id.c              |    5 +++-
 arch/arm/mach-omap2/pm34xx.c          |   43 +++++++++++++++++----------------
 arch/arm/plat-omap/include/plat/cpu.h |   17 +++++++++----
 3 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 37efb86..a1ccb66 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -201,8 +201,11 @@ static void __init omap3_check_features(void)
 	OMAP3_CHECK_FEATURE(status, ISP);
 	if (cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_192MHZ_CLK;
-	if (!cpu_is_omap3505() && !cpu_is_omap3517())
+	if (cpu_is_omap3430() || cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_IO_WAKEUP;
+	if (cpu_is_omap3630() || omap_rev() == OMAP3430_REV_ES3_1 ||
+	    omap_rev() == OMAP3430_REV_ES3_1_2)
+		omap_features |= OMAP3_HAS_IO_CHAIN_CTRL;
 
 	omap_features |= OMAP3_HAS_SDRC;
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7255d9b..979ed39 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -99,31 +99,27 @@ static void omap3_enable_io_chain(void)
 {
 	int timeout = 0;
 
-	if (omap_rev() >= OMAP3430_REV_ES3_1) {
-		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				     PM_WKEN);
-		/* Do a readback to assure write has been done */
-		omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
-
-		while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
-			 OMAP3430_ST_IO_CHAIN_MASK)) {
-			timeout++;
-			if (timeout > 1000) {
-				printk(KERN_ERR "Wake up daisy chain "
-				       "activation failed.\n");
-				return;
-			}
-			omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-					     WKUP_MOD, PM_WKEN);
+	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				   PM_WKEN);
+	/* Do a readback to assure write has been done */
+	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+
+	while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
+		 OMAP3430_ST_IO_CHAIN_MASK)) {
+		timeout++;
+		if (timeout > 1000) {
+			pr_err("Wake up daisy chain activation failed.\n");
+			return;
 		}
+		omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
+					   WKUP_MOD, PM_WKEN);
 	}
 }
 
 static void omap3_disable_io_chain(void)
 {
-	if (omap_rev() >= OMAP3430_REV_ES3_1)
-		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				       PM_WKEN);
+	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				     PM_WKEN);
 }
 
 static void omap3_core_save_context(void)
@@ -376,7 +372,8 @@ void omap_sram_idle(void)
 	    (per_next_state < PWRDM_POWER_ON ||
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
-		omap3_enable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_enable_io_chain();
 	}
 
 	/* Block console output in case it is on one of the OMAP UARTs */
@@ -475,7 +472,8 @@ console_still_active:
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
 					     PM_WKEN);
-		omap3_disable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_disable_io_chain();
 	}
 
 	pwrdm_post_transition();
@@ -870,6 +868,9 @@ static int __init omap3_pm_init(void)
 	if (!cpu_is_omap34xx())
 		return -ENODEV;
 
+	if (!omap3_has_io_chain_ctrl())
+		pr_warning("PM: no software I/O chain control; some wakeups may be lost\n");
+
 	pm_errata_configure();
 
 	/* XXX prcm_setup_regs needs to be before enabling hw
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 67b3d75..3a280aa 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -477,6 +477,13 @@ void omap2_check_revision(void);
 
 /*
  * Runtime detection of OMAP3 features
+ *
+ * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
+ *    family have OS-level control over the I/O chain clock.  This is
+ *    to avoid a window during which wakeups could potentially be lost
+ *    during powerdomain transitions.  If this bit is set, it
+ *    indicates that the chip does support OS-level control of this
+ *    feature.
  */
 extern u32 omap_features;
 
@@ -488,9 +495,10 @@ extern u32 omap_features;
 #define OMAP3_HAS_192MHZ_CLK		BIT(5)
 #define OMAP3_HAS_IO_WAKEUP		BIT(6)
 #define OMAP3_HAS_SDRC			BIT(7)
-#define OMAP4_HAS_MPU_1GHZ		BIT(8)
-#define OMAP4_HAS_MPU_1_2GHZ		BIT(9)
-#define OMAP4_HAS_MPU_1_5GHZ		BIT(10)
+#define OMAP3_HAS_IO_CHAIN_CTRL		BIT(8)
+#define OMAP4_HAS_MPU_1GHZ		BIT(9)
+#define OMAP4_HAS_MPU_1_2GHZ		BIT(10)
+#define OMAP4_HAS_MPU_1_5GHZ		BIT(11)
 
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
@@ -507,12 +515,11 @@ OMAP3_HAS_FEATURE(isp, ISP)
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
+OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)
 
 /*
  * Runtime detection of OMAP4 features
  */
-extern u32 omap_features;
-
 #define OMAP4_HAS_FEATURE(feat, flag)			\
 static inline unsigned int omap4_has_ ##feat(void)	\
 {							\
-- 
1.7.6.3

^ permalink raw reply related

* [PATCH/RFC] mm: add vm_area_add_early()
From: Andrew Morton @ 2011-10-06 23:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1109141427340.20358@xanadu.home>

On Wed, 14 Sep 2011 14:35:21 -0400 (EDT)
Nicolas Pitre <nicolas.pitre@linaro.org> wrote:

> 
> The existing vm_area_register_early() allows for early vmalloc space
> allocation.  However upcoming cleanups in the ARM architecture require
> that some fixed locations in the vmalloc area be reserved also very early.
> 
> The name "vm_area_register_early" would have been a good name for the
> reservation part without the allocation.  Since it is already in use with
> different semantics, let's create vm_area_add_early() instead.
> 
> Both vm_area_register_early() and vm_area_add_early() can be used together
> meaning that the former is now implemented using the later where it is
> ensured that no conflicting areas are added, but no attempt is made to
> make the allocation scheme in vm_area_register_early() more sophisticated.
> After all, you must know what you're doing when using those functions.
> 
> Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
> ---
> 
> Comments / ACKs appreciated.

Deafening silence?

> diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
> index 9332e52ea8..e7d2cba995 100644
> --- a/include/linux/vmalloc.h
> +++ b/include/linux/vmalloc.h
> @@ -130,6 +130,7 @@ extern long vwrite(char *buf, char *addr, unsigned long count);
>   */
>  extern rwlock_t vmlist_lock;
>  extern struct vm_struct *vmlist;
> +extern __init void vm_area_add_early(struct vm_struct *vm);
>  extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
>  
>  #ifdef CONFIG_SMP
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 7ef0903058..bf20a0ff95 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -1118,6 +1118,31 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
>  EXPORT_SYMBOL(vm_map_ram);
>  
>  /**
> + * vm_area_add_early - add vmap area early during boot
> + * @vm: vm_struct to add
> + *
> + * This function is used to add fixed kernel vm area to vmlist before
> + * vmalloc_init() is called.  @vm->addr, @vm->size, and @vm->flags
> + * should contain proper values and the other fields should be zero.
> + *
> + * DO NOT USE THIS FUNCTION UNLESS YOU KNOW WHAT YOU'RE DOING.
> + */
> +void __init vm_area_add_early(struct vm_struct *vm)
> +{
> +	struct vm_struct *tmp, **p;
> +
> +	for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
> +		if (tmp->addr >= vm->addr) {
> +			BUG_ON(tmp->addr < vm->addr + vm->size);
> +			break;
> +		} else
> +			BUG_ON(tmp->addr + tmp->size > vm->addr);
> +	}
> +	vm->next = *p;
> +	*p = vm;
> +}
> +
> +/**
>   * vm_area_register_early - register vmap area early during boot
>   * @vm: vm_struct to register
>   * @align: requested alignment
> @@ -1139,8 +1164,7 @@ void __init vm_area_register_early(struct vm_struct *vm, size_t align)
>  
>  	vm->addr = (void *)addr;
>  
> -	vm->next = vmlist;
> -	vmlist = vm;
> +	vm_area_add_early(vm);
>  }
>  
>  void __init vmalloc_init(void)

I tossed this into my tree for a bit of testing, assuming it's
up-to-date and still desired?

Feel free to add it to some ARM tree.  I'll drop my copy when that
turns up in linux-next.

Yes, the naming scheme in there is gruseome.

^ permalink raw reply

* [PATCH-V3 4/4] arm:omap:am33xx: Add low level debugging support
From: Tony Lindgren @ 2011-10-06 23:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316529142-27564-5-git-send-email-hvaibhav@ti.com>

* hvaibhav at ti.com <hvaibhav@ti.com> [110920 06:59]:
> From: Afzal Mohammed <afzal@ti.com>
> 
> Add support for low level debugging on AM335X EVM (AM33XX family).
> Currently only support for UART1 console, which is used on AM335X EVM
> is added.

Let's wait a bit on this one as there are other DEBUG_LL patches
pending from Nico.

Regards,

Tony

^ permalink raw reply

* [PATCH-V3 3/4] arm:omap:am33xx: Create board support and enable build for AM335XEVM
From: Tony Lindgren @ 2011-10-06 23:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316529142-27564-4-git-send-email-hvaibhav@ti.com>

* hvaibhav at ti.com <hvaibhav@ti.com> [110920 06:59]:
> From: Afzal Mohammed <afzal@ti.com>
> 
> This patch adds minimal support and build configuration for
> AM335X EVM.
...

> --- /dev/null
> +++ b/arch/arm/mach-omap2/board-am335xevm.c
> +
> +MACHINE_START(AM335XEVM, "am335xevm")
> +	/* Maintainer: Texas Instruments */
> +	.boot_params	= 0x80000100,
> +	.map_io		= am335x_evm_map_io,
> +	.init_early	= am335x_init_early,
> +	.init_irq	= ti816x_init_irq,
> +	.timer		= &omap3_timer,
> +	.init_machine	= am335x_evm_init,
> +MACHINE_END

Please just add the support into board-am3517evm.c, the board-*.c
files will be going away with device tree.

Regards,

Tony

^ permalink raw reply

* [PATCH v2] ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
From: Paul Walmsley @ 2011-10-06 23:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111006222912.GA27281@n2100.arm.linux.org.uk>

On Thu, 6 Oct 2011, Russell King - ARM Linux wrote:

> On Thu, Oct 06, 2011 at 01:47:22PM -0600, Paul Walmsley wrote:
> > +	if ((omap_rev() == OMAP3430_REV_ES3_1 ||
> > +	     omap_rev() == OMAP3430_REV_ES3_1_2) ||
> > +	    cpu_is_omap3630())
> > +		omap_features |= OMAP3_HAS_IO_CHAIN_CTRL;
> 
> 	(a || b) || c === a || b || c
> 
> IOW, no need for the additional parens.

Thanks; patch updated.

> > diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> > index 7255d9b..a6156bd 100644
> > --- a/arch/arm/mach-omap2/pm34xx.c
> > +++ b/arch/arm/mach-omap2/pm34xx.c
> > @@ -99,31 +99,28 @@ static void omap3_enable_io_chain(void)
> >  {
> >  	int timeout = 0;
> >  
> > -	if (omap_rev() >= OMAP3430_REV_ES3_1) {
> > -		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
> > -				     PM_WKEN);
> > -		/* Do a readback to assure write has been done */
> > -		omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
> > -
> > -		while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
> > -			 OMAP3430_ST_IO_CHAIN_MASK)) {
> > -			timeout++;
> > -			if (timeout > 1000) {
> > -				printk(KERN_ERR "Wake up daisy chain "
> > -				       "activation failed.\n");
> > -				return;
> > -			}
> > -			omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
> > -					     WKUP_MOD, PM_WKEN);
> > +	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
> > +				   PM_WKEN);
> > +	/* Do a readback to assure write has been done */
> > +	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
> > +
> > +	while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
> > +		 OMAP3430_ST_IO_CHAIN_MASK)) {
> > +		timeout++;
> > +		if (timeout > 1000) {
> > +			printk(KERN_ERR "Wake up daisy chain "
> > +			       "activation failed.\n");
> > +			return;
> >  		}
> > +		omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
> > +					   WKUP_MOD, PM_WKEN);
> >  	}
> 
> This should've been caught before.  Two things:
> 
> 1. Do you know how long it takes this to time out?

No, I don't; and I doubt the original author did either.

Really there should be at least a udelay(1) in that code; since as it 
stands right now, there's at least a partial CPU/interconnect/high 
frequency oscillator speed dependency in that loop.

But this patch was intended to be a minimal fix, avoiding code changes 
that are unrelated to the I/O chain feature detection change.  Those lines 
just showed up due to the indentation level change...
 
> 2. Don't wrap error printks, it prevents them being grepped for.

Thanks; patch updated.


- Paul

^ permalink raw reply

* [PATCH-V3 1/4] arm:omap:am33xx: Update common omap platform files
From: Tony Lindgren @ 2011-10-06 23:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316529142-27564-2-git-send-email-hvaibhav@ti.com>

* hvaibhav at ti.com <hvaibhav@ti.com> [110920 06:59]:
> From: Afzal Mohammed <afzal@ti.com>
> 
> This patch updates the common platform files with AM335X device
> support (AM33XX family).
> 
> The approach taken in this patch is,
> AM33XX device will be considered as OMAP3 variant, and a separate
> SoC class created for AM33XX family of devices with a subclass type
> for AM335X device, which is newly added device in the family.
> 
> This means, cpu_is_omap34xx(), cpu_is_am33xx() and cpu_is_am335x()
> checks will return success on AM335X device.
> A kernel config option CONFIG_SOC_OMAPAM33XX is added under OMAP3
> to include support for AM33XX build.
> 
> Also, cpu_mask and RATE_IN_XXX flags have crossed 8 bit hence
> struct clksel_rate.flags, struct prcm_config.flags and cpu_mask
> are changed to u16 from u8.
> 
> Signed-off-by: Afzal Mohammed <afzal@ti.com>
> Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
> Cc: Hemant Pedanekar <hemantp@ti.com>

I'll add this one into soc branch.

Regards,

Tony

^ permalink raw reply

* [PATCH-V3 2/4] arm:omap:am33xx: Update common OMAP machine specific sources
From: Tony Lindgren @ 2011-10-06 23:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87ehyyj6ts.fsf@ti.com>

* Kevin Hilman <khilman@ti.com> [110930 09:35]:
> "Premi, Sanjeev" <premi@ti.com> writes:
> 
> Actually, looking at this closer, I think the infrastructure is already
> there to handle this cleanly.
> 
> Basically, dpll5 should not even be registered for SoCs where it doesn't
> exist.  Then, any attempts to use DPLL5 would know it doesn't exist
> because the call to clk_get() in omap3_clk_lock_dpll5() would fail.

Yes please use the SoC specific lists, see what we have now queued
up in sram-map-io branch. So using SoC specific map_io + init_early +
set_globals should do the trick.
 
> I think the clock3xxx_data.c needs a bit more cleanup so that only
> clocks that exist for a given SoC are registered.
> 
> Paul already did a similar cleanup for the powerdomain data files by
> creating separate lists for common ones and unique ones.  Looks like we
> need the same for the clock data.

Right.

Regards,

Tony

^ permalink raw reply

* [PATCH] ARM: OMAP2: Fix H4 matrix keyboard warning
From: Tony Lindgren @ 2011-10-06 22:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111006224435.GV6324@atomide.com>

Convert to use matrix keyboard to remove the warning
"Please update the board to use matrix-keypad driver".

Based on similar setup in palmtc.c. Note that this
patch is compile tested only because of lack of working
hardware.

Signed-off-by: Tony Lindgren <tony@atomide.com>

--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -25,6 +25,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -35,7 +36,6 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/keypad.h>
 #include <plat/menelaus.h>
 #include <plat/dma.h>
 #include <plat/gpmc.h>
@@ -48,10 +48,8 @@
 
 #define H4_ETHR_GPIO_IRQ		92
 
-static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 };
-static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 };
-
-static const unsigned int h4_keymap[] = {
+#if defined(CONFIG_KEYBOARD_MATRIX) || defined(CONFIG_KEYBOARD_MATRIX_MODULE)
+static const uint32_t board_matrix_keys[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(1, 0, KEY_RIGHT),
 	KEY(2, 0, KEY_A),
@@ -84,6 +82,71 @@ static const unsigned int h4_keymap[] = {
 	KEY(4, 5, KEY_ENTER),
 };
 
+static const struct matrix_keymap_data board_keymap_data = {
+	.keymap			= board_matrix_keys,
+	.keymap_size		= ARRAY_SIZE(board_matrix_keys),
+};
+
+static unsigned int board_keypad_row_gpios[] = {
+	88, 89, 124, 11, 6, 96
+};
+
+static unsigned int board_keypad_col_gpios[] = {
+	90, 91, 100, 36, 12, 97, 98
+};
+
+static struct matrix_keypad_platform_data board_keypad_platform_data = {
+	.keymap_data	= &board_keymap_data,
+	.row_gpios	= board_keypad_row_gpios,
+	.num_row_gpios	= ARRAY_SIZE(board_keypad_row_gpios),
+	.col_gpios	= board_keypad_col_gpios,
+	.num_col_gpios	= ARRAY_SIZE(board_keypad_col_gpios),
+	.active_low	= 1,
+
+	.debounce_ms		= 20,
+	.col_scan_delay_us	= 5,
+};
+
+static struct platform_device board_keyboard = {
+	.name	= "matrix-keypad",
+	.id	= -1,
+	.dev	= {
+		.platform_data = &board_keypad_platform_data,
+	},
+};
+static void __init board_mkp_init(void)
+{
+	omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
+	omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
+	if (omap_has_menelaus()) {
+		omap_mux_init_signal("sdrc_a14.gpio0",
+			OMAP_PULL_ENA | OMAP_PULL_UP);
+		omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
+		omap_mux_init_signal("gpio_98", 0);
+		board_keypad_row_gpios[5] = 0;
+		board_keypad_col_gpios[2] = 15;
+		board_keypad_col_gpios[6] = 18;
+	} else {
+		omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
+		omap_mux_init_signal("gpio_100", 0);
+		omap_mux_init_signal("gpio_98", 0);
+	}
+	omap_mux_init_signal("gpio_90", 0);
+	omap_mux_init_signal("gpio_91", 0);
+	omap_mux_init_signal("gpio_36", 0);
+	omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
+	omap_mux_init_signal("gpio_97", 0);
+
+	platform_device_register(&board_keyboard);
+}
+#else
+static inline void board_mkp_init(void)
+{
+}
+#endif
+
 static struct mtd_partition h4_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -135,28 +198,6 @@ static struct platform_device h4_flash_device = {
 	.resource	= &h4_flash_resource,
 };
 
-static const struct matrix_keymap_data h4_keymap_data = {
-	.keymap		= h4_keymap,
-	.keymap_size	= ARRAY_SIZE(h4_keymap),
-};
-
-static struct omap_kp_platform_data h4_kp_data = {
-	.rows		= 6,
-	.cols		= 7,
-	.keymap_data	= &h4_keymap_data,
-	.rep		= true,
-	.row_gpios 	= row_gpios,
-	.col_gpios 	= col_gpios,
-};
-
-static struct platform_device h4_kp_device = {
-	.name		= "omap-keypad",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &h4_kp_data,
-	},
-};
-
 static struct platform_device h4_lcd_device = {
 	.name		= "lcd_h4",
 	.id		= -1,
@@ -164,7 +205,6 @@ static struct platform_device h4_lcd_device = {
 
 static struct platform_device *h4_devices[] __initdata = {
 	&h4_flash_device,
-	&h4_kp_device,
 	&h4_lcd_device,
 };
 
@@ -329,31 +369,7 @@ static void __init omap_h4_init(void)
 	 * if not needed.
 	 */
 
-#if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
-	omap_mux_init_gpio(88, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_gpio(89, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_gpio(124, OMAP_PULL_ENA | OMAP_PULL_UP);
-	omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
-	if (omap_has_menelaus()) {
-		omap_mux_init_signal("sdrc_a14.gpio0",
-			OMAP_PULL_ENA | OMAP_PULL_UP);
-		omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
-		omap_mux_init_signal("gpio_98", 0);
-		row_gpios[5] = 0;
-		col_gpios[2] = 15;
-		col_gpios[6] = 18;
-	} else {
-		omap_mux_init_signal("gpio_96", OMAP_PULL_ENA | OMAP_PULL_UP);
-		omap_mux_init_signal("gpio_100", 0);
-		omap_mux_init_signal("gpio_98", 0);
-	}
-	omap_mux_init_signal("gpio_90", 0);
-	omap_mux_init_signal("gpio_91", 0);
-	omap_mux_init_signal("gpio_36", 0);
-	omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
-	omap_mux_init_signal("gpio_97", 0);
-#endif
-
+	board_mkp_init();
 	i2c_register_board_info(1, h4_i2c_board_info,
 			ARRAY_SIZE(h4_i2c_board_info));
 

^ permalink raw reply

* [PATCH] ARM: OMAP3: hwmod: fix variant registration and remove SmartReflex from common list
From: Russell King - ARM Linux @ 2011-10-06 22:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1110061433540.4611@utopia.booyaka.com>

On Thu, Oct 06, 2011 at 02:39:28PM -0600, Paul Walmsley wrote:
> @@ -3240,7 +3240,7 @@ int __init omap3xxx_hwmod_init(void)
>  
>  	/* Register hwmods common to all OMAP3 */
>  	r = omap_hwmod_register(omap3xxx_hwmods);
> -	if (!r)
> +	if (IS_ERR_VALUE(r))
>  		return r;
>  
>  	rev = omap_rev();
> @@ -3265,7 +3265,7 @@ int __init omap3xxx_hwmod_init(void)
>  	};
>  
>  	r = omap_hwmod_register(h);
> -	if (!r)
> +	if (IS_ERR_VALUE(r))
>  		return r;

What _really_ is the return value meaning of omap_hwmod_register() ?

If it's zero for success, negative for error codes, then don't be
clever and try to use IS_ERR_VALUE() for that - just use a standard
< 0 test instead.

You only need to use IS_ERR_VALUE() for stuff that may return negative
errno values _and_ which may return valid addresses which may be
misinterpreted as negative numbers.

^ permalink raw reply

* [PATCH v2] ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
From: Russell King - ARM Linux @ 2011-10-06 22:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1110061346570.4611@utopia.booyaka.com>

On Thu, Oct 06, 2011 at 01:47:22PM -0600, Paul Walmsley wrote:
> +	if ((omap_rev() == OMAP3430_REV_ES3_1 ||
> +	     omap_rev() == OMAP3430_REV_ES3_1_2) ||
> +	    cpu_is_omap3630())
> +		omap_features |= OMAP3_HAS_IO_CHAIN_CTRL;

	(a || b) || c === a || b || c

IOW, no need for the additional parens.

> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index 7255d9b..a6156bd 100644
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -99,31 +99,28 @@ static void omap3_enable_io_chain(void)
>  {
>  	int timeout = 0;
>  
> -	if (omap_rev() >= OMAP3430_REV_ES3_1) {
> -		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
> -				     PM_WKEN);
> -		/* Do a readback to assure write has been done */
> -		omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
> -
> -		while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
> -			 OMAP3430_ST_IO_CHAIN_MASK)) {
> -			timeout++;
> -			if (timeout > 1000) {
> -				printk(KERN_ERR "Wake up daisy chain "
> -				       "activation failed.\n");
> -				return;
> -			}
> -			omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
> -					     WKUP_MOD, PM_WKEN);
> +	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
> +				   PM_WKEN);
> +	/* Do a readback to assure write has been done */
> +	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
> +
> +	while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
> +		 OMAP3430_ST_IO_CHAIN_MASK)) {
> +		timeout++;
> +		if (timeout > 1000) {
> +			printk(KERN_ERR "Wake up daisy chain "
> +			       "activation failed.\n");
> +			return;
>  		}
> +		omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
> +					   WKUP_MOD, PM_WKEN);
>  	}

This should've been caught before.  Two things:

1. Do you know how long it takes this to time out?
2. Don't wrap error printks, it prevents them being grepped for.

^ permalink raw reply

* [PATCH 1/2] arm: samsung: move timer irq numbers to end of linux irq space
From: Russell King - ARM Linux @ 2011-10-06 22:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317935503-11756-2-git-send-email-thomas.abraham@linaro.org>

On Fri, Oct 07, 2011 at 02:41:42AM +0530, Thomas Abraham wrote:
> All of Samsung's s5p platforms have timer irqs statically mapped from linux
> irq numbers 11 to 15. These timer irqs are moved to end of the statically
> mapped linux irq space and the hardware irqs, which were statically mapped
> starting from 32 is moved to start from 0. The NR_IRQS macro is consolidated
> for all the s5p platforms in this process.

Am I reading this patch correctly - in that on platforms with the GIC,
you add 32 to the GIC IRQ number _just_ to avoid the possibility that
IRQs 11-15 are seen as valid?

Or to put it another way, you're trying to ensure that if these timer
IRQs are requested, they will fail?

^ permalink raw reply

* [PATCH] arm: exynos4: build is failing due to missing SZ_4K definition
From: Angus Ainslie @ 2011-10-06 22:03 UTC (permalink / raw)
  To: linux-arm-kernel

linux-next build is failing using the exynos4_defconfig. <asm/sizes.h> needs to be 
for the SZ_4K definition

Signed-off-by: Angus Ainslie <angus.ainslie@linaro.org>
---
 arch/arm/mach-exynos4/include/mach/map.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 918a979..02d68f1 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -13,6 +13,7 @@
 #ifndef __ASM_ARCH_MAP_H
 #define __ASM_ARCH_MAP_H __FILE__
 
+#include <asm/sizes.h>
 #include <plat/map-base.h>
 
 /*
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH] ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
From: Paul Walmsley @ 2011-10-06 21:25 UTC (permalink / raw)
  To: linux-arm-kernel

The way that we detect which OMAP3 chips support I/O wakeup and
software I/O chain clock control is broken.

Currently, I/O wakeup is marked as present for all OMAP3 SoCs other
than the AM3505/3517.  The TI81xx family of SoCs are at present
considered to be OMAP3 SoCs, but don't support I/O wakeup.  To resolve
this, convert the existing blacklist approach to an explicit,
whitelist support, in which only SoCs which are known to support I/O
wakeup are listed.  (At present, this only includes OMAP34xx,
OMAP3503, OMAP3515, OMAP3525, OMAP3530, and OMAP36xx.)

Also, the current code incorrectly detects the presence of a
software-controllable I/O chain clock on several chips that don't
support it.  This results in writes to reserved bitfields, unnecessary
delays, and console messages on kernels running on those chips:

    http://www.spinics.net/lists/linux-omap/msg58735.html

Convert this test to a feature test with a chip-by-chip whitelist.

Thanks to Dave Hylands <dhylands@gmail.com> for reporting this problem
and doing some testing to help isolate the cause.  Thanks to Steve
Sakoman <sakoman@gmail.com> for catching a bug in the first version of
this patch.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dave Hylands <dhylands@gmail.com>
Cc: Steve Sakoman <sakoman@gmail.com>
Tested-by: Steve Sakoman <sakoman@gmail.com>
[khilman at ti.com: unwrapped printk, removed extra braces around conditional
                 as suggessted by Russell King.]
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
 arch/arm/mach-omap2/id.c              |    6 +++-
 arch/arm/mach-omap2/pm34xx.c          |   44 +++++++++++++++++---------------
 arch/arm/plat-omap/include/plat/cpu.h |   17 +++++++++---
 3 files changed, 40 insertions(+), 27 deletions(-)

diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 37efb86..1c93462 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -201,8 +201,12 @@ static void __init omap3_check_features(void)
 	OMAP3_CHECK_FEATURE(status, ISP);
 	if (cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_192MHZ_CLK;
-	if (!cpu_is_omap3505() && !cpu_is_omap3517())
+	if (cpu_is_omap3430() || cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_IO_WAKEUP;
+	if (omap_rev() == OMAP3430_REV_ES3_1 ||
+	    omap_rev() == OMAP3430_REV_ES3_1_2 ||
+	    cpu_is_omap3630())
+		omap_features |= OMAP3_HAS_IO_CHAIN_CTRL;
 
 	omap_features |= OMAP3_HAS_SDRC;
 
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7255d9b..43536b2 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -99,31 +99,28 @@ static void omap3_enable_io_chain(void)
 {
 	int timeout = 0;
 
-	if (omap_rev() >= OMAP3430_REV_ES3_1) {
-		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				     PM_WKEN);
-		/* Do a readback to assure write has been done */
-		omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
-
-		while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
-			 OMAP3430_ST_IO_CHAIN_MASK)) {
-			timeout++;
-			if (timeout > 1000) {
-				printk(KERN_ERR "Wake up daisy chain "
-				       "activation failed.\n");
-				return;
-			}
-			omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-					     WKUP_MOD, PM_WKEN);
+	omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				   PM_WKEN);
+	/* Do a readback to assure write has been done */
+	omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
+
+	while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
+		 OMAP3430_ST_IO_CHAIN_MASK)) {
+		timeout++;
+		if (timeout > 1000) {
+			printk(KERN_ERR
+			       "Wake up daisy chain activation failed.\n");
+			return;
 		}
+		omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
+					   WKUP_MOD, PM_WKEN);
 	}
 }
 
 static void omap3_disable_io_chain(void)
 {
-	if (omap_rev() >= OMAP3430_REV_ES3_1)
-		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-				       PM_WKEN);
+	omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+				     PM_WKEN);
 }
 
 static void omap3_core_save_context(void)
@@ -376,7 +373,8 @@ void omap_sram_idle(void)
 	    (per_next_state < PWRDM_POWER_ON ||
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
-		omap3_enable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_enable_io_chain();
 	}
 
 	/* Block console output in case it is on one of the OMAP UARTs */
@@ -475,7 +473,8 @@ console_still_active:
 	     core_next_state < PWRDM_POWER_ON)) {
 		omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
 					     PM_WKEN);
-		omap3_disable_io_chain();
+		if (omap3_has_io_chain_ctrl())
+			omap3_disable_io_chain();
 	}
 
 	pwrdm_post_transition();
@@ -870,6 +869,9 @@ static int __init omap3_pm_init(void)
 	if (!cpu_is_omap34xx())
 		return -ENODEV;
 
+	if (!omap3_has_io_chain_ctrl())
+		pr_warning("PM: no software I/O chain control; some wakeups may be lost\n");
+
 	pm_errata_configure();
 
 	/* XXX prcm_setup_regs needs to be before enabling hw
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 67b3d75..3a280aa 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -477,6 +477,13 @@ void omap2_check_revision(void);
 
 /*
  * Runtime detection of OMAP3 features
+ *
+ * OMAP3_HAS_IO_CHAIN_CTRL: Some later members of the OMAP3 chip
+ *    family have OS-level control over the I/O chain clock.  This is
+ *    to avoid a window during which wakeups could potentially be lost
+ *    during powerdomain transitions.  If this bit is set, it
+ *    indicates that the chip does support OS-level control of this
+ *    feature.
  */
 extern u32 omap_features;
 
@@ -488,9 +495,10 @@ extern u32 omap_features;
 #define OMAP3_HAS_192MHZ_CLK		BIT(5)
 #define OMAP3_HAS_IO_WAKEUP		BIT(6)
 #define OMAP3_HAS_SDRC			BIT(7)
-#define OMAP4_HAS_MPU_1GHZ		BIT(8)
-#define OMAP4_HAS_MPU_1_2GHZ		BIT(9)
-#define OMAP4_HAS_MPU_1_5GHZ		BIT(10)
+#define OMAP3_HAS_IO_CHAIN_CTRL		BIT(8)
+#define OMAP4_HAS_MPU_1GHZ		BIT(9)
+#define OMAP4_HAS_MPU_1_2GHZ		BIT(10)
+#define OMAP4_HAS_MPU_1_5GHZ		BIT(11)
 
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
@@ -507,12 +515,11 @@ OMAP3_HAS_FEATURE(isp, ISP)
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
+OMAP3_HAS_FEATURE(io_chain_ctrl, IO_CHAIN_CTRL)
 
 /*
  * Runtime detection of OMAP4 features
  */
-extern u32 omap_features;
-
 #define OMAP4_HAS_FEATURE(feat, flag)			\
 static inline unsigned int omap4_has_ ##feat(void)	\
 {							\
-- 
1.7.6

^ permalink raw reply related

* [PATCH v3] ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
From: Paul Walmsley @ 2011-10-06 21:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAGDS+nmb20E4y2HqBtDN05PK1C1YXjmRvnVAbQkhGpp17s4Zcg@mail.gmail.com>



^ permalink raw reply

* [PATCH v2] ARM: OMAP3: PM: fix I/O wakeup and I/O chain clock control detection
From: Steve Sakoman @ 2011-10-06 21:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1110061346570.4611@utopia.booyaka.com>

On Thu, Oct 6, 2011 at 12:47 PM, Paul Walmsley <paul@pwsan.com> wrote:
>
> The way that we detect which OMAP3 chips support I/O wakeup and
> software I/O chain clock control is broken.
>
> Currently, I/O wakeup is marked as present for all OMAP3 SoCs other
> than the AM3505/3517. ?The TI81xx family of SoCs are at present
> considered to be OMAP3 SoCs, but don't support I/O wakeup. ?To resolve
> this, convert the existing blacklist approach to an explicit,
> whitelist support, in which only SoCs which are known to support I/O
> wakeup are listed. ?(At present, this only includes OMAP34xx,
> OMAP3503, OMAP3515, OMAP3525, OMAP3530, and OMAP36xx.)
>
> Also, the current code incorrectly detects the presence of a
> software-controllable I/O chain clock on several chips that don't
> support it. ?This results in writes to reserved bitfields, unnecessary
> delays, and console messages on kernels running on those chips:
>
> ? ?http://www.spinics.net/lists/linux-omap/msg58735.html
>
> Convert this test to a feature test with a chip-by-chip whitelist.
>
> Thanks to Dave Hylands <dhylands@gmail.com> for reporting this problem
> and doing some testing to help isolate the cause. ?Thanks to Steve
> Sakoman <sakoman@gmail.com> for catching a bug in the first version of
> this patch.
>
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@ti.com>
> Cc: Dave Hylands <dhylands@gmail.com>
> Cc: Steve Sakoman <sakoman@gmail.com>

I just tested a Linux 3.0 version of the patch on both ES2.1
and ES3.1 and it works just fine.

So here is my:

Tested-by: Steve Sakoman <steve@sakoman.com>

^ permalink raw reply

* [PATCH 2/2] arm: exynos4: add support for dt irq specifier to linux virq conversion
From: Thomas Abraham @ 2011-10-06 21:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317935503-11756-1-git-send-email-thomas.abraham@linaro.org>

Add support for conversion of device tree interrupt specifier to linux
virq domain for GIC and Interrupt combiner controllers.

Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos4/cpu.c          |   20 ++++++++++++++-
 arch/arm/mach-exynos4/irq-combiner.c |   44 ++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 1c5e803..9898f9c 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -10,6 +10,8 @@
 
 #include <linux/sched.h>
 #include <linux/sysdev.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -38,6 +40,8 @@ unsigned int gic_bank_offset __read_mostly;
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
 			 unsigned int irq_start);
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
+extern void combiner_init_dt(struct device_node *node,
+				struct device_node *parent);
 
 /* Initial IO mappings */
 static struct map_desc exynos4_iodesc[] __initdata = {
@@ -218,13 +222,27 @@ static void exynos4_gic_irq_fix_base(struct irq_data *d)
 			    (gic_bank_offset * smp_processor_id());
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id exynos4_dt_irq_match[] = {
+	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+	{ .compatible = "samsung,exynos4-combiner", .data = combiner_init_dt, },
+	{},
+};
+#endif
+
 void __init exynos4_init_irq(void)
 {
 	int irq;
 
 	gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
 
-	gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+#ifdef CONFIG_OF
+	if (of_have_populated_dt())
+		of_irq_init(exynos4_dt_irq_match);
+	else
+#endif
+		gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+
 	gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
 	gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
 	gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
diff --git a/arch/arm/mach-exynos4/irq-combiner.c b/arch/arm/mach-exynos4/irq-combiner.c
index 5a2758a..d2d143a 100644
--- a/arch/arm/mach-exynos4/irq-combiner.c
+++ b/arch/arm/mach-exynos4/irq-combiner.c
@@ -13,6 +13,10 @@
 */
 
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/slab.h>
 
 #include <asm/mach/irq.h>
 
@@ -122,3 +126,43 @@ void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
 }
+
+#ifdef CONFIG_OF
+/* Translate dt irq specifier to linux virq for interrupt combiner controller */
+static int exynos4_irq_domain_combiner_dt_translate(struct irq_domain *d,
+			struct device_node *controller,
+			const u32 *intspec, unsigned int intsize,
+			unsigned long *out_hwirq, unsigned int *out_type)
+{
+	if (d->of_node != controller)
+		return -EINVAL;
+	if (intsize < 2)
+		return -EINVAL;
+
+	*out_hwirq = COMBINER_IRQ(intspec[0], intspec[1]);
+	*out_type = IRQ_TYPE_NONE;
+	return 0;
+}
+
+static struct irq_domain_ops exynos4_irq_domain_combiner_ops = {
+	.dt_translate = exynos4_irq_domain_combiner_dt_translate,
+};
+
+void __init combiner_init_dt(struct device_node *node,
+					struct device_node *parent)
+{
+	struct irq_domain *domain;
+
+	if (WARN(!node, "combiner_init_dt: invalid node in parameter\n"))
+		return;
+
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (domain) {
+		domain->of_node = node;
+		domain->ops = &exynos4_irq_domain_combiner_ops;
+		irq_domain_add(domain);
+	} else {
+		WARN_ON(1);
+	}
+}
+#endif
-- 
1.6.6.rc2

^ permalink raw reply related

* [PATCH 1/2] arm: samsung: move timer irq numbers to end of linux irq space
From: Thomas Abraham @ 2011-10-06 21:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317935503-11756-1-git-send-email-thomas.abraham@linaro.org>

All of Samsung's s5p platforms have timer irqs statically mapped from linux
irq numbers 11 to 15. These timer irqs are moved to end of the statically
mapped linux irq space and the hardware irqs, which were statically mapped
starting from 32 is moved to start from 0. The NR_IRQS macro is consolidated
for all the s5p platforms in this process.

Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    1 -
 arch/arm/mach-exynos4/include/mach/irqs.h        |    3 +--
 arch/arm/mach-s5p64x0/include/mach/irqs.h        |    4 +---
 arch/arm/mach-s5pc100/include/mach/irqs.h        |    3 +--
 arch/arm/mach-s5pv210/include/mach/irqs.h        |    3 +--
 arch/arm/plat-samsung/include/plat/irqs.h        |    7 +++++--
 6 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index 4c9adbd..5c4fbcc 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -72,7 +72,6 @@
 		cmpcc	\irqnr, \irqnr
 		cmpne	\irqnr, \tmp
 		cmpcs	\irqnr, \irqnr
-		addne	\irqnr, \irqnr, #32
 
 		.endm
 
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index dfd4b7e..43087c3 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -163,7 +163,6 @@
 #define IRQ_GPIO2_NR_GROUPS	9
 #define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
 
-/* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_GPIO_END + 64)
+#define IRQ_TIMER_BASE		(IRQ_GPIO_END + 64)
 
 #endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 53982db..bea73cc 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -141,8 +141,6 @@
 
 #define IRQ_EINT_GROUP(grp, x)	(IRQ_EINT_GROUP##grp##_BASE + (x))
 
-/* Set the default NR_IRQS */
-
-#define NR_IRQS			(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
+#define IRQ_TIMER_BASE		(IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
 
 #endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index d2eb475..3a9d300 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -104,8 +104,7 @@
 #define S5P_GPIOINT_BASE	(IRQ_EINT(31) + 1)
 #define S5P_GPIOINT_GROUP_MAXNR	21
 
-/* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
+#define IRQ_TIMER_BASE		(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
 
 /* Compatibility */
 #define IRQ_LCD_FIFO		IRQ_LCD0
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index 5e0de3a..df3173a 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -125,8 +125,7 @@
 #define S5P_GPIOINT_BASE	(IRQ_EINT(31) + 1)
 #define S5P_GPIOINT_GROUP_MAXNR	22
 
-/* Set the default NR_IRQS */
-#define NR_IRQS			(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
+#define IRQ_TIMER_BASE		(IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
 
 /* Compatibility */
 #define IRQ_LCD_FIFO		IRQ_LCD0
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
index 08d1a7e..b8918b3 100644
--- a/arch/arm/plat-samsung/include/plat/irqs.h
+++ b/arch/arm/plat-samsung/include/plat/irqs.h
@@ -22,7 +22,7 @@
  * mulitple of 32 to allow the common code to work
  */
 
-#define S5P_IRQ_OFFSET		(32)
+#define S5P_IRQ_OFFSET		(0)
 
 #define S5P_IRQ(x)		((x) + S5P_IRQ_OFFSET)
 
@@ -44,13 +44,14 @@
 #define S5P_IRQ_VIC2(x)		(S5P_VIC2_BASE + (x))
 #define S5P_IRQ_VIC3(x)		(S5P_VIC3_BASE + (x))
 
-#define S5P_TIMER_IRQ(x)	(11 + (x))
+#define S5P_TIMER_IRQ(x)	(IRQ_TIMER_BASE + (x))
 
 #define IRQ_TIMER0		S5P_TIMER_IRQ(0)
 #define IRQ_TIMER1		S5P_TIMER_IRQ(1)
 #define IRQ_TIMER2		S5P_TIMER_IRQ(2)
 #define IRQ_TIMER3		S5P_TIMER_IRQ(3)
 #define IRQ_TIMER4		S5P_TIMER_IRQ(4)
+#define IRQ_TIMER_COUNT		(5)
 
 #define IRQ_EINT(x)		((x) < 16 ? ((x) + S5P_EINT_BASE1) \
 					: ((x) - 16 + S5P_EINT_BASE2))
@@ -77,4 +78,6 @@
 #define S5P_IRQ_TYPE_EDGE_RISING	(0x03)
 #define S5P_IRQ_TYPE_EDGE_BOTH		(0x04)
 
+#define NR_IRQS			(IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
+
 #endif /* __PLAT_SAMSUNG_IRQS_H */
-- 
1.6.6.rc2

^ permalink raw reply related

* [PATCH 0/2] arm: samsung: add device tree support for gic and interrupt combiner
From: Thomas Abraham @ 2011-10-06 21:11 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds device tree support for GIC and Interrupt Combiner
controllers in the Exynos4 SoC.

Patch 1 moves the statically mapped timer irqs 11 to 15 to the end of the
statically mapped linux irq space for all s5p platforms. This was required
because, device tree support for gic is based on Rob Herring's "GIC OF
bindings" patchset and that patchset requires hardware irq number to be
equal to GIC interrupt ID. Since GIC interrupt ID starts from zero, the
timer irqs 11 to 15 is moved to the end of the irq space and hardware irqs
are statically mapped to start from zero. I am not sure if statically
mapping hardware irqs starting from zero would be a problem.

Patch 2 adds device tree support for GIC and Interrupt Combiner controllers
on Exynos4. For GIC controller, this patch is based on Rob Herring's,
"[PATCH 0/3] GIC OF bindings" patchset. The concept of irq domain for
interrupt combiner controller is based on Grant's 'simple' irq converter

Thomas Abraham (2):
  arm: samsung: move timer irq numbers to end of linux irq space
  arm: exynos4: add support for dt irq specifier to linux virq conversion

 arch/arm/mach-exynos4/cpu.c                      |   20 +++++++++-
 arch/arm/mach-exynos4/include/mach/entry-macro.S |    1 -
 arch/arm/mach-exynos4/include/mach/irqs.h        |    3 +-
 arch/arm/mach-exynos4/irq-combiner.c             |   44 ++++++++++++++++++++++
 arch/arm/mach-s5p64x0/include/mach/irqs.h        |    4 +-
 arch/arm/mach-s5pc100/include/mach/irqs.h        |    3 +-
 arch/arm/mach-s5pv210/include/mach/irqs.h        |    3 +-
 arch/arm/plat-samsung/include/plat/irqs.h        |    7 ++-
 8 files changed, 72 insertions(+), 13 deletions(-)

^ permalink raw reply

* [PATCH] ARM: OMAP3: hwmod data: disable multiblock reads on MMC1/2 on OMAP34xx/35xx <= ES2.1
From: Paul Walmsley @ 2011-10-06 20:56 UTC (permalink / raw)
  To: linux-arm-kernel


The HSMMC1/HSMMC2 host controllers on OMAP34xx and
OMAP3503/3515/3525/3530 chips at ES levels prior to 3.0 can't do multiple
block reads[1].  Mark the hwmod data appropriately.

Reported by Dave Hylands <dhylands@gmail.com> and Steve Sakoman
<sakoman@gmail.com>.

1. See for example Advisory 2.1.1.128 "MMC: Multiple Block Read
   Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
   Revision F (October 2010) (SPRZ278F), available from
   http://focus.ti.com/lit/er/sprz278f/sprz278f.pdf

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dave Hylands <dhylands@gmail.com>
Cc: Steve Sakoman <sakoman@gmail.com>
---

This patch has a dependency on the "MMC: disable multiblock reads on 
controllers that don't support them" series recently posted to 
the linux-mmc list, so the application of this patch will probably be 
delayed until the 3.3 merge window.

 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   90 ++++++++++++++++++++++++++-
 1 files changed, 86 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 53b6706..a14d150 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -3020,7 +3020,35 @@ static struct omap_mmc_dev_attr mmc1_dev_attr = {
 	.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
-static struct omap_hwmod omap3xxx_mmc1_hwmod = {
+/* See 35xx errata 2.1.1.128 in SPRZ278F */
+static struct omap_mmc_dev_attr mmc1_pre_es3_dev_attr = {
+	.flags = (OMAP_HSMMC_SUPPORTS_DUAL_VOLT |
+		  OMAP_HSMMC_BROKEN_MULTIBLOCK_READ),
+};
+
+static struct omap_hwmod omap3xxx_pre_es3_mmc1_hwmod = {
+	.name		= "mmc1",
+	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
+	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
+	.opt_clks	= omap34xx_mmc1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc1_opt_clks),
+	.main_clk	= "mmchs1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MMC1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MMC1_SHIFT,
+		},
+	},
+	.dev_attr	= &mmc1_pre_es3_dev_attr,
+	.slaves		= omap3xxx_mmc1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc1_slaves),
+	.class		= &omap34xx_mmc_class,
+};
+
+static struct omap_hwmod omap3xxx_es3plus_mmc1_hwmod = {
 	.name		= "mmc1",
 	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
 	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
@@ -3063,7 +3091,34 @@ static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
 	&omap3xxx_l4_core__mmc2,
 };
 
-static struct omap_hwmod omap3xxx_mmc2_hwmod = {
+/* See 35xx errata 2.1.1.128 in SPRZ278F */
+static struct omap_mmc_dev_attr mmc2_pre_es3_dev_attr = {
+	.flags = OMAP_HSMMC_BROKEN_MULTIBLOCK_READ,
+};
+
+static struct omap_hwmod omap3xxx_pre_es3_mmc2_hwmod = {
+	.name		= "mmc2",
+	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
+	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
+	.opt_clks	= omap34xx_mmc2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc2_opt_clks),
+	.main_clk	= "mmchs2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MMC2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MMC2_SHIFT,
+		},
+	},
+	.dev_attr	= &mmc2_pre_es3_dev_attr,
+	.slaves		= omap3xxx_mmc2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc2_slaves),
+	.class		= &omap34xx_mmc_class,
+};
+
+static struct omap_hwmod omap3xxx_es3plus_mmc2_hwmod = {
 	.name		= "mmc2",
 	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
 	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
@@ -3130,8 +3185,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l4_core_hwmod,
 	&omap3xxx_l4_per_hwmod,
 	&omap3xxx_l4_wkup_hwmod,
-	&omap3xxx_mmc1_hwmod,
-	&omap3xxx_mmc2_hwmod,
 	&omap3xxx_mmc3_hwmod,
 	&omap3xxx_mpu_hwmod,
 	&omap3xxx_iva_hwmod,
@@ -3209,6 +3262,20 @@ static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
 	NULL
 };
 
+/* <= 3430ES3-only hwmods */
+static __initdata struct omap_hwmod *omap3430_pre_es3_hwmods[] = {
+	&omap3xxx_pre_es3_mmc1_hwmod,
+	&omap3xxx_pre_es3_mmc2_hwmod,
+	NULL
+};
+
+/* 3430ES3+-only hwmods */
+static __initdata struct omap_hwmod *omap3430_es3plus_hwmods[] = {
+	&omap3xxx_es3plus_mmc1_hwmod,
+	&omap3xxx_es3plus_mmc2_hwmod,
+	NULL
+};
+
 /* 34xx-only hwmods (all ES revisions) */
 static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
 	&omap34xx_sr1_hwmod,
@@ -3281,6 +3348,21 @@ int __init omap3xxx_hwmod_init(void)
 		h = omap3430es2plus_hwmods;
 	};
 
+	if (h) {
+		r = omap_hwmod_register(h);
+		if (IS_ERR_VALUE(r))
+			return r;
+	}
+
+	h = NULL;
+	if (rev == OMAP3430_REV_ES1_0 || rev == OMAP3430_REV_ES2_0 ||
+	    rev == OMAP3430_REV_ES2_1) {
+		h = omap3430_pre_es3_hwmods;
+	} else if (rev == OMAP3430_REV_ES3_0 || rev == OMAP3430_REV_ES3_1 ||
+		   rev == OMAP3430_REV_ES3_1_2) {
+		h = omap3430_es3plus_hwmods;
+	};
+
 	if (h)
 		r = omap_hwmod_register(h);
 
-- 
1.7.6.3

^ permalink raw reply related

* [PATCHv2] hw_random: add driver for atmel true hardware random number generator
From: Baruch Siach @ 2011-10-06 20:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87ty7l3l5b.fsf@macbook.be.48ers.dk>

Hi Peter,

On Thu, Oct 06, 2011 at 10:44:32PM +0200, Peter Korsgaard wrote:
> >>>>> "Baruch" == Baruch Siach <baruch@tkos.co.il> writes:
>  >> +static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
>  >> +			   bool wait)
>  >> +{
>  >> +	struct atmel_trng *trng = container_of(rng, struct atmel_trng, rng);
>  >> +	u32 *data = buf;
>  >> +
>  >> +	/* data ready? */
>  >> +	if (readl(trng->base + TRNG_ODATA) & 1) {
>  >> +		*data = readl(trng->base + TRNG_ODATA);
>  >> +		return 4;
> 
>  Baruch> Shouldn't you check for max >= 4 before writing to *buf?
> 
> Conceptually, yes. The other hw_random drivers don't seem to do it
> though, and the buffer size is guaranteed to be atleast 32 bytes, 

Ah, you're right, I missed that.

> but I can stick a '&& max >= 4' in the conditional if you prefer.

It probably doesn't worth the trouble, and the little added overhead. Thanks 
for the explanation.

baruch

-- 
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -

^ permalink raw reply

* [PATCH 2/2] MMC: omap_hsmmc: disable multiblock reads when platform_data indicates that they are broken
From: Paul Walmsley @ 2011-10-06 20:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111006205002.7083.94088.stgit@dusk>

When device data indicates that multiple block reads are not supported on
a given HSMMC controller instance, log a message to the console, and
pass the appropriate MMC capability flag to the MMC core.

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dave Hylands <dhylands@gmail.com>
Cc: Steve Sakoman <sakoman@gmail.com>
Cc: Chris Ball <cjb@laptop.org>
---
 arch/arm/plat-omap/include/plat/mmc.h |   19 ++++++++++++++++++-
 drivers/mmc/host/omap_hsmmc.c         |    4 ++++
 2 files changed, 22 insertions(+), 1 deletions(-)

diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index c7b8741..94cf70a 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -31,7 +31,24 @@
 
 #define OMAP_MMC_MAX_SLOTS	2
 
-#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT	BIT(1)
+/*
+ * struct omap_mmc_dev_attr.flags possibilities
+ *
+ * OMAP_HSMMC_SUPPORTS_DUAL_VOLT: Some HSMMC controller instances can
+ *    operate with either 1.8Vdc or 3.0Vdc card voltages; this flag
+ *    should be set if this is the case.  See for example Section 22.5.3
+ *    "MMC/SD/SDIO1 Bus Voltage Selection" of the OMAP34xx Multimedia
+ *    Device Silicon Revision 3.1.x Revision ZR (July 2011) (SWPU223R).
+ *
+ * OMAP_HSMMC_BROKEN_MULTIBLOCK_READ: Multiple-block read transfers
+ *    don't work correctly on some MMC controller instances on some
+ *    OMAP3 SoCs; this flag should be set if this is the case.  See
+ *    for example Advisory 2.1.1.128 "MMC: Multiple Block Read
+ *    Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
+ *    Revision F (October 2010) (SPRZ278F).
+ */
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT		BIT(0)
+#define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ	BIT(1)
 
 struct omap_mmc_dev_attr {
 	u8 flags;
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 21e4a79..9e8fc75 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1943,6 +1943,10 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	omap_hsmmc_context_save(host);
 
 	mmc->caps |= MMC_CAP_DISABLE;
+	if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
+		dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
+		mmc->caps |= MMC_CAP_NO_MULTI_READ;
+	}
 
 	pm_runtime_enable(host->dev);
 	pm_runtime_get_sync(host->dev);

^ permalink raw reply related

* [PATCH 1/2] MMC: add workaround for controllers with broken multiblock reads
From: Paul Walmsley @ 2011-10-06 20:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111006205002.7083.94088.stgit@dusk>

Due to hardware bugs, some MMC host controllers don't support
multiple-block reads[1].  To resolve, add a new MMC capability flag,
MMC_CAP_NO_MULTI_READ, which can be set by affected host controller
drivers.  When this capability is set, all reads will be issued one
sector at a time.

1. See for example Advisory 2.1.1.128 "MMC: Multiple Block Read
Operation Issue" in _OMAP3530/3525/3515/3503 Silicon Errata_
Revision F (October 2010) (SPRZ278F), available from
http://focus.ti.com/lit/er/sprz278f/sprz278f.pdf

Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Dave Hylands <dhylands@gmail.com>
Cc: Steve Sakoman <sakoman@gmail.com>
Cc: Chris Ball <cjb@laptop.org>
---
 drivers/mmc/card/block.c |   21 ++++++++++++++-------
 include/linux/mmc/host.h |    1 +
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 1ff5486..927f9d5 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -954,13 +954,20 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
 	if (brq->data.blocks > card->host->max_blk_count)
 		brq->data.blocks = card->host->max_blk_count;
 
-	/*
-	 * After a read error, we redo the request one sector at a time
-	 * in order to accurately determine which sectors can be read
-	 * successfully.
-	 */
-	if (disable_multi && brq->data.blocks > 1)
-		brq->data.blocks = 1;
+	if (brq->data.blocks > 1) {
+		/*
+		 * After a read error, we redo the request one sector
+		 * at a time in order to accurately determine which
+		 * sectors can be read successfully.
+		 */
+		if (disable_multi)
+			brq->data.blocks = 1;
+
+		/* Some controllers can't do multiblock reads due to hw bugs */
+		if (card->host->caps & MMC_CAP_NO_MULTI_READ &&
+		    rq_data_dir(req) == READ)
+			brq->data.blocks = 1;
+	}
 
 	if (brq->data.blocks > 1 || do_rel_wr) {
 		/* SPI multiblock writes terminate using a special
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 1d09562..745f506 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -229,6 +229,7 @@ struct mmc_host {
 #define MMC_CAP_MAX_CURRENT_600	(1 << 28)	/* Host max current limit is 600mA */
 #define MMC_CAP_MAX_CURRENT_800	(1 << 29)	/* Host max current limit is 800mA */
 #define MMC_CAP_CMD23		(1 << 30)	/* CMD23 supported. */
+#define MMC_CAP_NO_MULTI_READ	(1 << 31)	/* Multiblock reads don't work */
 
 	mmc_pm_flag_t		pm_caps;	/* supported pm features */
 

^ permalink raw reply related

* [PATCH 0/2] MMC: disable multiblock reads on controllers that don't support them
From: Paul Walmsley @ 2011-10-06 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

Some MMC controller instances integrated on older OMAP34xx/35xx chips
don't work correctly with multiple-block reads, due to a hardware bug.
This series fixes the problem by adding an MMC capability flag for this
case and making the appropriate changes to the MMC core code and OMAP HSMMC
driver to support this.

Once this series is merged, a subsequent patch will be needed by us OMAP
folks to pass the appropriate device data via hwmod - this will be posted
separately.


- Paul

---
mmc_errata_2.1.1.128_fix_3.2
   text	   data	    bss	    dec	    hex	filename
6325283	 655708	5591124	12572115	 bfd5d3	vmlinux.omap2plus_defconfig.orig
6329423	 655700	5591124	12576247	 bfe5f7	vmlinux.omap2plus_defconfig.patched

Paul Walmsley (2):
      MMC: add workaround for controllers with broken multiblock reads
      MMC: omap_hsmmc: disable multiblock reads when platform_data indicates that they are broken


 arch/arm/plat-omap/include/plat/mmc.h |   19 ++++++++++++++++++-
 drivers/mmc/card/block.c              |   21 ++++++++++++++-------
 drivers/mmc/host/omap_hsmmc.c         |    4 ++++
 include/linux/mmc/host.h              |    1 +
 4 files changed, 37 insertions(+), 8 deletions(-)

^ permalink raw reply

* [PATCHv2] hw_random: add driver for atmel true hardware random number generator
From: Peter Korsgaard @ 2011-10-06 20:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20111006203023.GE24034@tarshish>

>>>>> "Baruch" == Baruch Siach <baruch@tkos.co.il> writes:

Hi,

 >> +static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max,
 >> +			   bool wait)
 >> +{
 >> +	struct atmel_trng *trng = container_of(rng, struct atmel_trng, rng);
 >> +	u32 *data = buf;
 >> +
 >> +	/* data ready? */
 >> +	if (readl(trng->base + TRNG_ODATA) & 1) {
 >> +		*data = readl(trng->base + TRNG_ODATA);
 >> +		return 4;

 Baruch> Shouldn't you check for max >= 4 before writing to *buf?

Conceptually, yes. The other hw_random drivers don't seem to do it
though, and the buffer size is guaranteed to be atleast 32 bytes, but I
can stick a '&& max >= 4' in the conditional if you prefer.

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* [PATCH] ARM: OMAP3: hwmod: fix variant registration and remove SmartReflex from common list
From: Tony Lindgren @ 2011-10-06 20:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1110061433540.4611@utopia.booyaka.com>

* Paul Walmsley <paul@pwsan.com> [111006 13:05]:
> 
> Commit d6504acd2125984c61dce24727dd3842d0144015 ("OMAP2+: hwmod:
> remove OMAP_CHIP*") tests the inverse condition of what it should be
> testing for the return value from omap_hwmod_register().  This causes
> several IP blocks to not be registered on several OMAP3 family devices.
> 
> Fixing that bug also unmasked another bug, originally reported by
> Chase Maupin <chase.maupin@ti.com> and then subsequently by Abhilash K
> V <abhilash.kv@ti.com>, which caused SmartReflex IP blocks to be
> registered on SoCs that don't support them.
> 
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> Cc: Chase Maupin <chase.maupin@ti.com>
> Cc: Abhilash K V <abhilash.kv@ti.com>
> ---
> 
> This fixes a pretty embarrassing "brown paper bag" bug of mine in one of 
> the cleanup patches.  Tony, it would be good if you could send this to 
> Arnd ASAP and merge into your cleanup branch.  Tested on 3430SDP, 37XX 
> EVM, and OMAP3503.

OK thanks, applying into fixes-part2 branch.

Regards,

Tony

^ permalink raw reply


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