Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/09] ARM: s3c2442: gta02: Fix usage gpio bank j pin definitions
From: Kukjin Kim @ 2011-02-21  9:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4D5E4CC1.1010705@metafoo.de>

Lasrs-Peter Clausen wrote:
> 
> On 02/07/2011 02:51 AM, Lars-Peter Clausen wrote:
> > The gta02 header file still uses the old S3C2410_GPJx defines instead of
> the
> > S3C2410_GPJ(x) macro. Since the S3C2410_GPJx defines have already been
> removed
> > this causes the following build failure:
> >
> > 	sound/soc/samsung/neo1973_wm8753.c: In function 'lm4853_set_spk':
> > 	sound/soc/samsung/neo1973_wm8753.c:259: error: 'S3C2440_GPJ2'
> undeclared (first use in this function)
> > 	sound/soc/samsung/neo1973_wm8753.c:259: error: (Each undeclared
> identifier is reported only once
> > 	sound/soc/samsung/neo1973_wm8753.c:259: error: for each function it
> appears in.)
> > 	sound/soc/samsung/neo1973_wm8753.c: In function 'lm4853_get_spk':
> > 	sound/soc/samsung/neo1973_wm8753.c:267: error: 'S3C2440_GPJ2'
> undeclared (first use in this function)
> > 	sound/soc/samsung/neo1973_wm8753.c: In function 'lm4853_event':
> > 	sound/soc/samsung/neo1973_wm8753.c:276: error: 'S3C2440_GPJ1'
> undeclared (first use in this function)
> > 	sound/soc/samsung/neo1973_wm8753.c: At top level:
> > 	sound/soc/samsung/neo1973_wm8753.c:439: error: 'S3C2440_GPJ2'
> undeclared here (not in a function)
> > 	sound/soc/samsung/neo1973_wm8753.c:440: error: 'S3C2440_GPJ1'
> undeclared here (not in a function)
> >
> > This patches fixes the issue by doing a
> s,S3C2410_GPJ([\d]+),S3C2410_GPJ(\1),g
> > on the file.
> >
> > Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
> 
> 
> Hi
> 
> Ben or Kukjin could you take a look at this series and merge it, if it is
ok?
> 
Hi Lars-Peter,

Basically, the maintainer of mach-s3c* is Ben Dooks.
I think, he will review this series but if he can't soon, I will/can do it.

Ben, could you please review this patches?
If you're busy, please let me know :)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

^ permalink raw reply

* [PATCH 2/6] ARM: pm: add generic CPU suspend/resume support
From: Kukjin Kim @ 2011-02-21  9:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110220120039.GA14495@n2100.arm.linux.org.uk>

Russell King - ARM Linux wrote:
> 
> Kukjin, could you test this update as well please?
> 
No problem :)

It works fine with following.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

> Thanks.
> 
> On Tue, Feb 15, 2011 at 11:04:53AM +0000, Russell King - ARM Linux wrote:
> > On Fri, Feb 11, 2011 at 06:50:57PM -0800, Colin Cross wrote:
> > > > +ENDPROC(cpu_resume_turn_mmu_on)
> > > > +cpu_resume_after_mmu:
> > > > + ? ? ? str ? ? r5, [r2, r4, lsl #2] ? ?@ restore old mapping
> > > > +#ifdef MULTI_CACHE
> > > > + ? ? ? ldr ? ? r10, =cpu_cache
> > > > + ? ? ? ldr ? ? pc, [r10, #CACHE_FLUSH_KERN_ALL]
> > > > +#else
> > > > + ? ? ? b ? ? ? __cpuc_flush_kern_all
> > > > +#endif
> >
> > I think we can eliminate this cache flush by delaying the cache enable
> > as below.  Could you see whether Tegra 2 survives this please?
> > Thanks.
> >
> > diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> > index bed1876..193be5f 100644
> > --- a/arch/arm/kernel/sleep.S
> > +++ b/arch/arm/kernel/sleep.S
> > @@ -4,6 +4,7 @@
> >  #include <asm/assembler.h>
> >  #include <asm/glue-cache.h>
> >  #include <asm/glue-proc.h>
> > +#include <asm/system.h>
> >  	.text
> >
> >  /*
> > @@ -81,25 +82,22 @@ ENTRY(cpu_resume_mmu)
> >  	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
> >  	sub	r2, r2, r1
> >  	ldr	r3, =cpu_resume_after_mmu
> > +	bic	r1, r0, #CR_C		@ ensure D-cache is disabled
> >  	b	cpu_resume_turn_mmu_on
> >  ENDPROC(cpu_resume_mmu)
> >  	.ltorg
> >  	.align	5
> >  cpu_resume_turn_mmu_on:
> > -	mcr	p15, 0, r0, c1, c0, 0	@ turn on MMU, caches, etc
> > -	mrc	p15, 0, r0, c0, c0, 0	@ read id reg
> > -	mov	r0, r0
> > -	mov	r0, r0
> > +	mcr	p15, 0, r1, c1, c0, 0	@ turn on MMU, I-cache, etc
> > +	mrc	p15, 0, r1, c0, c0, 0	@ read id reg
> > +	mov	r1, r1
> > +	mov	r1, r1
> >  	mov	pc, r3			@ jump to virtual address
> >  ENDPROC(cpu_resume_turn_mmu_on)
> >  cpu_resume_after_mmu:
> >  	str	r5, [r2, r4, lsl #2]	@ restore old mapping
> > -#ifdef MULTI_CACHE
> > -	ldr	r10, =cpu_cache
> > -	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
> > -#else
> > -	b	__cpuc_flush_kern_all
> > -#endif
> > +	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
> > +	mov	pc, lr
> >
> >  /*
> >   * Note: Yes, part of the following code is located into the .data
section.

^ permalink raw reply

* [GIT PULL] Samsung fixes for 2.6.38-rc6
From: Kukjin Kim @ 2011-02-21  9:58 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Linus,

Please pull Samsung fixes from:

git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
s5p-fixes-for-linus

These things are for small fix and cleanup on 2.6.38-rc6.
As a note, cleanup patch includes fixing coding style such as removing
useless braces, and re-ordering.

If any problems, please let me know.

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.

The following changes since commit 85e2efbb1db9a18d218006706d6e4fbeb0216213:

  Linux 2.6.38-rc5 (2011-02-15 19:23:45 -0800)

are available in the git repository at:
   git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
s5p-fixes-for-linus

Axel Lin (1):
      ARM: SAMSUNG: Drop exporting s3c24xx_ts_set_platdata

Kukjin Kim (5):
      ARM: S5PV310: Cleanup map.h file
      ARM: S5PV210: Cleanup map.h file
      ARM: S5PC100: Clenaup map.h file
      ARM: S5P6442: Cleanup map.h file
      ARM: S5P64X0: Cleanup map.h file

Marek Szyprowski (2):
      ARM: S5PV210: Update max8998_platform_data
      ARM: S5PV210: Fix regulator names

Thomas Abraham (1):
      ARM: S5P: Fix end address in memory resource information for UART
devices

 arch/arm/mach-s5p6442/include/mach/map.h |   69 ++++++-----
 arch/arm/mach-s5p64x0/include/mach/map.h |   83 +++++++-------
 arch/arm/mach-s5pc100/include/mach/map.h |  193
+++++++++++++-----------------
 arch/arm/mach-s5pv210/include/mach/map.h |  168 +++++++++++++-------------
 arch/arm/mach-s5pv210/mach-aquila.c      |   15 ++-
 arch/arm/mach-s5pv210/mach-goni.c        |   15 ++-
 arch/arm/mach-s5pv310/include/mach/map.h |  149 +++++++++++------------
 arch/arm/plat-s5p/dev-uart.c             |   12 +-
 arch/arm/plat-samsung/dev-ts.c           |    1 -
 9 files changed, 342 insertions(+), 363 deletions(-)

^ permalink raw reply

* [PATCH 4/5] mm: sdhci-esdhc: remove SDHCI_QUIRK_NO_CARD_NO_RESET from ESDHC_DEFAULT_QUIRKS
From: Wolfram Sang @ 2011-02-21 10:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298282095-2279-4-git-send-email-richard.zhao@freescale.com>

On Mon, Feb 21, 2011 at 05:54:54PM +0800, Richard Zhao wrote:
> sdhci-esdhc-imx does not need SDHCI_QUIRK_NO_CARD_NO_RESET.
> Make it OF-specific.

Just to make sure, because all the other patches are for mx53: Do you
have tested it on mx25/35/51 also?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/68f6d0be/attachment.sig>

^ permalink raw reply

* [PATCH 5/5] mmc: sdhci: add quirk SDHCI_QUIRK_FIX_NO_INT_IN_MULTI_BLK_IO
From: Wolfram Sang @ 2011-02-21 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298282095-2279-5-git-send-email-richard.zhao@freescale.com>

On Mon, Feb 21, 2011 at 05:54:55PM +0800, Richard Zhao wrote:
> Fix no INT in MULTI-BLK IO.
> 
> Signed-off-by: Richard Zhu <Hong-Xing.Zhu@freescale.com>
> 
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 9b82910..2eeb03e 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -113,7 +113,10 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
>  	clk_enable(clk);
>  	pltfm_host->clk = clk;
>  
> -	if (cpu_is_mx35() || cpu_is_mx51())
> +	if (cpu_is_mx53())
> +		host->quirks |= SDHCI_QUIRK_FIX_NO_INT_IN_MULTI_BLK_IO;

Have you tried it doing it via IO-accessors?

> +	if (cpu_is_mx35() || cpu_is_mx51() || cpu_is_mx53())

Maybe we should use !cpu_is_mx25 for simplicity?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/41168972/attachment.sig>

^ permalink raw reply

* [PATCH 5/5] mmc: sdhci: add quirk SDHCI_QUIRK_FIX_NO_INT_IN_MULTI_BLK_IO
From: Zhu Richard-R65037 @ 2011-02-21 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110221100439.GE2616@pengutronix.de>

Hi Wolfsang:
See my comments marked by Richard Zhu below.

Best Regards
Richard Zhu

> -----Original Message-----
> From: Wolfram Sang [mailto:w.sang at pengutronix.de]
> Sent: Monday, February 21, 2011 6:05 PM
> To: Zhao Richard-B20223
> Cc: linux-arm-kernel at lists.infradead.org; kernel at pengutronix.de; linux-
> mmc at vger.kernel.org; cjb at laptop.org; avorontsov at ru.mvista.com;
> eric at eukrea.com; linuxzsc at gmail.com; Zhu Richard-R65037; Zhu Richard-
> R65037
> Subject: Re: [PATCH 5/5] mmc: sdhci: add quirk
> SDHCI_QUIRK_FIX_NO_INT_IN_MULTI_BLK_IO
>
> On Mon, Feb 21, 2011 at 05:54:55PM +0800, Richard Zhao wrote:
> > Fix no INT in MULTI-BLK IO.
> >
> > Signed-off-by: Richard Zhu <Hong-Xing.Zhu@freescale.com>
> >
> > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c
> b/drivers/mmc/host/sdhci-esdhc-imx.c
> > index 9b82910..2eeb03e 100644
> > --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> > @@ -113,7 +113,10 @@ static int esdhc_pltfm_init(struct sdhci_host
> *host, struct sdhci_pltfm_data *pd
> >     clk_enable(clk);
> >     pltfm_host->clk = clk;
> >
> > -   if (cpu_is_mx35() || cpu_is_mx51())
> > +   if (cpu_is_mx53())
> > +           host->quirks |= SDHCI_QUIRK_FIX_NO_INT_IN_MULTI_BLK_IO;
>
> Have you tried it doing it via IO-accessors?
Richard Zhu: This quirk is used to fix a mechanism problem in the MMC CMDs execution procedure.
It would be very abrupt and ugly, if the IO-accessors are added into these original procedures.
So one quirk is used here, and used to fix two different case.
One is multi-blk read in SDIO mode, the other is the Mult-blk read/write in mass storage mode.

>
> > +   if (cpu_is_mx35() || cpu_is_mx51() || cpu_is_mx53())
>
> Maybe we should use !cpu_is_mx25 for simplicity?
Richard Zhu: Accepted.
>
> Regards,
>
>    Wolfram
>
> --
> Pengutronix e.K.                           | Wolfram Sang
> |
> Industrial Linux Solutions                 | http://www.pengutronix.de/
> |

^ permalink raw reply

* [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
From: Jean Pihet @ 2011-02-21 10:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298112158-28469-15-git-send-email-santosh.shilimkar@ti.com>

Hi Santosh,

I have a few comments and questions inlined.

On Sat, Feb 19, 2011 at 11:42 AM, Santosh Shilimkar
<santosh.shilimkar@ti.com> wrote:
> This patch adds MPUSS low power states in cpuidle.
>
> ? ? ? ?C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON
> ? ? ? ?C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
> ? ? ? ?C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
> ? ? ? ?C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
>
> MPU OSWR isn't supported yet. To support OSWR, power domain context
> registers needs to be managed which are not supported yet. A patch
> to address this was submitted but it's not ready for merge yet because
> it was not addressing all OMAP4 power domain context registers.
> More info on this issue:
> ? ? ? ?http://www.mail-archive.com/linux-omap at vger.kernel.org/msg38667.html
>
> OMAP4 powerdomain INACTIVE support is also dropped because of inconsistency
> of it with OMAP3. More information ?on this thread.
> ? ? ? ?http://www.spinics.net/lists/linux-omap/msg45370.html
>
> CORE low power states and associated latencies will be updated as part
> along with chip retention support.
>
> On OMAP4 because of hardware constraints, no low power states are
> targeted when both CPUs are online and in SMP mode. The low power
> states are attempted only when secondary CPU gets offline to OFF
> through hotplug infrastructure.
>
> Thanks to Nicole Chalhoub <n-chalhoub@ti.com> for doing exhaustive
> C-state latency profiling.
>
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Reviewed-by: Kevin Hilman <khilman@ti.com>
> ---
> ?arch/arm/mach-omap2/cpuidle44xx.c | ?190 ++++++++++++++++++++++++++++++++++---
> ?1 files changed, 176 insertions(+), 14 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c
> index 6c3c69d..aa1584e 100644
> --- a/arch/arm/mach-omap2/cpuidle44xx.c
> +++ b/arch/arm/mach-omap2/cpuidle44xx.c
> @@ -3,6 +3,7 @@
> ?*
> ?* Copyright (C) 2011 Texas Instruments, Inc.
> ?* Rajendra Nayak <rnayak@ti.com>
> + * Santosh Shilimkar <santosh.shilimkar@ti.com>
> ?*
> ?* 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
> @@ -17,12 +18,21 @@
> ?#include <mach/omap4-common.h>
>
> ?#include "pm.h"
> +#include "prm.h"
>
> ?#ifdef CONFIG_CPU_IDLE
>
> -#define OMAP4_MAX_STATES ? ? ? 1
> -/* C1 - CPUx wfi + MPU inactive + CORE inactive */
> +#define CPUIDLE_FLAG_CHECK_BM ?0x10000 /* use omap4_enter_idle_bm() */
> +#define OMAP4_MAX_STATES ? ? ? 4
> +
> +/* C1 - CPU0 ON + CPU1 ON/OFF + MPU ON + CORE ON */
> ?#define OMAP4_STATE_C1 ? ? ? ? 0
> +/* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON */
> +#define OMAP4_STATE_C2 ? ? ? ? 1
> +/* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> +#define OMAP4_STATE_C3 ? ? ? ? 2
> +/* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> +#define OMAP4_STATE_C4 ? ? ? ? 3
>
> ?struct omap4_processor_cx {
> ? ? ? ?u8 valid;
> @@ -32,19 +42,44 @@ struct omap4_processor_cx {
> ? ? ? ?u32 cpu0_state;
> ? ? ? ?u32 cpu1_state;
> ? ? ? ?u32 mpu_state;
> + ? ? ? u32 mpu_logic_state;
> ? ? ? ?u32 core_state;
> + ? ? ? u32 core_logic_state;
> ? ? ? ?u32 threshold;
> ? ? ? ?u32 flags;
> + ? ? ? const char *desc;
> ?};
>
> -struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
> -struct omap4_processor_cx current_cx_state;
> +static struct omap4_processor_cx omap4_power_states[OMAP4_MAX_STATES];
> +static struct powerdomain *mpu_pd, *cpu1_pd, *core_pd;
>
> +/*
> + * FIXME: Full latenecy numbers needs to be updated as part of
Typo: 'latency'

> + * cpuidle CORE retention support.
> + * Currently only MPUSS latency numbers are added based on
> + * measurements done internally. The numbers for MPUSS are
> + * not board dependent and hence set directly here instead of
> + * passing it from board files.
> + */
> ?static struct cpuidle_params cpuidle_params_table[] = {
> - ? ? ? /* C1 */
> - ? ? ? {1, 2, 2, 5},
> + ? ? ? /* C1 - CPU0 WFI + CPU1 ON/OFF + MPU ON ? + CORE ON */
> + ? ? ? {1, ? ? 2, ? ? ?2, ? ? ?5},
> + ? ? ? /* C2 - CPU0 ON + CPU1 OFF + MPU ON ?+ CORE ON */
> + ? ? ? {1, ? ? 140, ? ?160, ? ?300},
> + ? ? ? /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> + ? ? ? {1, ? ? 200, ? ?300, ? ?700},
> + ? ? ? /* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> + ? ? ? {1, ? ? 1400, ? 600, ? ?5000},
> ?};
>
> +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> +
> +static int omap4_idle_bm_check(void)
> +{
> + ? ? ? /* FIXME: Populate this with CORE retention support */
> + ? ? ? return 0;
> +}
> +
> ?/**
> ?* omap4_enter_idle - Programs OMAP4 to enter the specified state
> ?* @dev: cpuidle device
> @@ -57,7 +92,9 @@ static struct cpuidle_params cpuidle_params_table[] = {
> ?static int omap4_enter_idle(struct cpuidle_device *dev,
> ? ? ? ? ? ? ? ? ? ? ? ?struct cpuidle_state *state)
> ?{
> + ? ? ? struct omap4_processor_cx *cx = cpuidle_get_statedata(state);
> ? ? ? ?struct timespec ts_preidle, ts_postidle, ts_idle;
> + ? ? ? u32 cpu1_state;
>
> ? ? ? ?/* Used to keep track of the total time in idle */
> ? ? ? ?getnstimeofday(&ts_preidle);
> @@ -65,28 +102,74 @@ static int omap4_enter_idle(struct cpuidle_device *dev,
> ? ? ? ?local_irq_disable();
> ? ? ? ?local_fiq_disable();
>
> - ? ? ? cpu_do_idle();

I think the piece of code below is rather difficult to read and
understand. Based on the patch description and the comment here below
I do not see the relation with the code.

" On OMAP4 because of hardware constraints, no low power states are
 targeted when both CPUs are online and in SMP mode. The low power
 states are attempted only when secondary CPU gets offline to OFF
 through hotplug infrastructure. "
The test below does not seem to match this comment.

> + ? ? ? /*
> + ? ? ? ?* Special hardware/software considerations:
> + ? ? ? ?* 1. Do only WFI for secondary CPU(non-boot - CPU1).
> + ? ? ? ?* ? ?Secondary cores are taken down only via hotplug path.
The comment looks contradictory. Which one is taken OFF using this
code, which one from hotplug?
Does this correspond to the condition '(dev->cpu)' in the test below?

> + ? ? ? ?* 2. Do only a WFI as long as in SMP mode.
Does this correspond to the condition '(num_online_cpus() > 1)' in the
test below? If so it this one triggering the low power mode for cpu0?

> + ? ? ? ?* 3. Continue to do only WFI till CPU1 hits OFF state.
> + ? ? ? ?* ? ?This is necessary to honour hardware recommondation
> + ? ? ? ?* ? ?of triggeing all the possible low power modes once CPU1 is
> + ? ? ? ?* ? ?out of coherency and in OFF mode.
Does this correspond to the condition '(cpu1_state !=
PWRDM_POWER_OFF)' in the test below?

> + ? ? ? ?* Update dev->last_state so that governor stats reflects right
> + ? ? ? ?* data.
> + ? ? ? ?*/
> + ? ? ? cpu1_state = pwrdm_read_pwrst(cpu1_pd);
> + ? ? ? if ((dev->cpu) || (num_online_cpus() > 1) ||
> + ? ? ? ? ? ? ? ? ? ? ? (cpu1_state != PWRDM_POWER_OFF)) {
Are '||' correct here?
Sorry if the code behaves correctly, the remarks are about readability
especially in the comments.

Regards,
Jean

> + ? ? ? ? ? ? ? dev->last_state = dev->safe_state;
> + ? ? ? ? ? ? ? cpu_do_idle();
> + ? ? ? ? ? ? ? goto return_sleep_time;
> + ? ? ? }
>
> + ? ? ? pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
> + ? ? ? omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
> + ? ? ? pwrdm_set_logic_retst(core_pd, cx->core_logic_state);
> + ? ? ? omap_set_pwrdm_state(core_pd, cx->core_state);
> +
> + ? ? ? omap4_enter_lowpower(dev->cpu, cx->cpu0_state);
> +
> +return_sleep_time:
> ? ? ? ?getnstimeofday(&ts_postidle);
> ? ? ? ?ts_idle = timespec_sub(ts_postidle, ts_preidle);
>
> ? ? ? ?local_irq_enable();
> ? ? ? ?local_fiq_enable();
>
> +
> ? ? ? ?return ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * USEC_PER_SEC;
> ?}
>
> -DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> +/**
> + * omap4_enter_idle_bm - Checks for any bus activity
> + * @dev: cpuidle device
> + * @state: The target state to be programmed
> + *
> + * Used for C states with CPUIDLE_FLAG_CHECK_BM flag set. This
> + * function checks for any pending activity and then programs the
> + * device to the specified or a safer state.
> + */
> +static int omap4_enter_idle_bm(struct cpuidle_device *dev,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct cpuidle_state *state)
> +{
> + ? ? ? if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap4_idle_bm_check()) {
> + ? ? ? ? ? ? ? BUG_ON(!dev->safe_state);
> + ? ? ? ? ? ? ? state = dev->safe_state;
> + ? ? ? }
> +
> + ? ? ? dev->last_state = state;
> + ? ? ? return omap4_enter_idle(dev, state);
> +}
>
> ?/**
> ?* omap4_init_power_states - Initialises the OMAP4 specific C states.
> ?*
> - * Below is the desciption of each C state.
> - * C1 : CPUx wfi + MPU inative + Core inactive
> ?*/
> -void omap_init_power_states(void)
> +void omap4_init_power_states(void)
> ?{
> - ? ? ? /* C1 . CPUx wfi + MPU inactive + Core inactive */
> + ? ? ? /*
> + ? ? ? ?* C1 - CPU0 WFI + CPU1 OFF + MPU ON + CORE ON
> + ? ? ? ?*/
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].valid =
> ? ? ? ? ? ? ? ? ? ? ? ?cpuidle_params_table[OMAP4_STATE_C1].valid;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].type = OMAP4_STATE_C1;
> @@ -96,9 +179,80 @@ void omap_init_power_states(void)
> ? ? ? ? ? ? ? ? ? ? ? ?cpuidle_params_table[OMAP4_STATE_C1].wake_latency;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].threshold =
> ? ? ? ? ? ? ? ? ? ? ? ?cpuidle_params_table[OMAP4_STATE_C1].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].cpu0_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].cpu1_state = PWRDM_POWER_OFF;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].mpu_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].mpu_logic_state = PWRDM_POWER_RET;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].core_logic_state = PWRDM_POWER_RET;
> ? ? ? ?omap4_power_states[OMAP4_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
> + ? ? ? omap4_power_states[OMAP4_STATE_C1].desc = "MPU ON + CORE ON";
> +
> + ? ? ? /*
> + ? ? ? ?* C2 - CPU0 ON + CPU1 OFF + MPU ON + CORE ON
> + ? ? ? ?*/
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].valid =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].valid;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].type = OMAP4_STATE_C2;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].sleep_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].sleep_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].wakeup_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].wake_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].threshold =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C2].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].cpu0_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].cpu1_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].mpu_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].mpu_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].core_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
> + ? ? ? ? ? ? ? CPUIDLE_FLAG_CHECK_BM;
> + ? ? ? omap4_power_states[OMAP4_STATE_C2].desc = "MPU ON + CORE ON";
> +
> + ? ? ? /*
> + ? ? ? ?* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON
> + ? ? ? ?*/
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].valid =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].valid;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].type = OMAP4_STATE_C3;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].sleep_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].sleep_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].wakeup_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].wake_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].threshold =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C3].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].cpu0_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].cpu1_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].mpu_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].mpu_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].core_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
> + ? ? ? ? ? ? ? CPUIDLE_FLAG_CHECK_BM;
> + ? ? ? omap4_power_states[OMAP4_STATE_C3].desc = "MPU CSWR + CORE ON";
> +
> + ? ? ? /*
> + ? ? ? ?* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON
> + ? ? ? ?*/
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].valid =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].valid;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].type = OMAP4_STATE_C4;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].sleep_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].sleep_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].wakeup_latency =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].wake_latency;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].threshold =
> + ? ? ? ? ? ? ? ? ? ? ? cpuidle_params_table[OMAP4_STATE_C4].threshold;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].cpu0_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].cpu1_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].mpu_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].mpu_logic_state = PWRDM_POWER_OFF;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].core_state = PWRDM_POWER_ON;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].core_logic_state = PWRDM_POWER_RET;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
> + ? ? ? ? ? ? ? CPUIDLE_FLAG_CHECK_BM;
> + ? ? ? omap4_power_states[OMAP4_STATE_C4].desc = "MPU OFF + CORE ON";
>
> ?}
>
> @@ -120,7 +274,11 @@ int __init omap4_idle_init(void)
> ? ? ? ?struct cpuidle_state *state;
> ? ? ? ?struct cpuidle_device *dev;
>
> - ? ? ? omap_init_power_states();
> + ? ? ? mpu_pd = pwrdm_lookup("mpu_pwrdm");
> + ? ? ? cpu1_pd = pwrdm_lookup("cpu1_pwrdm");
> + ? ? ? core_pd = pwrdm_lookup("core_pwrdm");
> +
> + ? ? ? omap4_init_power_states();
> ? ? ? ?cpuidle_register_driver(&omap4_idle_driver);
>
> ? ? ? ?for_each_cpu(cpu_id, cpu_online_mask) {
> @@ -139,8 +297,12 @@ int __init omap4_idle_init(void)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?cx->wakeup_latency;
> ? ? ? ? ? ? ? ? ? ? ? ?state->target_residency = cx->threshold;
> ? ? ? ? ? ? ? ? ? ? ? ?state->flags = cx->flags;
> - ? ? ? ? ? ? ? ? ? ? ? state->enter = omap4_enter_idle;
> + ? ? ? ? ? ? ? ? ? ? ? if (cx->type == OMAP4_STATE_C1)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev->safe_state = state;
> + ? ? ? ? ? ? ? ? ? ? ? state->enter = (state->flags & CPUIDLE_FLAG_CHECK_BM) ?
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? omap4_enter_idle_bm : omap4_enter_idle;
> ? ? ? ? ? ? ? ? ? ? ? ?sprintf(state->name, "C%d", count+1);
> + ? ? ? ? ? ? ? ? ? ? ? strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
> ? ? ? ? ? ? ? ? ? ? ? ?count++;
> ? ? ? ? ? ? ? ?}
>
> --
> 1.6.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* [PATCH v3] dmaengine: mxs-dma: add dma support for i.MX23/28
From: Shawn Guo @ 2011-02-21 10:21 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds dma support for Freescale MXS-based SoC i.MX23/28,
including apbh-dma and apbx-dma.

* apbh-dma and apbx-dma are supported in the driver as two mxs-dma
  instances.

* apbh-dma is different between mx23 and mx28, hardware version
  register is used to differentiate.

* mxs-dma supports pio function besides data transfer.  The driver
  uses dma_data_direction DMA_NONE to identify the pio mode, and
  steals sgl and sg_len to get pio words and numbers from clients.

* mxs dmaengine has some very specific features, like sense function
  and the special NAND support (nand_lock, nand_wait4ready).  These
  are too specific to implemented in generic dmaengine driver.

* The driver refers to imx-sdma and only a single descriptor is
  statically assigned to each channel.

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/include/mach/dma.h |   26 ++
 drivers/dma/Kconfig                  |    8 +
 drivers/dma/Makefile                 |    1 +
 drivers/dma/mxs-dma.c                |  719 ++++++++++++++++++++++++++++++++++
 4 files changed, 754 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/include/mach/dma.h
 create mode 100644 drivers/dma/mxs-dma.c

diff --git a/arch/arm/mach-mxs/include/mach/dma.h b/arch/arm/mach-mxs/include/mach/dma.h
new file mode 100644
index 0000000..7f4aeea
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/dma.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 __MACH_MXS_DMA_H__
+#define __MACH_MXS_DMA_H__
+
+struct mxs_dma_data {
+	int chan_irq;
+};
+
+static inline int mxs_dma_is_apbh(struct dma_chan *chan)
+{
+	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbh");
+}
+
+static inline int mxs_dma_is_apbx(struct dma_chan *chan)
+{
+	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbx");
+}
+
+#endif /* __MACH_MXS_DMA_H__ */
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 1c28816..76f6472 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -227,6 +227,14 @@ config IMX_DMA
 	  Support the i.MX DMA engine. This engine is integrated into
 	  Freescale i.MX1/21/27 chips.
 
+config MXS_DMA
+	bool "MXS DMA support"
+	depends on SOC_IMX23 || SOC_IMX28
+	select DMA_ENGINE
+	help
+	  Support the MXS DMA engine. This engine including APBH-DMA
+	  and APBX-DMA is integrated into Freescale i.MX23/28 chips.
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 64b21f5..802b557 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
 obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
 obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
 obj-$(CONFIG_IMX_DMA) += imx-dma.o
+obj-$(CONFIG_MXS_DMA) += mxs-dma.o
 obj-$(CONFIG_TIMB_DMA) += timb_dma.o
 obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
new file mode 100644
index 0000000..6e407e1
--- /dev/null
+++ b/drivers/dma/mxs-dma.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Refer to drivers/dma/imx-sdma.c
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+
+#include <asm/irq.h>
+#include <mach/mxs.h>
+#include <mach/dma.h>
+#include <mach/common.h>
+
+/*
+ * NOTE: The term "PIO" throughout the mxs-dma implementation means
+ * PIO mode of mxs apbh-dma and apbx-dma.  With this working mode,
+ * dma can program the controller registers of peripheral devices.
+ */
+
+#define MXS_DMA_APBH		0
+#define MXS_DMA_APBX		1
+#define dma_is_apbh()		(mxs_dma->dev_id == MXS_DMA_APBH)
+
+#define APBH_VERSION_LATEST	3
+#define apbh_is_old()		(mxs_dma->version < APBH_VERSION_LATEST)
+
+#define HW_APBHX_CTRL0				0x000
+#define  BM_APBH_CTRL0_APB_BURST8_EN		(1 << 29)
+#define  BM_APBH_CTRL0_APB_BURST_EN		(1 << 28)
+#define  BP_APBH_CTRL0_CLKGATE_CHANNEL		(8)
+#define  BP_APBH_CTRL0_RESET_CHANNEL		(16)
+#define HW_APBHX_CTRL1				0x010
+#define HW_APBHX_CTRL2				0x020
+#define HW_APBHX_CHANNEL_CTRL			0x030
+#define  BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL	(16)
+#define HW_APBH_VERSION				(cpu_is_mx23() ? 0x3f0 : 0x800)
+#define HW_APBX_VERSION				0x800
+#define  BP_APBHX_VERSION_MAJOR			(24)
+#define HW_APBHX_CHn_NXTCMDAR(n) \
+	(((dma_is_apbh() && apbh_is_old()) ? 0x050 : 0x110) + (n) * 0x70)
+#define HW_APBHX_CHn_SEMA(n) \
+	(((dma_is_apbh() && apbh_is_old()) ? 0x080 : 0x140) + (n) * 0x70)
+
+/*
+ * ccw bits definitions
+ *
+ * COMMAND:		0..1	(2)
+ * CHAIN:		2	(1)
+ * IRQ:			3	(1)
+ * NAND_LOCK:		4	(1) - not implemented
+ * NAND_WAIT4READY:	5	(1) - not implemented
+ * DEC_SEM:		6	(1)
+ * WAIT4END:		7	(1)
+ * HALT_ON_TERMINATE:	8	(1)
+ * TERMINATE_FLUSH:	9	(1)
+ * RESERVED:		10..11	(2)
+ * PIO_NUM:		12..15	(4)
+ */
+#define BP_CCW_COMMAND		0
+#define BM_CCW_COMMAND		(3 << 0)
+#define CCW_CHAIN		(1 << 2)
+#define CCW_IRQ			(1 << 3)
+#define CCW_DEC_SEM		(1 << 6)
+#define CCW_WAIT4END		(1 << 7)
+#define CCW_HALT_ON_TERM	(1 << 8)
+#define CCW_TERM_FLUSH		(1 << 9)
+#define BP_CCW_PIO_NUM		12
+#define BM_CCW_PIO_NUM		(0xf << 12)
+
+#define BF_CCW(value, field)	(((value) << BP_CCW_##field) & BM_CCW_##field)
+
+#define MXS_DMA_CMD_NO_XFER	0
+#define MXS_DMA_CMD_WRITE	1
+#define MXS_DMA_CMD_READ	2
+#define MXS_DMA_CMD_DMA_SENSE	3	/* not implemented */
+
+struct mxs_dma_ccw {
+	u32		next;
+	u16		bits;
+	u16		xfer_bytes;
+#define MAX_XFER_BYTES	0xff00
+	u32		bufaddr;
+#define MXS_PIO_WORDS	16
+	u32		pio_words[MXS_PIO_WORDS];
+};
+
+#define NUM_CCW	(int)(PAGE_SIZE / sizeof(struct mxs_dma_ccw))
+
+struct mxs_dma_chan {
+	struct mxs_dma_engine		*mxs_dma;
+	struct dma_chan			chan;
+	struct dma_async_tx_descriptor	desc;
+	struct tasklet_struct		tasklet;
+	int				chan_irq;
+	struct mxs_dma_ccw		*ccw;
+	dma_addr_t			ccw_phys;
+	dma_cookie_t			last_completed;
+	enum dma_status			status;
+	unsigned int			flags;
+#define MXS_DMA_SG_LOOP			(1 << 0)
+};
+
+struct mxs_dma_engine {
+	int				dev_id;
+	unsigned int			version;
+	void __iomem			*base;
+	struct clk			*clk;
+	struct dma_device		dma_device;
+	struct device_dma_parameters	dma_parms;
+#define MXS_DMA_CHANNELS		16
+	struct mxs_dma_chan		mxs_chans[MXS_DMA_CHANNELS];
+};
+
+static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL),
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	else
+		writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
+}
+
+static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* set cmd_addr up */
+	writel(mxs_chan->ccw_phys,
+		mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
+
+	/* enable apbh channel clock */
+	if (dma_is_apbh()) {
+		if (apbh_is_old())
+			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+	}
+
+	/* write 1 to SEMA to kick off the channel */
+	writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
+}
+
+static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* disable apbh channel clock */
+	if (dma_is_apbh()) {
+		if (apbh_is_old())
+			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	}
+
+	mxs_chan->status = DMA_SUCCESS;
+}
+
+static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* freeze the channel */
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	else
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
+
+	mxs_chan->status = DMA_PAUSED;
+}
+
+static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* unfreeze the channel */
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+	else
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_CLR_ADDR);
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+}
+
+static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan)
+{
+	dma_cookie_t cookie = mxs_chan->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	mxs_chan->chan.cookie = cookie;
+	mxs_chan->desc.cookie = cookie;
+
+	return cookie;
+}
+
+static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct mxs_dma_chan, chan);
+}
+
+static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan);
+
+	mxs_dma_enable_chan(mxs_chan);
+
+	return mxs_dma_assign_cookie(mxs_chan);
+}
+
+static void mxs_dma_tasklet(unsigned long data)
+{
+	struct mxs_dma_chan *mxs_chan = (struct mxs_dma_chan *) data;
+
+        if (mxs_chan->desc.callback)
+                mxs_chan->desc.callback(mxs_chan->desc.callback_param);
+}
+
+static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
+{
+	struct mxs_dma_engine *mxs_dma = dev_id;
+	u32 stat1, stat2;
+
+	/* completion status */
+	stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1);
+	stat1 &= 0xffff;
+	writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + MXS_CLR_ADDR);
+
+	/* error status */
+	stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2);
+	writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + MXS_CLR_ADDR);
+
+	/*
+	 * When both completion and error of termination bits set at the
+	 * same time, we do not take it as an error.  IOW, it only becomes
+	 * an error we need to handler here in case of ether it's an bus
+	 * error or a termination error with no completion.
+	 */
+	stat2 = ((stat2 >> 16) & stat2) |	   /* bus error */
+		(~(stat2 >> 16) & stat2 & ~stat1); /* termination with no completion */
+
+	/* combine error and completion status for checking */
+	stat1 = (stat2 << 16) | stat1;
+	while (stat1) {
+		int channel = fls(stat1) - 1;
+		struct mxs_dma_chan *mxs_chan =
+				&mxs_dma->mxs_chans[channel % 16];
+
+		if (channel >= 16) {
+			dev_dbg(mxs_dma->dma_device.dev, "%s: error in channel %d\n",
+						__func__, channel - 16);
+			mxs_chan->status = DMA_ERROR;
+			mxs_dma_reset_chan(mxs_chan);
+		} else {
+			if (mxs_chan->flags & MXS_DMA_SG_LOOP)
+				mxs_chan->status = DMA_IN_PROGRESS;
+			else
+				mxs_chan->status = DMA_SUCCESS;
+		}
+
+		stat1 &= ~(1 << channel);
+
+		if (mxs_chan->status == DMA_SUCCESS)
+			mxs_chan->last_completed = mxs_chan->desc.cookie;
+
+		/* schedule tasklet on this channel */
+		tasklet_schedule(&mxs_chan->tasklet);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_data *data = chan->private;
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int ret;
+
+	if (!data)
+		return -EINVAL;
+
+	mxs_chan->chan_irq = data->chan_irq;
+
+	mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+				&mxs_chan->ccw_phys, GFP_KERNEL);
+	if (!mxs_chan->ccw) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	memset(mxs_chan->ccw, 0, PAGE_SIZE);
+
+	ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
+				0, "mxs-dma", mxs_dma);
+	if (ret)
+		goto err_irq;
+
+	ret = clk_enable(mxs_dma->clk);
+	if (ret)
+		goto err_clk;
+
+	mxs_dma_reset_chan(mxs_chan);
+
+	dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
+	mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
+
+	/* the descriptor is ready */
+	async_tx_ack(&mxs_chan->desc);
+
+	return 0;
+
+err_clk:
+	free_irq(mxs_chan->chan_irq, mxs_dma);
+err_irq:
+	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+			mxs_chan->ccw, mxs_chan->ccw_phys);
+err_alloc:
+	return ret;
+}
+
+static void mxs_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+
+	mxs_dma_disable_chan(mxs_chan);
+
+	free_irq(mxs_chan->chan_irq, mxs_dma);
+
+	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+			mxs_chan->ccw, mxs_chan->ccw_phys);
+
+	clk_disable(mxs_dma->clk);
+}
+
+static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
+		unsigned long append)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	struct mxs_dma_ccw *ccw;
+	struct scatterlist *sg;
+	int i, j;
+	u32 *pio;
+	static int idx = 0;
+
+	if (mxs_chan->status == DMA_IN_PROGRESS && !append)
+		return NULL;
+
+	if (sg_len + (append ? idx : 0) > NUM_CCW) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum number of sg exceeded: %d > %d\n",
+				sg_len, NUM_CCW);
+		goto err_out;
+	}
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+	mxs_chan->flags = 0;
+
+	/*
+	 * If the sg is prepared with append flag set, the sg
+	 * will be appended to the last prepared sg.
+	 */
+	if (append) {
+		BUG_ON(idx < 1);
+		ccw = &mxs_chan->ccw[idx - 1];
+		ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx;
+		ccw->bits |= CCW_CHAIN;
+		ccw->bits &= ~CCW_IRQ;
+		ccw->bits &= ~CCW_DEC_SEM;
+		ccw->bits &= ~CCW_WAIT4END;
+	} else {
+		idx = 0;
+	}
+
+	if (direction == DMA_NONE) {
+		ccw = &mxs_chan->ccw[idx++];
+		pio = (u32 *) sgl;
+
+		for (j = 0; j < sg_len;)
+			ccw->pio_words[j++] = *pio++;
+
+		ccw->bits = 0;
+		ccw->bits |= CCW_IRQ;
+		ccw->bits |= CCW_DEC_SEM;
+		ccw->bits |= CCW_WAIT4END;
+		ccw->bits |= CCW_HALT_ON_TERM;
+		ccw->bits |= CCW_TERM_FLUSH;
+		ccw->bits |= BF_CCW(sg_len, PIO_NUM);
+		ccw->bits |= BF_CCW(MXS_DMA_CMD_NO_XFER, COMMAND);
+	} else {
+		for_each_sg(sgl, sg, sg_len, i) {
+			if (sg->length > MAX_XFER_BYTES) {
+				dev_err(mxs_dma->dma_device.dev, "maximum bytes for sg entry exceeded: %d > %d\n",
+						sg->length, MAX_XFER_BYTES);
+				goto err_out;
+			}
+
+			ccw = &mxs_chan->ccw[idx++];
+
+			ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx;
+			ccw->bufaddr = sg->dma_address;
+			ccw->xfer_bytes = sg->length;
+
+			ccw->bits = 0;
+			ccw->bits |= CCW_CHAIN;
+			ccw->bits |= CCW_HALT_ON_TERM;
+			ccw->bits |= CCW_TERM_FLUSH;
+			ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+					MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ,
+					COMMAND);
+
+			if (i + 1 == sg_len) {
+				ccw->bits &= ~CCW_CHAIN;
+				ccw->bits |= CCW_IRQ;
+				ccw->bits |= CCW_DEC_SEM;
+				ccw->bits |= CCW_WAIT4END;
+			}
+		}
+	}
+
+	return &mxs_chan->desc;
+
+err_out:
+	mxs_chan->status = DMA_ERROR;
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
+		size_t period_len, enum dma_data_direction direction)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int num_periods = buf_len / period_len;
+	int i = 0, buf = 0;
+
+	if (mxs_chan->status == DMA_IN_PROGRESS)
+		return NULL;
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+	mxs_chan->flags |= MXS_DMA_SG_LOOP;
+
+	if (num_periods > NUM_CCW) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum number of sg exceeded: %d > %d\n",
+				num_periods, NUM_CCW);
+		goto err_out;
+	}
+
+	if (period_len > MAX_XFER_BYTES) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum period size exceeded: %d > %d\n",
+				period_len, MAX_XFER_BYTES);
+		goto err_out;
+	}
+
+	while (buf < buf_len) {
+		struct mxs_dma_ccw *ccw = &mxs_chan->ccw[i];
+
+		if (i + 1 == num_periods)
+			ccw->next = mxs_chan->ccw_phys;
+		else
+			ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * (i + 1);
+
+		ccw->bufaddr = dma_addr;
+		ccw->xfer_bytes = period_len;
+
+		ccw->bits = 0;
+		ccw->bits |= CCW_CHAIN;
+		ccw->bits |= CCW_IRQ;
+		ccw->bits |= CCW_HALT_ON_TERM;
+		ccw->bits |= CCW_TERM_FLUSH;
+		ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+				MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND);
+
+		dma_addr += period_len;
+		buf += period_len;
+
+		i++;
+	}
+
+	return &mxs_chan->desc;
+
+err_out:
+	mxs_chan->status = DMA_ERROR;
+	return NULL;
+}
+
+static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+		unsigned long arg)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	int ret = 0;
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		mxs_dma_disable_chan(mxs_chan);
+		break;
+	case DMA_PAUSE:
+		mxs_dma_pause_chan(mxs_chan);
+		break;
+	case DMA_RESUME:
+		mxs_dma_resume_chan(mxs_chan);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	return ret;
+}
+
+static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
+			dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	dma_cookie_t last_used;
+
+	last_used = chan->cookie;
+	dma_set_tx_state(txstate, mxs_chan->last_completed, last_used, 0);
+
+	return mxs_chan->status;
+}
+
+static void mxs_dma_issue_pending(struct dma_chan *chan)
+{
+	/*
+	 * Nothing to do. We only have a single descriptor.
+	 */
+}
+
+static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
+{
+	int ret;
+
+	ret = clk_enable(mxs_dma->clk);
+	if (ret)
+		goto err_out;
+
+	ret = mxs_reset_block(mxs_dma->base);
+	if (ret)
+		goto err_out;
+
+	/* only major version matters */
+	mxs_dma->version = readl(mxs_dma->base +
+				((mxs_dma->dev_id == MXS_DMA_APBX) ?
+				HW_APBX_VERSION : HW_APBH_VERSION)) >>
+				BP_APBHX_VERSION_MAJOR;
+
+	/* enable apbh burst */
+	if (dma_is_apbh()) {
+		writel(BM_APBH_CTRL0_APB_BURST_EN,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+		writel(BM_APBH_CTRL0_APB_BURST8_EN,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	}
+
+	/* enable irq for all the channels */
+	writel(0xffff << 16, mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR);
+
+	clk_disable(mxs_dma->clk);
+
+	return 0;
+
+err_out:
+	return ret;
+}
+
+static int __init mxs_dma_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(pdev);
+	struct mxs_dma_engine *mxs_dma;
+	struct resource *iores;
+	int ret, i;
+
+	mxs_dma = kzalloc(sizeof(*mxs_dma), GFP_KERNEL);
+	if (!mxs_dma)
+		return -ENOMEM;
+
+	mxs_dma->dev_id = id_entry->driver_data;
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!request_mem_region(iores->start, resource_size(iores),
+				pdev->name)) {
+		ret = -EBUSY;
+		goto err_request_region;
+	}
+
+	mxs_dma->base = ioremap(iores->start, resource_size(iores));
+	if (!mxs_dma->base) {
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	mxs_dma->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mxs_dma->clk)) {
+		ret = PTR_ERR(mxs_dma->clk);
+		goto err_clk;
+	}
+
+	dma_cap_set(DMA_SLAVE, mxs_dma->dma_device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, mxs_dma->dma_device.cap_mask);
+
+	INIT_LIST_HEAD(&mxs_dma->dma_device.channels);
+
+	/* Initialize channel parameters */
+	for (i = 0; i < MXS_DMA_CHANNELS; i++) {
+		struct mxs_dma_chan *mxs_chan = &mxs_dma->mxs_chans[i];
+
+		mxs_chan->mxs_dma = mxs_dma;
+		mxs_chan->chan.device = &mxs_dma->dma_device;
+
+		tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet,
+			     (unsigned long) mxs_chan);
+
+
+		/* Add the channel to mxs_chan list */
+		list_add_tail(&mxs_chan->chan.device_node, &mxs_dma->dma_device.channels);
+	}
+
+	ret = mxs_dma_init(mxs_dma);
+	if (ret)
+		goto err_init;
+
+	mxs_dma->dma_device.dev = &pdev->dev;
+
+	/* mxs_dma gets 65535 bytes maximum sg size */
+	mxs_dma->dma_device.dev->dma_parms = &mxs_dma->dma_parms;
+	dma_set_max_seg_size(mxs_dma->dma_device.dev, MAX_XFER_BYTES);
+
+	mxs_dma->dma_device.device_alloc_chan_resources = mxs_dma_alloc_chan_resources;
+	mxs_dma->dma_device.device_free_chan_resources = mxs_dma_free_chan_resources;
+	mxs_dma->dma_device.device_tx_status = mxs_dma_tx_status;
+	mxs_dma->dma_device.device_prep_slave_sg = mxs_dma_prep_slave_sg;
+	mxs_dma->dma_device.device_prep_dma_cyclic = mxs_dma_prep_dma_cyclic;
+	mxs_dma->dma_device.device_control = mxs_dma_control;
+	mxs_dma->dma_device.device_issue_pending = mxs_dma_issue_pending;
+
+	ret = dma_async_device_register(&mxs_dma->dma_device);
+	if (ret) {
+		dev_err(mxs_dma->dma_device.dev, "unable to register\n");
+		goto err_init;
+	}
+
+	dev_info(mxs_dma->dma_device.dev, "initialized\n");
+
+	return 0;
+
+err_init:
+	clk_put(mxs_dma->clk);
+err_clk:
+	iounmap(mxs_dma->base);
+err_ioremap:
+	release_mem_region(iores->start, resource_size(iores));
+err_request_region:
+	kfree(mxs_dma);
+	return ret;
+}
+
+static struct platform_device_id mxs_dma_type[] = {
+	{
+		.name = "mxs-dma-apbh",
+		.driver_data = MXS_DMA_APBH,
+	}, {
+		.name = "mxs-dma-apbx",
+		.driver_data = MXS_DMA_APBX,
+	}
+};
+
+static struct platform_driver mxs_dma_driver = {
+	.driver		= {
+		.name	= "mxs-dma",
+	},
+	.id_table	= mxs_dma_type,
+};
+
+static int __init mxs_dma_module_init(void)
+{
+	return platform_driver_probe(&mxs_dma_driver, mxs_dma_probe);
+}
+subsys_initcall(mxs_dma_module_init);
-- 
1.7.1

^ permalink raw reply related

* [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
From: Santosh Shilimkar @ 2011-02-21 10:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTik-hj+-ZPnfVKLCH0h-QeyziH4H-j6EE+_QHHCU@mail.gmail.com>

> -----Original Message-----
> From: Jean Pihet [mailto:jean.pihet at newoldbits.com]
> Sent: Monday, February 21, 2011 3:49 PM
> To: Santosh Shilimkar
> Cc: linux-omap at vger.kernel.org; khilman at ti.com; linux-arm-
> kernel at lists.infradead.org; Rajendra Nayak
> Subject: Re: [PATCH 14/17] omap4: cpuidle: Add MPUSS RET OFF states
>
> Hi Santosh,
>
[...]

>
> > + * cpuidle CORE retention support.
> > + * Currently only MPUSS latency numbers are added based on
> > + * measurements done internally. The numbers for MPUSS are
> > + * not board dependent and hence set directly here instead of
> > + * passing it from board files.
> > + */
> > ?static struct cpuidle_params cpuidle_params_table[] = {
> > - ? ? ? /* C1 */
> > - ? ? ? {1, 2, 2, 5},
> > + ? ? ? /* C1 - CPU0 WFI + CPU1 ON/OFF + MPU ON ? + CORE ON */
> > + ? ? ? {1, ? ? 2, ? ? ?2, ? ? ?5},
> > + ? ? ? /* C2 - CPU0 ON + CPU1 OFF + MPU ON ?+ CORE ON */
> > + ? ? ? {1, ? ? 140, ? ?160, ? ?300},
> > + ? ? ? /* C3 - CPU0 OFF + CPU1 OFF + MPU CSWR + CORE ON */
> > + ? ? ? {1, ? ? 200, ? ?300, ? ?700},
> > + ? ? ? /* C4 - CPU0 OFF + CPU1 OFF + MPU OFF + CORE ON */
> > + ? ? ? {1, ? ? 1400, ? 600, ? ?5000},
> > ?};
> >
> > +DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev);
> > +
> > +static int omap4_idle_bm_check(void)
> > +{
> > + ? ? ? /* FIXME: Populate this with CORE retention support */
> > + ? ? ? return 0;
> > +}
> > +
> > ?/**
> > ?* omap4_enter_idle - Programs OMAP4 to enter the specified state
> > ?* @dev: cpuidle device
> > @@ -57,7 +92,9 @@ static struct cpuidle_params
> cpuidle_params_table[] = {
> > ?static int omap4_enter_idle(struct cpuidle_device *dev,
> > ? ? ? ? ? ? ? ? ? ? ? ?struct cpuidle_state *state)
> > ?{
> > + ? ? ? struct omap4_processor_cx *cx =
> cpuidle_get_statedata(state);
> > ? ? ? ?struct timespec ts_preidle, ts_postidle, ts_idle;
> > + ? ? ? u32 cpu1_state;
> >
> > ? ? ? ?/* Used to keep track of the total time in idle */
> > ? ? ? ?getnstimeofday(&ts_preidle);
> > @@ -65,28 +102,74 @@ static int omap4_enter_idle(struct
> cpuidle_device *dev,
> > ? ? ? ?local_irq_disable();
> > ? ? ? ?local_fiq_disable();
> >
> > - ? ? ? cpu_do_idle();
>
> I think the piece of code below is rather difficult to read and
> understand. Based on the patch description and the comment here
> below
> I do not see the relation with the code.
>
There is relation. The comments are as per the conditions. And
The hardware constraint is back-ground behind the conditions.

> " On OMAP4 because of hardware constraints, no low power states are
>  targeted when both CPUs are online and in SMP mode. The low power
>  states are attempted only when secondary CPU gets offline to OFF
>  through hotplug infrastructure. "
> The test below does not seem to match this comment.
>
> > + ? ? ? /*
> > + ? ? ? ?* Special hardware/software considerations:
> > + ? ? ? ?* 1. Do only WFI for secondary CPU(non-boot - CPU1).
> > + ? ? ? ?* ? ?Secondary cores are taken down only via hotplug
> path.
> The comment looks contradictory. Which one is taken OFF using this
> code, which one from hotplug?
> Does this correspond to the condition '(dev->cpu)' in the test
> below?

Yes.
>
> > + ? ? ? ?* 2. Do only a WFI as long as in SMP mode.
> Does this correspond to the condition '(num_online_cpus() > 1)' in
> the
> test below? If so it this one triggering the low power mode for
> cpu0?
yes
>
> > + ? ? ? ?* 3. Continue to do only WFI till CPU1 hits OFF state.
> > + ? ? ? ?* ? ?This is necessary to honour hardware recommondation
> > + ? ? ? ?* ? ?of triggeing all the possible low power modes once
> CPU1 is
> > + ? ? ? ?* ? ?out of coherency and in OFF mode.
> Does this correspond to the condition '(cpu1_state !=
> PWRDM_POWER_OFF)' in the test below?
>
Yes

> > + ? ? ? ?* Update dev->last_state so that governor stats reflects
> right
> > + ? ? ? ?* data.
> > + ? ? ? ?*/
> > + ? ? ? cpu1_state = pwrdm_read_pwrst(cpu1_pd);
> > + ? ? ? if ((dev->cpu) || (num_online_cpus() > 1) ||
> > + ? ? ? ? ? ? ? ? ? ? ? (cpu1_state != PWRDM_POWER_OFF)) {
> Are '||' correct here?
Yes.

> Sorry if the code behaves correctly, the remarks are about
> readability especially in the comments.
>
You got all three correct. Instead of having three If's doing
same thing I have merged them and added comments above.

And you got all of them correctly.

Regards,
Santosh

^ permalink raw reply

* [RFC PATCH 2/2] ARMv7: Invalidate the TLB before freeing page tables
From: Russell King - ARM Linux @ 2011-02-21 10:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTimpcQCjnfzT0R+Af+f38RwBg6DUBg_b85opJJnh@mail.gmail.com>

On Mon, Feb 21, 2011 at 09:39:32AM +0000, Catalin Marinas wrote:
> On 20 February 2011 12:12, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
> > On Tue, Feb 15, 2011 at 02:42:06PM +0000, Catalin Marinas wrote:
> >> On Tue, 2011-02-15 at 12:14 +0000, Russell King - ARM Linux wrote:
> >> > On Tue, Feb 15, 2011 at 11:32:42AM +0000, Russell King - ARM Linux wrote:
> >> > > The point of TLB shootdown is that we unmap the entries from the page
> >> > > tables, then issue the TLB flushes, and then free the pages and page
> >> > > tables after that. ?All that Peter's patch tries to do is to get ARM to
> >> > > use the generic stuff.
> >> >
> >> > As Peter's patch preserves the current behaviour, that's not sufficient.
> >> > So, let's do this our own way and delay pages and page table frees on
> >> > ARMv6 and v7. ?Untested.
> >>
> >> ARMv7 should be enough, I'm not aware of any pre-v7 with this behaviour.
> >
> > ARM11MPCore. ?Any SMP system can access a page which was free'd by the
> > tlb code but hasn't been flushed from the hardware TLBs. ?So maybe we
> > want it to be "defined(CONFIG_SMP) || defined(CONFIG_CPU_32v7)" ?
> 
> In practice, since the hardware TLB does not store higher level
> entries on existing v6 cores, there is no cached value pointing to the
> freed pte page.

It's not about cached values of PTE pointers.

> In theory, we first clear the pmd entry but another
> CPU could be doing a PTW at the same time and had already read the pmd
> before being cleared. But the timing constraints are difficult to
> reproduce in practice.

I don't think you properly understand the problem.

CPU#0 is unmapping page tables, eg due to munmap(), mremap(), etc.
CPU#1 is running a thread, and has TLB entries for the region being unmapped.

	CPU#0				CPU#1
	clear page table entry
	frees page
	loop continues
					accesses page
	...
	sometime in the future
	invalidates TLB

The point here is that user threads on CPU#1 should not have access to
a page which has been freed back into the pool, no matter how slim the
possibility of hitting such a condition.  What if a thread on CPU#2 is
given that free page which CPU#1 still has access to, and CPU#2 stores
your SSH private key there?

^ permalink raw reply

* [PATCH v3 0/2] Add dma device for i.MX23/28
From: Shawn Guo @ 2011-02-21 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sascha,

These two patches have no change since v2, and I re-post them to let
you pick them up easily.

Regards,
Shawn

^ permalink raw reply

* [PATCH v3 1/2] ARM: mxs: add dma channel definitions
From: Shawn Guo @ 2011-02-21 10:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284306-14710-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/include/mach/mx23.h |   24 +++++++++++++++++++++
 arch/arm/mach-mxs/include/mach/mx28.h |   37 +++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-mxs/include/mach/mx23.h b/arch/arm/mach-mxs/include/mach/mx23.h
index 9edd02e..1730c9c 100644
--- a/arch/arm/mach-mxs/include/mach/mx23.h
+++ b/arch/arm/mach-mxs/include/mach/mx23.h
@@ -142,4 +142,28 @@
 #define MX23_INT_VDD5V_DROOP		64
 #define MX23_INT_DCDC4P2_BO		65
 
+/*
+ * APBH DMA
+ */
+#define MX23_DMA_SSP1			1
+#define MX23_DMA_SSP2			2
+#define MX23_DMA_GPMI0			4
+#define MX23_DMA_GPMI1			5
+#define MX23_DMA_GPMI2			6
+#define MX23_DMA_GPMI3			7
+
+/*
+ * APBX DMA
+ */
+#define MX23_DMA_ADC			0
+#define MX23_DMA_DAC			1
+#define MX23_DMA_SPDIF			2
+#define MX23_DMA_I2C			3
+#define MX23_DMA_SAIF0			4
+#define MX23_DMA_UART0_RX		6
+#define MX23_DMA_UART0_TX		7
+#define MX23_DMA_UART1_RX		8
+#define MX23_DMA_UART1_TX		9
+#define MX23_DMA_SAIF1			10
+
 #endif /* __MACH_MX23_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/mx28.h b/arch/arm/mach-mxs/include/mach/mx28.h
index 0716745..3f3485a 100644
--- a/arch/arm/mach-mxs/include/mach/mx28.h
+++ b/arch/arm/mach-mxs/include/mach/mx28.h
@@ -185,4 +185,41 @@
 #define MX28_INT_GPIO1			126
 #define MX28_INT_GPIO0			127
 
+/*
+ * APBH DMA
+ */
+#define MX28_DMA_SSP0			0
+#define MX28_DMA_SSP1			1
+#define MX28_DMA_SSP2			2
+#define MX28_DMA_SSP3			3
+#define MX28_DMA_GPMI0			4
+#define MX28_DMA_GPMI1			5
+#define MX28_DMA_GPMI2			6
+#define MX28_DMA_GPMI3			7
+#define MX28_DMA_GPMI4			8
+#define MX28_DMA_GPMI5			9
+#define MX28_DMA_GPMI6			10
+#define MX28_DMA_GPMI7			11
+#define MX28_DMA_HSADC			12
+#define MX28_DMA_LCDIF			13
+
+/*
+ * APBX DMA
+ */
+#define MX28_DMA_AUART4_RX		0
+#define MX28_DMA_AUART4_TX		1
+#define MX28_DMA_SPDIF_TX		2
+#define MX28_DMA_SAIF0			4
+#define MX28_DMA_SAIF1			5
+#define MX28_DMA_I2C0			6
+#define MX28_DMA_I2C1			7
+#define MX28_DMA_AUART0_RX		8
+#define MX28_DMA_AUART0_TX		9
+#define MX28_DMA_AUART1_RX		10
+#define MX28_DMA_AUART1_TX		11
+#define MX28_DMA_AUART2_RX		12
+#define MX28_DMA_AUART2_TX		13
+#define MX28_DMA_AUART3_RX		14
+#define MX28_DMA_AUART3_TX		15
+
 #endif /* __MACH_MX28_H__ */
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3 2/2] ARM: mxs: add dma device
From: Shawn Guo @ 2011-02-21 10:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284306-14710-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/clock-mx23.c           |    3 +-
 arch/arm/mach-mxs/clock-mx28.c           |    4 +-
 arch/arm/mach-mxs/devices/Makefile       |    1 +
 arch/arm/mach-mxs/devices/platform-dma.c |  101 ++++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-dma.c

diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
index b1a362e..350b28c 100644
--- a/arch/arm/mach-mxs/clock-mx23.c
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -443,7 +443,8 @@ static struct clk_lookup lookups[] = {
 	/* for amba-pl011 driver */
 	_REGISTER_CLOCK("duart", NULL, uart_clk)
 	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
-	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
 	_REGISTER_CLOCK(NULL, "usb", usb_clk)
 	_REGISTER_CLOCK(NULL, "audio", audio_clk)
 	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index c9d7951..a3b4787 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -617,8 +617,8 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
 	_REGISTER_CLOCK("pll2", NULL, pll2_clk)
-	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
-	_REGISTER_CLOCK(NULL, "xclk", xbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can0_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can1_clk)
 	_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index a8dc8d5..ca7acc4 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_MXS_HAVE_AMBA_DUART) += amba-duart.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
+obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c
new file mode 100644
index 0000000..ee3220e
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-dma.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+struct mxs_mxs_dma_data {
+	const char *devid;
+	resource_size_t iobase;
+};
+
+#define mxs_dma_data_entry_single(soc, type, _devid)			\
+	{								\
+		.devid = _devid,					\
+		.iobase = soc ## _ ## type ## _DMA ## _BASE_ADDR,	\
+	}
+
+#ifdef CONFIG_SOC_IMX23
+struct mxs_mxs_dma_data mx23_dma_data[] __initconst = {
+	mxs_dma_data_entry_single(MX23, APBH, "mxs-dma-apbh"),
+	mxs_dma_data_entry_single(MX23, APBX, "mxs-dma-apbx"),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+struct mxs_mxs_dma_data mx28_dma_data[] __initconst = {
+	mxs_dma_data_entry_single(MX28, APBH, "mxs-dma-apbh"),
+	mxs_dma_data_entry_single(MX28, APBX, "mxs-dma-apbx"),
+};
+#endif
+
+struct platform_device *__init mxs_add_dma(
+			const struct mxs_mxs_dma_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}
+	};
+
+	return mxs_add_platform_device_dmamask(data->devid, -1,
+				res, ARRAY_SIZE(res), NULL, 0,
+				DMA_BIT_MASK(32));
+}
+
+#define mx23_add_apbh_dma() \
+	mxs_add_dma(&mx23_dma_data[0])
+#define mx23_add_apbx_dma() \
+	mxs_add_dma(&mx23_dma_data[1])
+
+#define mx28_add_apbh_dma() \
+	mxs_add_dma(&mx28_dma_data[0])
+#define mx28_add_apbx_dma() \
+	mxs_add_dma(&mx28_dma_data[1])
+
+static int __init mxs_add_mxs_dma(void)
+{
+	struct platform_device *ret;
+
+#ifdef CONFIG_SOC_IMX23
+	if (cpu_is_mx23()) {
+		ret = mx23_add_apbh_dma();
+		if (IS_ERR(ret))
+			goto out;
+
+		ret = mx23_add_apbx_dma();
+	} else
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+	if (cpu_is_mx28()) {
+		ret = mx28_add_apbh_dma();
+		if (IS_ERR(ret))
+			goto out;
+
+		ret = mx28_add_apbx_dma();
+	} else
+#endif
+		ret = ERR_PTR(-ENODEV);
+
+out:
+	if (IS_ERR(ret))
+		return PTR_ERR(ret);
+	else
+		return 0;
+}
+arch_initcall(mxs_add_mxs_dma);
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3] mmc: mxs-mmc: add mmc host driver for i.MX23/28
From: Shawn Guo @ 2011-02-21 10:35 UTC (permalink / raw)
  To: linux-arm-kernel

This adds the mmc host driver for Freescale MXS-based SoC i.MX23/28.
The driver calls into mxs-dma via generic dmaengine api for both pio
and data transfer.

Thanks Chris Ball for the indentation patch.

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/arm/mach-mxs/include/mach/mmc.h |   18 +
 drivers/mmc/host/Kconfig             |    9 +
 drivers/mmc/host/Makefile            |    1 +
 drivers/mmc/host/mxs-mmc.c           |  874 ++++++++++++++++++++++++++++++++++
 4 files changed, 902 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/include/mach/mmc.h
 create mode 100644 drivers/mmc/host/mxs-mmc.c

diff --git a/arch/arm/mach-mxs/include/mach/mmc.h b/arch/arm/mach-mxs/include/mach/mmc.h
new file mode 100644
index 0000000..211547a
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/mmc.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 __MACH_MXS_MMC_H__
+#define __MACH_MXS_MMC_H__
+
+struct mxs_mmc_platform_data {
+	int wp_gpio;	/* write protect pin */
+	unsigned int flags;
+#define SLOTF_4_BIT_CAPABLE	(1 << 0)
+#define SLOTF_8_BIT_CAPABLE	(1 << 1)
+};
+#endif /* __MACH_MXS_MMC_H__ */
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index afe8c6f..47ef75d 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -319,6 +319,15 @@ config MMC_MXC
 
 	  If unsure, say N.
 
+config MMC_MXS
+	tristate "Freescale MXS Multimedia Card Interface support"
+	depends on ARCH_MXS && MXS_DMA
+	help
+	  This selects the Freescale SSP MMC controller found on MXS based
+	  platforms like mx23/28.
+
+	  If unsure, say N.
+
 config MMC_TIFM_SD
 	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index e834fb2..30aa686 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
 obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
 obj-$(CONFIG_MMC_MXC)		+= mxcmmc.o
+obj-$(CONFIG_MMC_MXS)		+= mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
 obj-$(CONFIG_MMC_SDHCI_PXA)	+= sdhci-pxa.o
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
new file mode 100644
index 0000000..99d39a6
--- /dev/null
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -0,0 +1,874 @@
+/*
+ * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
+ * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/highmem.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/mxs.h>
+#include <mach/common.h>
+#include <mach/dma.h>
+#include <mach/mmc.h>
+
+#define DRIVER_NAME	"mxs-mmc"
+
+/* card detect polling timeout */
+#define MXS_MMC_DETECT_TIMEOUT			(HZ/2)
+
+#define SSP_VERSION_LATEST	4
+#define ssp_is_old()		(host->version < SSP_VERSION_LATEST)
+
+/* SSP registers */
+#define HW_SSP_CTRL0				0x000
+#define  BM_SSP_CTRL0_RUN			(1 << 29)
+#define  BM_SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define  BM_SSP_CTRL0_IGNORE_CRC		(1 << 26)
+#define  BM_SSP_CTRL0_READ			(1 << 25)
+#define  BM_SSP_CTRL0_DATA_XFER			(1 << 24)
+#define  BP_SSP_CTRL0_BUS_WIDTH			(22)
+#define  BM_SSP_CTRL0_BUS_WIDTH			(0x3 << 22)
+#define  BM_SSP_CTRL0_WAIT_FOR_IRQ		(1 << 21)
+#define  BM_SSP_CTRL0_LONG_RESP			(1 << 19)
+#define  BM_SSP_CTRL0_GET_RESP			(1 << 17)
+#define  BM_SSP_CTRL0_ENABLE			(1 << 16)
+#define  BP_SSP_CTRL0_XFER_COUNT		(0)
+#define  BM_SSP_CTRL0_XFER_COUNT		(0xffff)
+#define HW_SSP_CMD0				0x010
+#define  BM_SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define  BM_SSP_CMD0_SLOW_CLKING_EN		(1 << 22)
+#define  BM_SSP_CMD0_CONT_CLKING_EN		(1 << 21)
+#define  BM_SSP_CMD0_APPEND_8CYC		(1 << 20)
+#define  BP_SSP_CMD0_BLOCK_SIZE			(16)
+#define  BM_SSP_CMD0_BLOCK_SIZE			(0xf << 16)
+#define  BP_SSP_CMD0_BLOCK_COUNT		(8)
+#define  BM_SSP_CMD0_BLOCK_COUNT		(0xff << 8)
+#define  BP_SSP_CMD0_CMD			(0)
+#define  BM_SSP_CMD0_CMD			(0xff)
+#define HW_SSP_CMD1				0x020
+#define HW_SSP_XFER_SIZE			0x030
+#define HW_SSP_BLOCK_SIZE			0x040
+#define  BP_SSP_BLOCK_SIZE_BLOCK_COUNT		(4)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_COUNT		(0xffffff << 4)
+#define  BP_SSP_BLOCK_SIZE_BLOCK_SIZE		(0)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_SIZE		(0xf)
+#define HW_SSP_TIMING				(ssp_is_old() ? 0x050 : 0x070)
+#define  BP_SSP_TIMING_TIMEOUT			(16)
+#define  BM_SSP_TIMING_TIMEOUT			(0xffff << 16)
+#define  BP_SSP_TIMING_CLOCK_DIVIDE		(8)
+#define  BM_SSP_TIMING_CLOCK_DIVIDE		(0xff << 8)
+#define  BP_SSP_TIMING_CLOCK_RATE		(0)
+#define  BM_SSP_TIMING_CLOCK_RATE		(0xff)
+#define HW_SSP_CTRL1				(ssp_is_old() ? 0x060 : 0x080)
+#define  BM_SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define  BM_SSP_CTRL1_SDIO_IRQ_EN		(1 << 30)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ		(1 << 29)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN	(1 << 26)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN	(1 << 24)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ		(1 << 23)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN	(1 << 20)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN	(1 << 16)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN	(1 << 14)
+#define  BM_SSP_CTRL1_DMA_ENABLE		(1 << 13)
+#define  BM_SSP_CTRL1_POLARITY			(1 << 9)
+#define  BP_SSP_CTRL1_WORD_LENGTH		(4)
+#define  BM_SSP_CTRL1_WORD_LENGTH		(0xf << 4)
+#define  BP_SSP_CTRL1_SSP_MODE			(0)
+#define  BM_SSP_CTRL1_SSP_MODE			(0xf)
+#define HW_SSP_SDRESP0				(ssp_is_old() ? 0x080 : 0x0a0)
+#define HW_SSP_SDRESP1				(ssp_is_old() ? 0x090 : 0x0b0)
+#define HW_SSP_SDRESP2				(ssp_is_old() ? 0x0a0 : 0x0c0)
+#define HW_SSP_SDRESP3				(ssp_is_old() ? 0x0b0 : 0x0d0)
+#define HW_SSP_STATUS				(ssp_is_old() ? 0x0c0 : 0x100)
+#define  BM_SSP_STATUS_CARD_DETECT		(1 << 28)
+#define  BM_SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define HW_SSP_VERSION				(cpu_is_mx23() ? 0x110 : 0x130)
+#define  BP_SSP_VERSION_MAJOR			(24)
+
+#define BF_SSP(value, field)	(((value) << BP_SSP_##field) & BM_SSP_##field)
+
+#define MXS_MMC_IRQ_BITS	(BM_SSP_CTRL1_SDIO_IRQ		| \
+				 BM_SSP_CTRL1_RESP_ERR_IRQ	| \
+				 BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	| \
+				 BM_SSP_CTRL1_DATA_TIMEOUT_IRQ	| \
+				 BM_SSP_CTRL1_DATA_CRC_IRQ	| \
+				 BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ	| \
+				 BM_SSP_CTRL1_RECV_TIMEOUT_IRQ  | \
+				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
+
+#define SSP_PIO_NUM	3
+
+struct mxs_mmc_host {
+	struct mmc_host			*mmc;
+	struct mmc_request		*mrq;
+	struct mmc_command		*cmd;
+	struct mmc_data			*data;
+
+	void __iomem			*base;
+	int				irq;
+	struct resource			*res;
+	struct resource			*dma_res;
+	struct clk			*clk;
+	unsigned int			clk_rate;
+
+	struct dma_chan         	*dmach;
+	struct mxs_dma_data		dma_data;
+	unsigned int			dma_dir;
+	u32				ssp_pio_words[SSP_PIO_NUM];
+
+	unsigned int			version;
+	unsigned char			bus_width;
+	spinlock_t			lock;
+	int				sdio_irq_en;
+};
+
+static int mxs_mmc_get_ro(struct mmc_host *mmc)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_mmc_platform_data *pdata =
+		mmc_dev(host->mmc)->platform_data;
+
+	if (!pdata)
+		return -EFAULT;
+
+	if (!gpio_is_valid(pdata->wp_gpio))
+		return -EINVAL;
+
+	return gpio_get_value(pdata->wp_gpio);
+}
+
+static int mxs_mmc_get_cd(struct mmc_host *mmc)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	return !(readl(host->base + HW_SSP_STATUS) &
+		 BM_SSP_STATUS_CARD_DETECT);
+}
+
+static void mxs_mmc_reset(struct mxs_mmc_host *host)
+{
+	u32 ctrl0, ctrl1;
+
+	mxs_reset_block(host->base);
+
+	ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
+	ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
+		BF_SSP(0x7, CTRL1_WORD_LENGTH) |
+		BM_SSP_CTRL1_DMA_ENABLE |
+		BM_SSP_CTRL1_POLARITY |
+		BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
+		BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
+
+	writel(BF_SSP(0xffff, TIMING_TIMEOUT) |
+	       BF_SSP(2, TIMING_CLOCK_DIVIDE) |
+	       BF_SSP(0, TIMING_CLOCK_RATE),
+	       host->base + HW_SSP_TIMING);
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN;
+	}
+
+	writel(ctrl0, host->base + HW_SSP_CTRL0);
+	writel(ctrl1, host->base + HW_SSP_CTRL1);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+			      struct mmc_command *cmd);
+
+static void mxs_mmc_request_done(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = host->data;
+	struct mmc_request *mrq = host->mrq;
+
+	if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
+		if (mmc_resp_type(cmd) & MMC_RSP_136) {
+			cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0);
+			cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1);
+			cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2);
+			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3);
+		} else {
+			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0);
+		}
+	}
+
+	if (data) {
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+			     data->sg_len, host->dma_dir);
+		/*
+		 * If there was an error on any block, we mark all
+		 * data blocks as being in error.
+		 */
+		if (!data->error)
+			data->bytes_xfered = data->blocks * data->blksz;
+		else
+			data->bytes_xfered = 0;
+
+		host->data = NULL;
+		if (mrq->stop) {
+			mxs_mmc_start_cmd(host, mrq->stop);
+			return;
+		}
+	}
+
+	host->mrq = NULL;
+	mmc_request_done(host->mmc, mrq);
+}
+
+static void mxs_mmc_dma_irq_callback(void *param)
+{
+	struct mxs_mmc_host *host = param;
+
+	mxs_mmc_request_done(host);
+}
+
+static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
+{
+	struct mxs_mmc_host *host = dev_id;
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = host->data;
+	u32 stat;
+
+	spin_lock(&host->lock);
+
+	stat = readl(host->base + HW_SSP_CTRL1);
+	writel(stat & MXS_MMC_IRQ_BITS,
+	       host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+
+	if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
+		mmc_signal_sdio_irq(host->mmc);
+
+	spin_unlock(&host->lock);
+
+	if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
+		cmd->error = -ETIMEDOUT;
+	else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
+		cmd->error = -EIO;
+
+	if (data) {
+		if (stat & (BM_SSP_CTRL1_DATA_TIMEOUT_IRQ |
+			    BM_SSP_CTRL1_RECV_TIMEOUT_IRQ))
+			data->error = -ETIMEDOUT;
+		else if (stat & BM_SSP_CTRL1_DATA_CRC_IRQ)
+			data->error = -EILSEQ;
+		else if (stat & (BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ |
+				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ))
+			data->error = -EIO;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
+	struct mxs_mmc_host *host, unsigned int append)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct mmc_data *data = host->data;
+	struct scatterlist * sgl;
+	unsigned int sg_len;
+
+	if (data) {
+		/* data */
+		dma_map_sg(mmc_dev(host->mmc), data->sg,
+			   data->sg_len, host->dma_dir);
+		sgl = data->sg;
+		sg_len = data->sg_len;
+	} else {
+		/* pio */
+		sgl = (struct scatterlist *) host->ssp_pio_words;
+		sg_len = SSP_PIO_NUM;
+	}
+
+	desc = host->dmach->device->device_prep_slave_sg(host->dmach,
+				sgl, sg_len, host->dma_dir, append);
+	if (desc) {
+		desc->callback = mxs_mmc_dma_irq_callback;
+		desc->callback_param = host;
+	} else {
+		if (data)
+			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+				     data->sg_len, host->dma_dir);
+	}
+
+	return desc;
+}
+
+static void mxs_mmc_bc(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct dma_async_tx_descriptor *desc;
+	u32 ctrl0, cmd0, cmd1;
+
+	ctrl0 = BM_SSP_CTRL0_ENABLE | BM_SSP_CTRL0_IGNORE_CRC;
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD) | BM_SSP_CMD0_APPEND_8CYC;
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_ac(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct dma_async_tx_descriptor *desc;
+	u32 ignore_crc, get_resp, long_resp;
+	u32 ctrl0, cmd0, cmd1;
+
+	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+			0 : BM_SSP_CTRL0_IGNORE_CRC;
+	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+			BM_SSP_CTRL0_GET_RESP : 0;
+	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+			BM_SSP_CTRL0_LONG_RESP : 0;
+
+	ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | get_resp | long_resp;
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static unsigned short mxs_ns_to_ssp_ticks(unsigned clock_rate, unsigned ns)
+{
+	const unsigned int ssp_timeout_mul = 4096;
+	/*
+	 * Calculate ticks in ms since ns are large numbers
+	 * and might overflow
+	 */
+	const unsigned int clock_per_ms = clock_rate / 1000;
+	const unsigned int ms = ns / 1000;
+	const unsigned int ticks = ms * clock_per_ms;
+	const unsigned int ssp_ticks = ticks / ssp_timeout_mul;
+
+	WARN_ON(ssp_ticks == 0);
+	return ssp_ticks;
+}
+
+static void mxs_mmc_adtc(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = cmd->data;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sgl = data->sg, *sg;
+	unsigned int sg_len = data->sg_len;
+	int i;
+
+	unsigned short dma_data_dir, timeout;
+	unsigned int data_size = 0, log2_blksz;
+	unsigned int blocks = data->blocks;
+
+	u32 ignore_crc, get_resp, long_resp, read;
+	u32 ctrl0, cmd0, cmd1, val;
+
+	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+			0 : BM_SSP_CTRL0_IGNORE_CRC;
+	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+			BM_SSP_CTRL0_GET_RESP : 0;
+	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+			BM_SSP_CTRL0_LONG_RESP : 0;
+
+	if (data->flags & MMC_DATA_WRITE) {
+		dma_data_dir = DMA_TO_DEVICE;
+		read = 0;
+	} else {
+		dma_data_dir = DMA_FROM_DEVICE;
+		read = BM_SSP_CTRL0_READ;
+	}
+
+	ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) |
+		ignore_crc | get_resp | long_resp |
+		BM_SSP_CTRL0_DATA_XFER | read |
+		BM_SSP_CTRL0_WAIT_FOR_IRQ |
+		BM_SSP_CTRL0_ENABLE;
+
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+
+	/* get logarithm to base 2 of block size for setting register */
+	log2_blksz = ilog2(data->blksz);
+
+	/*
+	 * take special care of the case that data size from data->sg
+	 * is not equal to blocks x blksz
+	 */
+	for_each_sg(sgl, sg, sg_len, i)
+		data_size += sg->length;
+
+	if (data_size != data->blocks * data->blksz)
+		blocks = 1;
+
+	/* xfer count, block size and count need to be set differently */
+	if (ssp_is_old()) {
+		ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
+		cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
+			BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
+	} else {
+		writel(data_size, host->base + HW_SSP_XFER_SIZE);
+		writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
+		       BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
+		       host->base + HW_SSP_BLOCK_SIZE);
+	}
+
+	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
+	    (cmd->opcode == SD_IO_RW_EXTENDED))
+		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	/* set the timeout count */
+	timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns);
+	val = readl(host->base + HW_SSP_TIMING);
+	val &= ~(BM_SSP_TIMING_TIMEOUT);
+	val |= BF_SSP(timeout, TIMING_TIMEOUT);
+	writel(val, host->base + HW_SSP_TIMING);
+
+	/* pio */
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	/* append data sg */
+	WARN_ON(host->data != NULL);
+	host->data = data;
+	host->dma_dir = dma_data_dir;
+	desc = mxs_mmc_prep_dma(host, 1);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+			      struct mmc_command *cmd)
+{
+	host->cmd = cmd;
+
+	switch (mmc_cmd_type(cmd)) {
+	case MMC_CMD_BC:
+		mxs_mmc_bc(host);
+		break;
+	case MMC_CMD_BCR:
+		mxs_mmc_ac(host);
+		break;
+	case MMC_CMD_AC:
+		mxs_mmc_ac(host);
+		break;
+	case MMC_CMD_ADTC:
+		mxs_mmc_adtc(host);
+		break;
+	default:
+		dev_warn(mmc_dev(host->mmc),
+			 "%s: unknown MMC command\n", __func__);
+		break;
+	}
+}
+
+static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	WARN_ON(host->mrq != NULL);
+	host->mrq = mrq;
+	mxs_mmc_start_cmd(host, mrq->cmd);
+}
+
+static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
+{
+	unsigned int ssp_rate, bit_rate;
+	u32 div1, div2;
+	u32 val;
+
+	ssp_rate = clk_get_rate(host->clk);
+
+	for (div1 = 2; div1 < 254; div1 += 2) {
+		div2 = ssp_rate / rate / div1;
+		if (div2 < 0x100)
+			break;
+	}
+
+	if (div1 >= 254) {
+		dev_err(mmc_dev(host->mmc),
+			"%s: cannot set clock to %d\n", __func__, rate);
+		return;
+	}
+
+	if (div2 == 0)
+		bit_rate = ssp_rate / div1;
+	else
+		bit_rate = ssp_rate / div1 / div2;
+
+	val = readl(host->base + HW_SSP_TIMING);
+	val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
+	val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE);
+	val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE);
+	writel(val, host->base + HW_SSP_TIMING);
+
+	host->clk_rate = bit_rate;
+
+	dev_dbg(mmc_dev(host->mmc),
+		"%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n",
+		__func__, div1, div2, ssp_rate, bit_rate, rate);
+}
+
+static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	if (ios->bus_width == MMC_BUS_WIDTH_8)
+		host->bus_width = 2;
+	else if (ios->bus_width == MMC_BUS_WIDTH_4)
+		host->bus_width = 1;
+	else
+		host->bus_width = 0;
+
+	if (ios->clock)
+		mxs_mmc_set_clk_rate(host, ios->clock);
+}
+
+static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->sdio_irq_en = enable;
+
+	if (enable) {
+		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+		       host->base + HW_SSP_CTRL0 + MXS_SET_ADDR);
+		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+		       host->base + HW_SSP_CTRL1 + MXS_SET_ADDR);
+
+		if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ)
+			mmc_signal_sdio_irq(host->mmc);
+
+	} else {
+		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+		       host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR);
+		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+		       host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+	}
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static const struct mmc_host_ops mxs_mmc_ops = {
+	.request = mxs_mmc_request,
+	.get_ro = mxs_mmc_get_ro,
+	.get_cd = mxs_mmc_get_cd,
+	.set_ios = mxs_mmc_set_ios,
+	.enable_sdio_irq = mxs_mmc_enable_sdio_irq,
+};
+
+static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct mxs_mmc_host *host = param;
+
+	if (!mxs_dma_is_apbh(chan))
+		return false;
+
+	if (chan->chan_id != host->dma_res->start)
+		return false;
+
+	chan->private = &host->dma_data;
+
+	return true;
+}
+
+static int mxs_mmc_probe(struct platform_device *pdev)
+{
+	struct mxs_mmc_host *host;
+	struct mmc_host *mmc;
+	struct resource *iores, *dmares, *r;
+	struct mxs_mmc_platform_data *pdata;
+	int ret = 0, irq_err, irq_dma;
+	dma_cap_mask_t mask;
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	irq_err = platform_get_irq(pdev, 0);
+	irq_dma = platform_get_irq(pdev, 1);
+	if (!iores || !dmares || irq_err < 0 || irq_dma < 0)
+		return -EINVAL;
+
+	r = request_mem_region(iores->start, resource_size(iores), pdev->name);
+	if (!r)
+		return -EBUSY;
+
+	mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out_release_mem;
+	}
+
+	host = mmc_priv(mmc);
+	host->base = ioremap(r->start, resource_size(r));
+	if (!host->base) {
+		ret = -ENOMEM;
+		goto out_mmc_free;
+	}
+
+	/* only major verion does matter */
+	host->version = readl(host->base + HW_SSP_VERSION) >>
+			BP_SSP_VERSION_MAJOR;
+
+	host->mmc = mmc;
+	host->res = r;
+	host->dma_res = dmares;
+	host->irq = irq_err;
+	host->sdio_irq_en = 0;
+
+	host->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		goto out_iounmap;
+	}
+	clk_enable(host->clk);
+
+	mxs_mmc_reset(host);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	host->dma_data.chan_irq = irq_dma;
+	host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
+	if (!host->dmach) {
+		dev_err(mmc_dev(host->mmc),
+			"%s: failed to request dma\n", __func__);
+		goto out_clk_put;
+	}
+
+	/* set mmc core parameters */
+	mmc->ops = &mxs_mmc_ops;
+	mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
+		    MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
+
+	pdata =	mmc_dev(host->mmc)->platform_data;
+	if (pdata) {
+		if (pdata->flags & SLOTF_8_BIT_CAPABLE)
+			mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+		if (pdata->flags & SLOTF_4_BIT_CAPABLE)
+			mmc->caps |= MMC_CAP_4_BIT_DATA;
+	}
+
+	mmc->f_min = 400000;
+	mmc->f_max = 288000000;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->max_segs = 52;
+	mmc->max_blk_size = 1 << 0xf;
+	mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff;
+	mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff;
+	mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
+
+	platform_set_drvdata(pdev, mmc);
+
+	ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host);
+	if (ret)
+		goto out_free_dma;
+
+	spin_lock_init(&host->lock);
+
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto out_free_irq;
+
+	dev_info(mmc_dev(host->mmc), "initialized\n");
+
+	return 0;
+
+out_free_irq:
+	free_irq(host->irq, host);
+out_free_dma:
+	if (host->dmach)
+		dma_release_channel(host->dmach);
+out_clk_put:
+	clk_disable(host->clk);
+	clk_put(host->clk);
+out_iounmap:
+	iounmap(host->base);
+out_mmc_free:
+	mmc_free_host(mmc);
+out_release_mem:
+	release_mem_region(iores->start, resource_size(iores));
+	return ret;
+}
+
+static int mxs_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct resource *res = host->res;
+
+	mmc_remove_host(mmc);
+
+	free_irq(host->irq, host);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (host->dmach)
+		dma_release_channel(host->dmach);
+
+	clk_disable(host->clk);
+	clk_put(host->clk);
+
+	iounmap(host->base);
+
+	mmc_free_host(mmc);
+
+	release_mem_region(res->start, resource_size(res));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxs_mmc_suspend(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	int ret = 0;
+
+	ret = mmc_suspend_host(mmc);
+
+	clk_disable(host->clk);
+
+	return ret;
+}
+
+static int mxs_mmc_resume(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	int ret = 0;
+
+	clk_enable(host->clk);
+
+	ret = mmc_resume_host(mmc);
+
+	return ret;
+}
+
+static const struct dev_pm_ops mxs_mmc_pm_ops = {
+	.suspend	= mxs_mmc_suspend,
+	.resume		= mxs_mmc_resume,
+};
+#endif
+
+static struct platform_driver mxs_mmc_driver = {
+	.probe		= mxs_mmc_probe,
+	.remove		= mxs_mmc_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &mxs_mmc_pm_ops,
+#endif
+	},
+};
+
+static int __init mxs_mmc_init(void)
+{
+	return platform_driver_register(&mxs_mmc_driver);
+}
+
+static void __exit mxs_mmc_exit(void)
+{
+	platform_driver_unregister(&mxs_mmc_driver);
+}
+
+module_init(mxs_mmc_init);
+module_exit(mxs_mmc_exit);
+
+MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_LICENSE("GPL");
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3] Add mmc device for i.MX23/28
From: Shawn Guo @ 2011-02-21 10:42 UTC (permalink / raw)
  To: linux-arm-kernel

This patch set is to add mmc device for i.MX23 and i.MX28.

Regards,
Shawn

^ permalink raw reply

* [PATCH v3 1/6] ARM: mxs/clock: fix base address missing in name##_set_parent
From: Shawn Guo @ 2011-02-21 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284979-14853-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/clock-mx23.c |    2 +-
 arch/arm/mach-mxs/clock-mx28.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
index 350b28c..c19b69a 100644
--- a/arch/arm/mach-mxs/clock-mx23.c
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -347,7 +347,7 @@ static int name##_set_parent(struct clk *clk, struct clk *parent)	\
 {									\
 	if (parent != clk->parent) {					\
 		__raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit,		\
-			 HW_CLKCTRL_CLKSEQ_TOG);			\
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG);	\
 		clk->parent = parent;					\
 	}								\
 									\
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index a3b4787..9f4ee36 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -483,7 +483,7 @@ static int name##_set_parent(struct clk *clk, struct clk *parent)	\
 {									\
 	if (parent != clk->parent) {					\
 		__raw_writel(BM_CLKCTRL_CLKSEQ_BYPASS_##bit,		\
-			 HW_CLKCTRL_CLKSEQ_TOG);			\
+			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CLKSEQ_TOG);	\
 		clk->parent = parent;					\
 	}								\
 									\
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3 2/6] ARM: mxs: make ssp error irq definition consistent
From: Shawn Guo @ 2011-02-21 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284979-14853-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/include/mach/mx23.h |    2 +-
 arch/arm/mach-mxs/include/mach/mx28.h |    8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-mxs/include/mach/mx23.h b/arch/arm/mach-mxs/include/mach/mx23.h
index 1730c9c..e858692 100644
--- a/arch/arm/mach-mxs/include/mach/mx23.h
+++ b/arch/arm/mach-mxs/include/mach/mx23.h
@@ -93,7 +93,7 @@
 #define MX23_INT_USB_WAKEUP		12
 #define MX23_INT_GPMI_DMA		13
 #define MX23_INT_SSP1_DMA		14
-#define MX23_INT_SSP_ERROR		15
+#define MX23_INT_SSP1_ERROR		15
 #define MX23_INT_GPIO0			16
 #define MX23_INT_GPIO1			17
 #define MX23_INT_GPIO2			18
diff --git a/arch/arm/mach-mxs/include/mach/mx28.h b/arch/arm/mach-mxs/include/mach/mx28.h
index 3f3485a..75d8611 100644
--- a/arch/arm/mach-mxs/include/mach/mx28.h
+++ b/arch/arm/mach-mxs/include/mach/mx28.h
@@ -163,10 +163,10 @@
 #define MX28_INT_USB0			93
 #define MX28_INT_USB1_WAKEUP		94
 #define MX28_INT_USB0_WAKEUP		95
-#define MX28_INT_SSP0			96
-#define MX28_INT_SSP1			97
-#define MX28_INT_SSP2			98
-#define MX28_INT_SSP3			99
+#define MX28_INT_SSP0_ERROR		96
+#define MX28_INT_SSP1_ERROR		97
+#define MX28_INT_SSP2_ERROR		98
+#define MX28_INT_SSP3_ERROR		99
 #define MX28_INT_ENET_SWI		100
 #define MX28_INT_ENET_MAC0		101
 #define MX28_INT_ENET_MAC1		102
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3 3/6] ARM: mxs: dynamically allocate mmc device
From: Shawn Guo @ 2011-02-21 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284979-14853-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/clock-mx23.c                  |   16 +++++
 arch/arm/mach-mxs/clock-mx28.c                  |   18 +++++
 arch/arm/mach-mxs/devices-mx23.h                |    4 +
 arch/arm/mach-mxs/devices-mx28.h                |    4 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-mmc.c        |   77 +++++++++++++++++++++++
 arch/arm/mach-mxs/include/mach/devices-common.h |   13 ++++
 8 files changed, 136 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-mmc.c

diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
index c19b69a..a1ed5f4 100644
--- a/arch/arm/mach-mxs/clock-mx23.c
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -445,6 +445,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
 	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
 	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
+	_REGISTER_CLOCK("mxs-mmc.0", NULL, ssp_clk)
 	_REGISTER_CLOCK(NULL, "usb", usb_clk)
 	_REGISTER_CLOCK(NULL, "audio", audio_clk)
 	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
@@ -515,6 +516,15 @@ static int clk_misc_init(void)
 	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
 			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
 
+	/*
+	 * 480 MHz seems too high to be ssp clock source directly,
+	 * so set frac to get a 288 MHz ref_io.
+	 */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+	reg &= ~BM_CLKCTRL_FRAC_IOFRAC;
+	reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+
 	return 0;
 }
 
@@ -522,6 +532,12 @@ int __init mx23_clocks_init(void)
 {
 	clk_misc_init();
 
+	/*
+	 * source ssp clock from ref_io than ref_xtal,
+	 * as ref_xtal only provides 24 MHz as maximum.
+	 */
+	clk_set_parent(&ssp_clk, &ref_io_clk);
+
 	clk_enable(&cpu_clk);
 	clk_enable(&hbus_clk);
 	clk_enable(&xbus_clk);
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index 9f4ee36..aeb7b2c 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -619,6 +619,8 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("pll2", NULL, pll2_clk)
 	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
 	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
+	_REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk)
+	_REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can0_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can1_clk)
 	_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
@@ -730,6 +732,15 @@ static int clk_misc_init(void)
 	reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
 
+	/*
+	 * 480 MHz seems too high to be ssp clock source directly,
+	 * so set frac0 to get a 288 MHz ref_io0.
+	 */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
+	reg &= ~BM_CLKCTRL_FRAC0_IO0FRAC;
+	reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
+
 	return 0;
 }
 
@@ -737,6 +748,13 @@ int __init mx28_clocks_init(void)
 {
 	clk_misc_init();
 
+	/*
+	 * source ssp clock from ref_io0 than ref_xtal,
+	 * as ref_xtal only provides 24 MHz as maximum.
+	 */
+	clk_set_parent(&ssp0_clk, &ref_io0_clk);
+	clk_set_parent(&ssp1_clk, &ref_io0_clk);
+
 	clk_enable(&cpu_clk);
 	clk_enable(&hbus_clk);
 	clk_enable(&xbus_clk);
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
index 1256788..4419390 100644
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -14,3 +14,7 @@
 extern const struct amba_device mx23_duart_device __initconst;
 #define mx23_add_duart() \
 	mxs_add_duart(&mx23_duart_device)
+
+extern const struct mxs_mmc_data mx23_mmc_data[] __initconst;
+#define mx23_add_mmc(id, pdata) \
+	mxs_add_mmc(&mx23_mmc_data[id], pdata)
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 3b18304..540639d 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -32,3 +32,7 @@ extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst;
 	mxs_add_flexcan(&mx28_flexcan_data[id], pdata)
 #define mx28_add_flexcan0(pdata)	mx28_add_flexcan(0, pdata)
 #define mx28_add_flexcan1(pdata)	mx28_add_flexcan(1, pdata)
+
+extern const struct mxs_mmc_data mx28_mmc_data[] __initconst;
+#define mx28_add_mmc(id, pdata) \
+	mxs_add_mmc(&mx28_mmc_data[id], pdata)
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
index 6c65b67..49307f8 100644
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -11,3 +11,6 @@ config MXS_HAVE_PLATFORM_FEC
 config MXS_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN if CAN
 	bool
+
+config MXS_HAVE_PLATFORM_MMC
+	bool
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index ca7acc4..c0dacfd 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
 obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MMC) += platform-mmc.o
diff --git a/arch/arm/mach-mxs/devices/platform-mmc.c b/arch/arm/mach-mxs/devices/platform-mmc.c
new file mode 100644
index 0000000..868def1
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-mmc.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_mmc_data_entry_single(soc, _id, hwid)			\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _SSP ## hwid ## _BASE_ADDR,		\
+		.dma = soc ## _DMA_SSP ## hwid,				\
+		.irq_err = soc ## _INT_SSP ## hwid ## _ERROR,		\
+		.irq_dma = soc ## _INT_SSP ## hwid ## _DMA,		\
+	}
+
+#define mxs_mmc_data_entry(soc, _id, hwid)				\
+	[_id] = mxs_mmc_data_entry_single(soc, _id, hwid)
+
+
+#ifdef CONFIG_SOC_IMX23
+const struct mxs_mmc_data mx23_mmc_data[] __initconst = {
+#define mx23_mmc_data_entry(_id, hwid)					\
+	mxs_mmc_data_entry(MX23, _id, hwid)
+	mx23_mmc_data_entry(0, 1),
+	mx23_mmc_data_entry(1, 2),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_mmc_data mx28_mmc_data[] __initconst = {
+#define mx28_mmc_data_entry(_id)					\
+	mxs_mmc_data_entry(MX28, _id, _id)
+	mx28_mmc_data_entry(0),
+	mx28_mmc_data_entry(1),
+};
+#endif
+
+struct platform_device *__init mxs_add_mmc(
+		const struct mxs_mmc_data *data,
+		const struct mxs_mmc_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start	= data->iobase,
+			.end	= data->iobase + SZ_8K - 1,
+			.flags	= IORESOURCE_MEM,
+		}, {
+			.start	= data->dma,
+			.end	= data->dma,
+			.flags	= IORESOURCE_DMA,
+		}, {
+			.start	= data->irq_err,
+			.end	= data->irq_err,
+			.flags	= IORESOURCE_IRQ,
+		}, {
+			.start	= data->irq_dma,
+			.end	= data->irq_dma,
+			.flags	= IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("mxs-mmc", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index e7aefb4..54710c5 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -63,3 +63,16 @@ struct mxs_flexcan_data {
 struct platform_device *__init mxs_add_flexcan(
 		const struct mxs_flexcan_data *data,
 		const struct flexcan_platform_data *pdata);
+
+/* mmc */
+#include <mach/mmc.h>
+struct mxs_mmc_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t dma;
+	resource_size_t irq_err;
+	resource_size_t irq_dma;
+};
+struct platform_device *__init mxs_add_mmc(
+		const struct mxs_mmc_data *data,
+		const struct mxs_mmc_platform_data *pdata);
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3 4/6] ARM: mxs: fix typo "GPO" in iomux-mx23.h
From: Shawn Guo @ 2011-02-21 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284979-14853-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/include/mach/iomux-mx23.h |  190 +++++++++++++-------------
 1 files changed, 95 insertions(+), 95 deletions(-)

diff --git a/arch/arm/mach-mxs/include/mach/iomux-mx23.h b/arch/arm/mach-mxs/include/mach/iomux-mx23.h
index 94e5dd8..b0190a4 100644
--- a/arch/arm/mach-mxs/include/mach/iomux-mx23.h
+++ b/arch/arm/mach-mxs/include/mach/iomux-mx23.h
@@ -254,102 +254,102 @@
 #define MX23_PAD_ROTARYB__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_2)
 
 /* MUXSEL_GPIO */
-#define MX23_PAD_GPMI_D00__GPO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D01__GPO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D02__GPO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D03__GPO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D04__GPO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D05__GPO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D06__GPO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D07__GPO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D08__GPO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D09__GPO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D10__GPO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D11__GPO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D12__GPO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D13__GPO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D14__GPO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D15__GPO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CLE__GPO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_ALE__GPO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE2N__GPO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY0__GPO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY1__GPO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY2__GPO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY3__GPO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WPN__GPO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WRN__GPO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDN__GPO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_CTS__GPO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RTS__GPO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RX__GPO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_TX__GPO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SCL__GPO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SDA__GPO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D00__GPIO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D01__GPIO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D02__GPIO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D03__GPIO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D04__GPIO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D05__GPIO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D06__GPIO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D07__GPIO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D08__GPIO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D09__GPIO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D10__GPIO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D11__GPIO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D12__GPIO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D13__GPIO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D14__GPIO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D15__GPIO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CLE__GPIO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_ALE__GPIO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE2N__GPIO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY0__GPIO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY1__GPIO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY2__GPIO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY3__GPIO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WPN__GPIO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WRN__GPIO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDN__GPIO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_CTS__GPIO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RTS__GPIO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RX__GPIO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_TX__GPIO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SCL__GPIO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SDA__GPIO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
 
-#define MX23_PAD_LCD_D00__GPO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D01__GPO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D02__GPO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D03__GPO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D04__GPO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D05__GPO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D06__GPO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D07__GPO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D08__GPO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D09__GPO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D10__GPO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D11__GPO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D12__GPO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D13__GPO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D14__GPO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D15__GPO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D16__GPO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D17__GPO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RESET__GPO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RS__GPO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_WR__GPO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_CS__GPO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_DOTCK__GPO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_ENABLE__GPO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_HSYNC__GPO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_VSYNC__GPO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM0__GPO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM1__GPO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM2__GPO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM3__GPO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM4__GPO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D00__GPIO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D01__GPIO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D02__GPIO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D03__GPIO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D04__GPIO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D05__GPIO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D06__GPIO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D07__GPIO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D08__GPIO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D09__GPIO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D10__GPIO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D11__GPIO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D12__GPIO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D13__GPIO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D14__GPIO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D15__GPIO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D16__GPIO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D17__GPIO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RESET__GPIO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RS__GPIO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_WR__GPIO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_CS__GPIO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_DOTCK__GPIO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_ENABLE__GPIO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_HSYNC__GPIO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_VSYNC__GPIO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM0__GPIO_1_26		MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM1__GPIO_1_27		MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM2__GPIO_1_28		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM3__GPIO_1_29		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM4__GPIO_1_30		MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
 
-#define MX23_PAD_SSP1_CMD__GPO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DETECT__GPO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA0__GPO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA1__GPO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA2__GPO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA3__GPO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_SCK__GPO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYA__GPO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYB__GPO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A00__GPO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A01__GPO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A02__GPO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A03__GPO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A04__GPO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A05__GPO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A06__GPO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A07__GPO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A08__GPO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A09__GPO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A10__GPO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A11__GPO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A12__GPO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA0__GPO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA1__GPO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CASN__GPO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE0N__GPO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE1N__GPO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE1N__GPO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE0N__GPO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CKE__GPO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_RASN__GPO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_WEN__GPO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_CMD__GPIO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DETECT__GPIO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA0__GPIO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA1__GPIO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA2__GPIO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA3__GPIO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_SCK__GPIO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYA__GPIO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYB__GPIO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A00__GPIO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A01__GPIO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A02__GPIO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A03__GPIO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A04__GPIO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A05__GPIO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A06__GPIO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A07__GPIO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A08__GPIO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A09__GPIO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A10__GPIO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A11__GPIO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A12__GPIO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA0__GPIO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA1__GPIO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CASN__GPIO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE0N__GPIO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE1N__GPIO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE1N__GPIO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE0N__GPIO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CKE__GPIO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_RASN__GPIO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_WEN__GPIO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
 
 #endif /* __MACH_IOMUX_MX23_H__ */
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3 5/6] ARM: mxs/mx23evk: add mmc device
From: Shawn Guo @ 2011-02-21 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284979-14853-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/Kconfig        |    1 +
 arch/arm/mach-mxs/mach-mx23evk.c |   47 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index cd2fbdf..f47fae3 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -19,6 +19,7 @@ config MACH_MX23EVK
 	bool "Support MX23EVK Platform"
 	select SOC_IMX23
 	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_MMC
 	default y
 	help
 	  Include support for MX23EVK platform. This includes specific
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
index aa06400..21519e3 100644
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -26,17 +26,64 @@
 
 #include "devices-mx23.h"
 
+#define MX23EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(1, 30)
+#define MX23EVK_MMC0_SLOT_POWER		MXS_GPIO_NR(1, 29)
+
 static const iomux_cfg_t mx23evk_pads[] __initconst = {
 	/* duart */
 	MX23_PAD_PWM0__DUART_RX | MXS_PAD_4MA,
 	MX23_PAD_PWM1__DUART_TX | MXS_PAD_4MA,
+
+	/* mmc */
+	MX23_PAD_SSP1_DATA0__SSP1_DATA0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DATA1__SSP1_DATA1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DATA2__SSP1_DATA2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DATA3__SSP1_DATA3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D08__SSP1_DATA4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D09__SSP1_DATA5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D10__SSP1_DATA6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D11__SSP1_DATA7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_CMD__SSP1_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DETECT__SSP1_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX23_PAD_SSP1_SCK__SSP1_SCK |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX23_PAD_PWM4__GPIO_1_30 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* slot power enable */
+	MX23_PAD_PWM3__GPIO_1_29 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+};
+
+static struct mxs_mmc_platform_data mx23_mmc_pdata __initdata = {
+	.wp_gpio = MX23EVK_MMC0_WRITE_PROTECT,
+	.flags = SLOTF_8_BIT_CAPABLE,
 };
 
 static void __init mx23evk_init(void)
 {
+	int ret;
+
 	mxs_iomux_setup_multiple_pads(mx23evk_pads, ARRAY_SIZE(mx23evk_pads));
 
 	mx23_add_duart();
+
+	/* power on mmc slot by writing 0 to the gpio */
+	ret = gpio_request_one(MX23EVK_MMC0_SLOT_POWER, GPIOF_DIR_OUT,
+			       "mmc0-slot-power");
+	if (ret)
+		pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
+	mx23_add_mmc(0, &mx23_mmc_pdata);
 }
 
 static void __init mx23evk_timer_init(void)
-- 
1.7.1

^ permalink raw reply related

* [PATCH v3 6/6] ARM: mxs/mx28evk: add mmc device
From: Shawn Guo @ 2011-02-21 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1298284979-14853-1-git-send-email-shawn.guo@freescale.com>

Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
---
 arch/arm/mach-mxs/Kconfig        |    1 +
 arch/arm/mach-mxs/mach-mx28evk.c |   96 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 95 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index f47fae3..287e0f8 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -30,6 +30,7 @@ config MACH_MX28EVK
 	select SOC_IMX28
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_FEC
+	select MXS_HAVE_PLATFORM_MMC
 	select MXS_OCOTP
 	default y
 	help
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index e8db99f..75597c1 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -28,8 +28,13 @@
 #include "devices-mx28.h"
 #include "gpio.h"
 
-#define MX28EVK_FEC_PHY_POWER	MXS_GPIO_NR(2, 15)
-#define MX28EVK_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
+#define MX28EVK_FEC_PHY_POWER		MXS_GPIO_NR(2, 15)
+#define MX28EVK_FEC_PHY_RESET		MXS_GPIO_NR(4, 13)
+
+#define MX28EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(2, 12)
+#define MX28EVK_MMC1_WRITE_PROTECT	MXS_GPIO_NR(0, 28)
+#define MX28EVK_MMC0_SLOT_POWER		MXS_GPIO_NR(3, 28)
+#define MX28EVK_MMC1_SLOT_POWER		MXS_GPIO_NR(3, 29)
 
 static const iomux_cfg_t mx28evk_pads[] __initconst = {
 	/* duart */
@@ -76,6 +81,66 @@ static const iomux_cfg_t mx28evk_pads[] __initconst = {
 	/* phy reset line */
 	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
 		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* mmc0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA1__SSP0_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA2__SSP0_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA3__SSP0_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA4__SSP0_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA5__SSP0_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA6__SSP0_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA7__SSP0_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_CMD__SSP0_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX28_PAD_SSP1_SCK__GPIO_2_12 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* slot power enable */
+	MX28_PAD_PWM3__GPIO_3_28 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* mmc1 */
+	MX28_PAD_GPMI_D00__SSP1_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D01__SSP1_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D02__SSP1_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D03__SSP1_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D04__SSP1_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D05__SSP1_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D06__SSP1_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D07__SSP1_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY1__SSP1_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_WRN__SSP1_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX28_PAD_GPMI_RESETN__GPIO_0_28 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* slot power enable */
+	MX28_PAD_PWM4__GPIO_3_29 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
 };
 
 /* fec */
@@ -159,12 +224,39 @@ error:
 	return -ETIMEDOUT;
 }
 
+static struct mxs_mmc_platform_data mx28_mmc_pdata[] __initdata = {
+	{
+		/* mmc0 */
+		.wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	}, {
+		/* mmc1 */
+		.wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	},
+};
+
 static void __init mx28evk_init(void)
 {
+	int ret;
+
 	mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
 
 	mx28_add_duart();
 
+	/* power on mmc slot by writing 0 to the gpio */
+	ret = gpio_request_one(MX28EVK_MMC0_SLOT_POWER, GPIOF_DIR_OUT,
+			       "mmc0-slot-power");
+	if (ret)
+		pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
+	mx28_add_mmc(0, &mx28_mmc_pdata[0]);
+
+	ret = gpio_request_one(MX28EVK_MMC1_SLOT_POWER, GPIOF_DIR_OUT,
+			       "mmc1-slot-power");
+	if (ret)
+		pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
+	mx28_add_mmc(1, &mx28_mmc_pdata[1]);
+
 	if (mx28evk_fec_get_mac())
 		pr_warn("%s: failed on fec mac setup\n", __func__);
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 5/5] mmc: sdhci: add quirk SDHCI_QUIRK_FIX_NO_INT_IN_MULTI_BLK_IO
From: Wolfram Sang @ 2011-02-21 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <010C9052C42A00499CE76D637FA5EE900C579F@039-SN1MPN1-001.039d.mgd.msft.net>

> > > -   if (cpu_is_mx35() || cpu_is_mx51())
> > > +   if (cpu_is_mx53())
> > > +           host->quirks |= SDHCI_QUIRK_FIX_NO_INT_IN_MULTI_BLK_IO;
> >
> > Have you tried it doing it via IO-accessors?
> Richard Zhu: This quirk is used to fix a mechanism problem in the MMC CMDs execution procedure.
> It would be very abrupt and ugly, if the IO-accessors are added into these original procedures.

Please don't get it personal, but IMHO it is pretty ugly the way it is
now. This quirk is very imx-specific and calling something like
SDHCI_VENDOR_SPEC in sdhci.c looks clearly wrong to me. By the way, what
does this bit do, the description doesn't say so?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110221/2393fe81/attachment.sig>

^ permalink raw reply

* [PATCH V5 36/63] ST SPEAr : EMI (Extrenal Memory Interface) controller driver
From: Russell King - ARM Linux @ 2011-02-21 11:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4D620582.40802@st.com>

On Mon, Feb 21, 2011 at 11:56:10AM +0530, Vipin Kumar wrote:
> >> +void __init
> >> +emi_init_board_info(struct platform_device *pdev, struct resource *resources,
> >> +		int res_num, struct mtd_partition *partitions,
> >> +		unsigned int nr_partitions, unsigned int width)
> >> +{
> >> +	struct physmap_flash_data *emi_plat_data = dev_get_platdata(&pdev->dev);
> >> +
> >> +	pdev->resource = resources;
> >> +	pdev->num_resources = res_num;
> >> +
> >> +	if (partitions) {
> >> +		emi_plat_data->parts = partitions;
> >> +		emi_plat_data->nr_parts = nr_partitions;
> >> +	}
> >> +
> >> +	emi_plat_data->width = width;
> >> +}
> > 
> > I don't see why this has to be code rather than in the platform specific
> > files as static initializers.  
> 
> The device is instantiated in the machine file and above information comes
> from the board file. So we kept them this way.

Ok, but I don't see why this should be in the EMI code.  Surely this
should be along side the nor device, and called 'nor_init_board_info'
or something similar?

^ permalink raw reply

* [PATCH V5 30/63] ST SPEAr: Replacing SIZE macro's with actual required size
From: Russell King - ARM Linux @ 2011-02-21 11:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4D62088D.7050205@st.com>

On Mon, Feb 21, 2011 at 12:09:09PM +0530, viresh kumar wrote:
> On 02/19/2011 11:31 PM, Russell King - ARM Linux wrote:
> > Same comments as the other patch changing to SZ_* macros.  Where possible
> > fold these changes into the patch(es) which add the original definitions
> > rather than having patches which add stuff and then separate patches
> > which rework those patches.
> > 
> 
> Ok.
> 
> > Could you do that and provide reworked patches please?  I'll publish the
> > branch I've merged stuff onto thus far (but note that it's 'unstable'),
> > but note that it won't contain the bits I've merged into the 'fixes'
> > branch.
> 
> Ok. I will surely do that.
> 
> Just one question, should i send these patches to mailing list again or
> directly to tracker?

If you can update the ones I've mentioned in the patch tracker that'd
be great.

^ permalink raw reply

* [RFC PATCH 2/2] ARMv7: Invalidate the TLB before freeing page tables
From: Catalin Marinas @ 2011-02-21 11:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110221103018.GH14495@n2100.arm.linux.org.uk>

On 21 February 2011 10:30, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Mon, Feb 21, 2011 at 09:39:32AM +0000, Catalin Marinas wrote:
>> On 20 February 2011 12:12, Russell King - ARM Linux
>> <linux@arm.linux.org.uk> wrote:
>> > On Tue, Feb 15, 2011 at 02:42:06PM +0000, Catalin Marinas wrote:
>> >> On Tue, 2011-02-15 at 12:14 +0000, Russell King - ARM Linux wrote:
>> >> > On Tue, Feb 15, 2011 at 11:32:42AM +0000, Russell King - ARM Linux wrote:
>> >> > > The point of TLB shootdown is that we unmap the entries from the page
>> >> > > tables, then issue the TLB flushes, and then free the pages and page
>> >> > > tables after that. ?All that Peter's patch tries to do is to get ARM to
>> >> > > use the generic stuff.
>> >> >
>> >> > As Peter's patch preserves the current behaviour, that's not sufficient.
>> >> > So, let's do this our own way and delay pages and page table frees on
>> >> > ARMv6 and v7. ?Untested.
>> >>
>> >> ARMv7 should be enough, I'm not aware of any pre-v7 with this behaviour.
>> >
>> > ARM11MPCore. ?Any SMP system can access a page which was free'd by the
>> > tlb code but hasn't been flushed from the hardware TLBs. ?So maybe we
>> > want it to be "defined(CONFIG_SMP) || defined(CONFIG_CPU_32v7)" ?
>>
>> In practice, since the hardware TLB does not store higher level
>> entries on existing v6 cores, there is no cached value pointing to the
>> freed pte page.
>
> It's not about cached values of PTE pointers.

My point is about cached values in the 1st level of page tables
pointing to the second level and the freeing of the 2nd level of page
tables.

I think we talk about two different cases (but could be fixable with
the same patch). Your scenario is valid as well, just different.

>> In theory, we first clear the pmd entry but another
>> CPU could be doing a PTW at the same time and had already read the pmd
>> before being cleared. But the timing constraints are difficult to
>> reproduce in practice.
>
> I don't think you properly understand the problem.
>
> CPU#0 is unmapping page tables, eg due to munmap(), mremap(), etc.
> CPU#1 is running a thread, and has TLB entries for the region being unmapped.
>
> ? ? ? ?CPU#0 ? ? ? ? ? ? ? ? ? ? ? ? ? CPU#1
> ? ? ? ?clear page table entry
> ? ? ? ?frees page
> ? ? ? ?loop continues
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?accesses page
> ? ? ? ?...
> ? ? ? ?sometime in the future
> ? ? ? ?invalidates TLB

For this scenario we only need to implement tlb_remove_page() to
invalidate the TLB before releasing the page (called via
zap_pte_range). We currently delay the TLB operation until
tlb_end_vma() which happens after the page was released.

For my scenario, we also need pte_free_tlb() because of the pmd
caching in the TLB.

So your patch fixes both. My ack is still valid.

-- 
Catalin

^ 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