Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ARM: footbridge: Switch to sched_clock_register()
From: Stephen Boyd @ 2014-02-04 19:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1389922207-5154-1-git-send-email-sboyd@codeaurora.org>

On 01/16, Stephen Boyd wrote:
> The 32 bit sched_clock interface supports 64 bits since 3.13-rc1.
> Upgrade to the 64 bit function to allow us to remove the 32 bit
> registration interface.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

Russell,

Can you please apply this for 3.14? This is the last user of the
deprecated interface in linus' tree. Once this is merged I will
remove setup_sched_clock(). It's 7945/1 in the patch tracker.

> 
> Based on rmk/for-next
> 
>  arch/arm/mach-footbridge/dc21285-timer.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
> index 3971104d32d4..5d2725fd878c 100644
> --- a/arch/arm/mach-footbridge/dc21285-timer.c > +++ b/arch/arm/mach-footbridge/dc21285-timer.c
> @@ -125,7 +125,7 @@ void __init footbridge_timer_init(void)
>  	clockevents_config_and_register(ce, rate, 0x4, 0xffffff);
>  }
>  
> -static u32 notrace footbridge_read_sched_clock(void)
> +static u64 notrace footbridge_read_sched_clock(void)
>  {
>  	return ~*CSR_TIMER3_VALUE;
>  }
> @@ -138,5 +138,5 @@ void __init footbridge_sched_clock(void)
>  	*CSR_TIMER3_CLR = 0;
>  	*CSR_TIMER3_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
>  
> -	setup_sched_clock(footbridge_read_sched_clock, 24, rate);
> +	sched_clock_register(footbridge_read_sched_clock, 24, rate);
>  }
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply

* [PATCH 07/17] spi: pl022: Don't ignore power domain and amba bus at system suspend
From: Mark Brown @ 2014-02-04 19:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391529538-21685-8-git-send-email-ulf.hansson@linaro.org>

On Tue, Feb 04, 2014 at 04:58:48PM +0100, Ulf Hansson wrote:

> @@ -2328,8 +2300,23 @@ static int pl022_suspend(struct device *dev)
>  		return ret;
>  	}
>  
> -	pm_runtime_get_sync(dev);
> -	pl022_suspend_resources(pl022, false);
> +	pm_runtime_disable(dev);
> +
> +	if (!pm_runtime_status_suspended(dev)) {
> +		if (dev->pm_domain && dev->pm_domain->ops.runtime_suspend)
> +			ret = dev->pm_domain->ops.runtime_suspend(dev);
> +		else
> +			ret = dev->bus->pm->runtime_suspend(dev);
> +
> +		if (ret) {
> +			pm_runtime_enable(dev);
> +			return ret;
> +		}
> +
> +		pm_runtime_set_suspended(dev);
> +	}

This seems like a fairly hideous thing to be having to open code in an
individual driver, it all looks generic and like something that most if
not all devices ought to be doing and it looks very vulnerable to being
broken by changes in the core.  At the very least I would expect this to
be done in a helper function, though it would be even nicer if the
driver core were figuring this stuff out for us based on the device
level callback so that drivers didn't need to worry about being in power
domains or manually calling bus level callbacks.  

Putting it in a helper would at least mean that it's easier for the
mechanics to be transferred to the core proper later on.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140204/c6740df7/attachment.sig>

^ permalink raw reply

* [PATCH 09/17] spi: pl022: Simplify clock handling
From: Mark Brown @ 2014-02-04 19:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391529538-21685-10-git-send-email-ulf.hansson@linaro.org>

On Tue, Feb 04, 2014 at 04:58:50PM +0100, Ulf Hansson wrote:
> Make use of clk_prepare_enable and clk_disable_unprepare to simplify
> code. No functional change.

I went ahead and applied this since it looks good and seems like an
unrelated cleanup to the runtime PM stuff which seems to be where the
interdependencies are - thanks!  It's on a separate branch with the
already applied change so if it does need to be cross merged we can do
that easily or even drop the branch.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140204/04b74d44/attachment.sig>

^ permalink raw reply

* [PATCH 10/17] spi: pl022: Remove redundant pinctrl to default state in probe
From: Mark Brown @ 2014-02-04 19:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391529538-21685-11-git-send-email-ulf.hansson@linaro.org>

On Tue, Feb 04, 2014 at 04:58:51PM +0100, Ulf Hansson wrote:
> The driver core is now taking care of putting our pins into default
> state at probe. Thus we can remove the redundant call for it in probe.

I applied this one too, as with the last patch it looks independant of
the runtime PM stuff.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140204/a1237526/attachment.sig>

^ permalink raw reply

* [PATCH] arm64: Add architecture support for PCI
From: Arnd Bergmann @ 2014-02-04 19:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191055.GC25695@obsidianresearch.com>

On Tuesday 04 February 2014 12:10:55 Jason Gunthorpe wrote:
> 
> For instance to support peer-to-peer IO you need to have a consisent,
> non-overlapping set of bus/device/function/tag to uniquely route TLPs
> within the chip. Cross domain TLP routing in HW is non-trivial.

Yes, that is a good reason.

> IOMMUs (and SR-IOv) rely on the BDF to identify the originating device
> for each TLP. Multiple domains means a much more complex IOMMU
> environment.

I fear we already have to support complex IOMMU setups on ARM,
whether there are multiple PCI domains or not. But it would be
nice in theory not to require it.

> Failure to integrate on-chip devices into the PCI world also means
> thing like SR-IOv won't work sanely with on-chip devices.

I'd consider this a feature ;)

But you are probably right: people will do SR-IOV whether we like
it or not, and they will try to do it on non-PCI devices too,
and great suffering will be involved.

	Arnd

^ permalink raw reply

* [PATCH 05/17] mmc: mmci: Put the device into low power state at system suspend
From: Kevin Hilman @ 2014-02-04 19:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391529538-21685-6-git-send-email-ulf.hansson@linaro.org>

Ulf Hansson <ulf.hansson@linaro.org> writes:

> Due to the available runtime PM callbacks, we are now able to put our
> device into low power state at system suspend.
>
> Earlier we could not accomplish this without trusting a power domain
> for the device to take care of it. Now we are able to cope with
> scenarios both with and without a power domain.
>
> Cc: Russell King <linux@arm.linux.org.uk>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>  drivers/mmc/host/mmci.c |   45 +++++++++++++++++++++++++--------------------
>  1 file changed, 25 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
> index c88da1c..074e0cb 100644
> --- a/drivers/mmc/host/mmci.c
> +++ b/drivers/mmc/host/mmci.c
> @@ -1723,33 +1723,38 @@ static int mmci_remove(struct amba_device *dev)
>  	return 0;
>  }
>  
> -#ifdef CONFIG_SUSPEND
> -static int mmci_suspend(struct device *dev)
> +#ifdef CONFIG_PM_SLEEP
> +static int mmci_suspend_late(struct device *dev)
>  {
> -	struct amba_device *adev = to_amba_device(dev);
> -	struct mmc_host *mmc = amba_get_drvdata(adev);
> +	int ret = 0;
>  
> -	if (mmc) {
> -		struct mmci_host *host = mmc_priv(mmc);
> -		pm_runtime_get_sync(dev);
> -		writel(0, host->base + MMCIMASK0);
> -	}
> +	if (pm_runtime_status_suspended(dev))
> +		return 0;
>  
> -	return 0;
> +	if (dev->pm_domain && dev->pm_domain->ops.runtime_suspend)
> +		ret = dev->pm_domain->ops.runtime_suspend(dev);
> +	else
> +		ret = dev->bus->pm->runtime_suspend(dev);
> +
> +	if (!ret)
> +		pm_runtime_set_suspended(dev);

Isn't this basically open-coding pm_runtime_suspend()...

> +	return ret;
>  }
>  
> -static int mmci_resume(struct device *dev)
> +static int mmci_resume_early(struct device *dev)
>  {
> -	struct amba_device *adev = to_amba_device(dev);
> -	struct mmc_host *mmc = amba_get_drvdata(adev);
> +	int ret = 0;
>  
> -	if (mmc) {
> -		struct mmci_host *host = mmc_priv(mmc);
> -		writel(MCI_IRQENABLE, host->base + MMCIMASK0);
> -		pm_runtime_put(dev);
> -	}
> +	if (pm_runtime_status_suspended(dev))
> +		return 0;
>  
> -	return 0;
> +	if (dev->pm_domain && dev->pm_domain->ops.runtime_resume)
> +		ret = dev->pm_domain->ops.runtime_resume(dev);
> +	else
> +		ret = dev->bus->pm->runtime_resume(dev);
> +
> +	return ret;

...and this is pm_runtime_resume()? (though both terribly simplified.)

This is starting to show that building with PM_SLEEP but not PM_RUNTIME
is going to force open-coding a lot of stuff that the runtime PM
framework already provides.  So either we need some helper functions so
we're not sprinkling manual calls to bus/pm_domain callbacks all over
the place, or maybe where we need to go is have a way for platforms that
really are "runtime PM centric" to declare that even PM_SLEEP depends on
PM_RUNTIME.  

I'm trying to thing of a good reason to not make PM_SLEEP depend on
PM_RUNTIME for platforms like this.

Kevin

^ permalink raw reply

* [RFC PATCH V3 1/4] pci: APM X-Gene PCIe controller driver
From: Arnd Bergmann @ 2014-02-04 19:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140203221559.GG2519@obsidianresearch.com>

On Monday 03 February 2014, Jason Gunthorpe wrote:
> On Mon, Feb 03, 2014 at 09:12:32PM +0100, Arnd Bergmann wrote:
> 
> > Are you sure that is true for the root bridge as well? I don't
> > remember the details, but I though that for the host bridge,
> > we don't actually look at the BARs at all.
> 
> That is right, but this isn't a host bridge device, it is a PCI-PCI
> bridge with root complex registers. The root complex bridge is not the
> same as the host bridge.
> 
> Unfortunately the implementation is non-conforming. :(

Ok, I see. I was probably asking the wrong question then earlier
when I tried to find out what this is.

	Arnd

^ permalink raw reply

* [PATCH v2 0/6] ARM: sunxi: Add driver for SD/MMC hosts found on allwinner sunxi SOCs
From: David Lanzendörfer @ 2014-02-04 19:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hello
The following patchset adds support for the SD/MMC host found in the Allwinner SoCs.
It contains all the necessary modifications for clock environment and also the device
tree script modification which add it to all the boards using it.
The clock environment function needed for phase offset configuration has
been proposed and implemented by Emilio.
This patchset is the second attempt to send this driver upstream.
I'm looking forward to the acceptance of this patchset into mainline.

best regards
David

---

David Lanzend?rfer (4):
      ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs
      ARM: dts: sun7i: Add support for mmc
      ARM: dts: sun4i: Add support for mmc
      ARM: dts: sun5i: Add support for mmc

Emilio L?pez (1):
      clk: sunxi: Implement MMC phase control

Hans de Goede (1):
      ARM: sunxi: clk: export clk_sunxi_mmc_phase_control


 arch/arm/boot/dts/sun4i-a10-a1000.dts            |    8 
 arch/arm/boot/dts/sun4i-a10-cubieboard.dts       |    8 
 arch/arm/boot/dts/sun4i-a10.dtsi                 |   54 +
 arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts |   30 +
 arch/arm/boot/dts/sun5i-a10s.dtsi                |   44 +
 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts  |   15 
 arch/arm/boot/dts/sun5i-a13-olinuxino.dts        |   15 
 arch/arm/boot/dts/sun5i-a13.dtsi                 |   37 +
 arch/arm/boot/dts/sun7i-a20-cubieboard2.dts      |    8 
 arch/arm/boot/dts/sun7i-a20-cubietruck.dts       |    8 
 arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts  |   23 +
 arch/arm/boot/dts/sun7i-a20.dtsi                 |   61 ++
 drivers/clk/sunxi/clk-sunxi.c                    |   35 +
 drivers/mmc/host/Kconfig                         |    8 
 drivers/mmc/host/Makefile                        |    2 
 drivers/mmc/host/sunxi-mci.c                     |  848 ++++++++++++++++++++++
 drivers/mmc/host/sunxi-mci.h                     |  239 ++++++
 include/linux/clk/sunxi.h                        |   22 +
 18 files changed, 1465 insertions(+)
 create mode 100644 drivers/mmc/host/sunxi-mci.c
 create mode 100644 drivers/mmc/host/sunxi-mci.h
 create mode 100644 include/linux/clk/sunxi.h

-- 
Signature

^ permalink raw reply

* [Patch v4 1/2] dmaengine: add Qualcomm BAM dma driver
From: Andy Gross @ 2014-02-04 19:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52F0D5E1.3040409@metafoo.de>

On Tue, Feb 04, 2014 at 12:58:25PM +0100, Lars-Peter Clausen wrote:
> On 02/04/2014 12:04 AM, Andy Gross wrote:
> [...]
> >+static int bam_dma_remove(struct platform_device *pdev)
> >+{
> >+	struct bam_device *bdev = platform_get_drvdata(pdev);
> >+	u32 i;
> >+
> >+	dma_async_device_unregister(&bdev->common);
> >+	of_dma_controller_free(pdev->dev.of_node);
> 
> The controller should first be removed from the of lookup table,
> then free the device.
> 
Ah right, had this reversed.

> >+
> >+	/* mask all interrupts for this execution environment */
> >+	writel_relaxed(0, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
> 
> You still need to free the interrupt to make this race free,
> especially on a multi-processor system. free_irq() acts as a
> synchronization point that makes sure that interrupt handler has
> finished running and that no new interrupt handlers are being run
> after this point. Just masking the interrupt in the control register
> does not provide these guarantees.

ok i'll just add in a devm_free_irq().  The only good thing then about using the
devm_request_irq is the cleanup on error paths in the probe.

> >+
> >+	for (i = 0; i < bdev->num_channels; i++) {
> >+		bam_dma_terminate_all(&bdev->channels[i]);
> >+		tasklet_kill(&bdev->channels[i].vc.task);
> >+	}
> >+
> >+	tasklet_kill(&bdev->task);
> >+
> >+	clk_disable_unprepare(bdev->bamclk);
> >+
> >+	return 0;
> >+}
> [...]
> 

-- 
sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply

* [PATCH v2 1/6] ARM: sunxi: Add driver for SD/MMC hosts found on Allwinner sunxi SoCs
From: David Lanzendörfer @ 2014-02-04 19:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191648.29809.14611.stgit@dizzy-6.o2s.ch>

This is based on the driver Allwinner ships in the Android kernel sources.

Initial porting to upstream kernels done by David Lanzend??rfer, additional
fixes and cleanups by Hans de Goede.

It uses dma in bus-master mode using a built-in designware idmac controller,
which is identical to the one found in the mmc-dw hosts.
The rest of the host is not identical to mmc-dw.
---
 drivers/mmc/host/Kconfig     |    8 
 drivers/mmc/host/Makefile    |    2 
 drivers/mmc/host/sunxi-mci.c |  848 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mmc/host/sunxi-mci.h |  239 ++++++++++++
 4 files changed, 1097 insertions(+)
 create mode 100644 drivers/mmc/host/sunxi-mci.c
 create mode 100644 drivers/mmc/host/sunxi-mci.h

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1384f67..e56aabd 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -689,3 +689,11 @@ config MMC_REALTEK_PCI
 	help
 	  Say Y here to include driver code to support SD/MMC card interface
 	  of Realtek PCI-E card reader
+
+config MMC_SUNXI
+	tristate "Allwinner sunxi SD/MMC Host Controller support"
+	depends on ARCH_SUNXI
+	default y
+	help
+	  This selects support for the SD/MMC Host Controller on
+	  Allwinner sunxi SoCs.
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3483b6b..6c9cbd3 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -54,6 +54,8 @@ obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
 
 obj-$(CONFIG_MMC_REALTEK_PCI)	+= rtsx_pci_sdmmc.o
 
+obj-$(CONFIG_MMC_SUNXI)		+= sunxi-mci.o
+
 obj-$(CONFIG_MMC_SDHCI_PLTFM)		+= sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_CNS3XXX)		+= sdhci-cns3xxx.o
 obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX)	+= sdhci-esdhc-imx.o
diff --git a/drivers/mmc/host/sunxi-mci.c b/drivers/mmc/host/sunxi-mci.c
new file mode 100644
index 0000000..9d87da7
--- /dev/null
+++ b/drivers/mmc/host/sunxi-mci.c
@@ -0,0 +1,848 @@
+/*
+ * Driver for sunxi SD/MMC host controllers
+ * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd.
+ * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com>
+ * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
+ * (C) Copyright 2013-2013 David Lanzend?rfer <david.lanzendoerfer@o2s.ch>
+ * (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+
+#include <linux/clk.h>
+#include <linux/clk-private.h>
+#include <linux/clk/sunxi.h>
+
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/slot-gpio.h>
+
+#include "sunxi-mci.h"
+
+static void sunxi_mmc_init_host(struct mmc_host *mmc)
+{
+	u32 rval;
+	struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
+
+	/* reset controller */
+	rval = mci_readl(smc_host, REG_GCTRL) | SDXC_HWReset;
+	mci_writel(smc_host, REG_GCTRL, rval);
+
+	mci_writel(smc_host, REG_FTRGL, 0x20070008);
+	mci_writel(smc_host, REG_TMOUT, 0xffffffff);
+	mci_writel(smc_host, REG_IMASK, smc_host->sdio_imask);
+	mci_writel(smc_host, REG_RINTR, 0xffffffff);
+	mci_writel(smc_host, REG_DBGC, 0xdeb);
+	mci_writel(smc_host, REG_FUNS, 0xceaa0000);
+	mci_writel(smc_host, REG_DLBA, smc_host->sg_dma);
+	rval = mci_readl(smc_host, REG_GCTRL)|SDXC_INTEnb;
+	rval &= ~SDXC_AccessDoneDirect;
+	mci_writel(smc_host, REG_GCTRL, rval);
+}
+
+static void sunxi_mmc_exit_host(struct sunxi_mmc_host *smc_host)
+{
+	mci_writel(smc_host, REG_GCTRL, SDXC_HWReset);
+}
+
+/* /\* UHS-I Operation Modes */
+/*  * DS		25MHz	12.5MB/s	3.3V */
+/*  * HS		50MHz	25MB/s		3.3V */
+/*  * SDR12	25MHz	12.5MB/s	1.8V */
+/*  * SDR25	50MHz	25MB/s		1.8V */
+/*  * SDR50	100MHz	50MB/s		1.8V */
+/*  * SDR104	208MHz	104MB/s		1.8V */
+/*  * DDR50	50MHz	50MB/s		1.8V */
+/*  * MMC Operation Modes */
+/*  * DS		26MHz	26MB/s		3/1.8/1.2V */
+/*  * HS		52MHz	52MB/s		3/1.8/1.2V */
+/*  * HSDDR	52MHz	104MB/s		3/1.8/1.2V */
+/*  * HS200	200MHz	200MB/s		1.8/1.2V */
+/*  * */
+/*  * Spec. Timing */
+/*  * SD3.0 */
+/*  * Fcclk    Tcclk   Fsclk   Tsclk   Tis     Tih     odly  RTis     RTih */
+/*  * 400K     2.5us   24M     41ns    5ns     5ns     1     2209ns   41ns */
+/*  * 25M      40ns    600M    1.67ns  5ns     5ns     3     14.99ns  5.01ns */
+/*  * 50M      20ns    600M    1.67ns  6ns     2ns     3     14.99ns  5.01ns */
+/*  * 50MDDR   20ns    600M    1.67ns  6ns     0.8ns   2     6.67ns   3.33ns */
+/*  * 104M     9.6ns   600M    1.67ns  3ns     0.8ns   1     7.93ns   1.67ns */
+/*  * 208M     4.8ns   600M    1.67ns  1.4ns   0.8ns   1     3.33ns   1.67ns */
+
+/*  * 25M      40ns    300M    3.33ns  5ns     5ns     2     13.34ns   6.66ns */
+/*  * 50M      20ns    300M    3.33ns  6ns     2ns     2     13.34ns   6.66ns */
+/*  * 50MDDR   20ns    300M    3.33ns  6ns     0.8ns   1     6.67ns    3.33ns */
+/*  * 104M     9.6ns   300M    3.33ns  3ns     0.8ns   0     7.93ns    1.67ns */
+/*  * 208M     4.8ns   300M    3.33ns  1.4ns   0.8ns   0     3.13ns    1.67ns */
+
+/*  * eMMC4.5 */
+/*  * 400K     2.5us   24M     41ns    3ns     3ns     1     2209ns    41ns */
+/*  * 25M      40ns    600M    1.67ns  3ns     3ns     3     14.99ns   5.01ns */
+/*  * 50M      20ns    600M    1.67ns  3ns     3ns     3     14.99ns   5.01ns */
+/*  * 50MDDR   20ns    600M    1.67ns  2.5ns   2.5ns   2     6.67ns    3.33ns */
+/*  * 200M     5ns     600M    1.67ns  1.4ns   0.8ns   1     3.33ns    1.67ns */
+/*  *\/ */
+
+static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
+				    struct mmc_data *data)
+{
+	struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu;
+	struct sunxi_idma_des *pdes_pa = (struct sunxi_idma_des *)host->sg_dma;
+	int i, max_len = (1 << host->idma_des_size_bits);
+
+	for (i = 0; i < data->sg_len; i++) {
+		pdes[i].config = SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN |
+				 SDXC_IDMAC_DES0_DIC;
+
+		if (data->sg[i].length == max_len)
+			pdes[i].buf_size = 0; /* 0 == max_len */
+		else
+			pdes[i].buf_size = data->sg[i].length;
+
+		pdes[i].buf_addr_ptr1 = sg_dma_address(&data->sg[i]);
+		pdes[i].buf_addr_ptr2 = (u32)&pdes_pa[i + 1];
+	}
+	pdes[0].config |= SDXC_IDMAC_DES0_FD;
+	pdes[i - 1].config = SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_LD;
+
+	wmb(); /* Ensure idma_des hit main mem before we start the idmac */
+}
+
+static enum dma_data_direction sunxi_mmc_get_dma_dir(struct mmc_data *data)
+{
+	if (data->flags & MMC_DATA_WRITE)
+		return DMA_TO_DEVICE;
+	else
+		return DMA_FROM_DEVICE;
+}
+
+static int sunxi_mmc_prepare_dma(struct sunxi_mmc_host *smc_host,
+				 struct mmc_data *data)
+{
+	u32 dma_len;
+	u32 i;
+	u32 temp;
+	struct scatterlist *sg;
+
+	dma_len = dma_map_sg(mmc_dev(smc_host->mmc), data->sg, data->sg_len,
+			     sunxi_mmc_get_dma_dir(data));
+	if (dma_len == 0) {
+		dev_err(mmc_dev(smc_host->mmc), "dma_map_sg failed\n");
+		return -ENOMEM;
+	}
+
+	for_each_sg(data->sg, sg, data->sg_len, i) {
+		if (sg->offset & 3 || sg->length & 3) {
+			dev_err(mmc_dev(smc_host->mmc),
+				"unaligned scatterlist: os %x length %d\n",
+				sg->offset, sg->length);
+			return -EINVAL;
+		}
+	}
+
+	sunxi_mmc_init_idma_des(smc_host, data);
+
+	temp = mci_readl(smc_host, REG_GCTRL);
+	temp |= SDXC_DMAEnb;
+	mci_writel(smc_host, REG_GCTRL, temp);
+	temp |= SDXC_DMAReset;
+	mci_writel(smc_host, REG_GCTRL, temp);
+
+	mci_writel(smc_host, REG_DMAC, SDXC_IDMACSoftRST);
+
+	if (!(data->flags & MMC_DATA_WRITE))
+		mci_writel(smc_host, REG_IDIE, SDXC_IDMACReceiveInt);
+
+	mci_writel(smc_host, REG_DMAC, SDXC_IDMACFixBurst | SDXC_IDMACIDMAOn);
+
+	return 0;
+}
+
+static void sunxi_mmc_send_manual_stop(struct sunxi_mmc_host *host,
+				       struct mmc_request *req)
+{
+	u32 cmd_val = SDXC_Start | SDXC_RspExp | SDXC_StopAbortCMD
+			| SDXC_CheckRspCRC | MMC_STOP_TRANSMISSION;
+	u32 ri = 0;
+	unsigned long expire = jiffies + msecs_to_jiffies(1000);
+
+	mci_writel(host, REG_CARG, 0);
+	mci_writel(host, REG_CMDR, cmd_val);
+	do {
+		ri = mci_readl(host, REG_RINTR);
+	} while (!(ri & (SDXC_CmdDone | SDXC_IntErrBit)) &&
+		 time_before(jiffies, expire));
+
+	if (ri & SDXC_IntErrBit) {
+		dev_err(mmc_dev(host->mmc), "send stop command failed\n");
+		if (req->stop)
+			req->stop->resp[0] = -ETIMEDOUT;
+	} else {
+		if (req->stop)
+			req->stop->resp[0] = mci_readl(host, REG_RESP0);
+	}
+
+	mci_writel(host, REG_RINTR, 0xffff);
+}
+
+static void sunxi_mmc_dump_errinfo(struct sunxi_mmc_host *smc_host)
+{
+	struct mmc_command *cmd = smc_host->mrq->cmd;
+	struct mmc_data *data = smc_host->mrq->data;
+
+	/* For some cmds timeout is normal with sd/mmc cards */
+	if ((smc_host->int_sum & SDXC_IntErrBit) == SDXC_RespTimeout &&
+			(cmd->opcode == 5 || cmd->opcode == 52))
+		return;
+
+	dev_err(mmc_dev(smc_host->mmc),
+		"smc %d err, cmd %d,%s%s%s%s%s%s%s%s%s%s !!\n",
+		smc_host->mmc->index, cmd->opcode,
+		data ? (data->flags & MMC_DATA_WRITE ? " WR" : " RD") : "",
+		smc_host->int_sum & SDXC_RespErr     ? " RE"     : "",
+		smc_host->int_sum & SDXC_RespCRCErr  ? " RCE"    : "",
+		smc_host->int_sum & SDXC_DataCRCErr  ? " DCE"    : "",
+		smc_host->int_sum & SDXC_RespTimeout ? " RTO"    : "",
+		smc_host->int_sum & SDXC_DataTimeout ? " DTO"    : "",
+		smc_host->int_sum & SDXC_FIFORunErr  ? " FE"     : "",
+		smc_host->int_sum & SDXC_HardWLocked ? " HL"     : "",
+		smc_host->int_sum & SDXC_StartBitErr ? " SBE"    : "",
+		smc_host->int_sum & SDXC_EndBitErr   ? " EBE"    : ""
+		);
+}
+
+static void sunxi_mmc_finalize_request(struct sunxi_mmc_host *host)
+{
+	struct mmc_request *mrq;
+	unsigned long iflags;
+
+	spin_lock_irqsave(&host->lock, iflags);
+
+	mrq = host->mrq;
+	if (!mrq) {
+		spin_unlock_irqrestore(&host->lock, iflags);
+		dev_err(mmc_dev(host->mmc), "no request to finalize\n");
+		return;
+	}
+
+	if (host->int_sum & SDXC_IntErrBit) {
+		sunxi_mmc_dump_errinfo(host);
+		mrq->cmd->error = -ETIMEDOUT;
+		if (mrq->data)
+			mrq->data->error = -ETIMEDOUT;
+		if (mrq->stop)
+			mrq->stop->error = -ETIMEDOUT;
+	} else {
+		if (mrq->cmd->flags & MMC_RSP_136) {
+			mrq->cmd->resp[0] = mci_readl(host, REG_RESP3);
+			mrq->cmd->resp[1] = mci_readl(host, REG_RESP2);
+			mrq->cmd->resp[2] = mci_readl(host, REG_RESP1);
+			mrq->cmd->resp[3] = mci_readl(host, REG_RESP0);
+		} else {
+			mrq->cmd->resp[0] = mci_readl(host, REG_RESP0);
+		}
+		if (mrq->data)
+			mrq->data->bytes_xfered =
+				mrq->data->blocks * mrq->data->blksz;
+	}
+
+	if (mrq->data) {
+		struct mmc_data *data = mrq->data;
+		u32 temp;
+
+		mci_writel(host, REG_IDST, 0x337);
+		mci_writel(host, REG_DMAC, 0);
+		temp = mci_readl(host, REG_GCTRL);
+		mci_writel(host, REG_GCTRL, temp|SDXC_DMAReset);
+		temp &= ~SDXC_DMAEnb;
+		mci_writel(host, REG_GCTRL, temp);
+		temp |= SDXC_FIFOReset;
+		mci_writel(host, REG_GCTRL, temp);
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+				     sunxi_mmc_get_dma_dir(data));
+	}
+
+	mci_writel(host, REG_RINTR, 0xffff);
+
+	dev_dbg(mmc_dev(host->mmc), "req done, resp %08x %08x %08x %08x\n",
+		mrq->cmd->resp[0], mrq->cmd->resp[1],
+		mrq->cmd->resp[2], mrq->cmd->resp[3]);
+
+	host->mrq = NULL;
+	host->int_sum = 0;
+	host->wait_dma = 0;
+
+	spin_unlock_irqrestore(&host->lock, iflags);
+
+	if (mrq->data && mrq->data->error) {
+		dev_err(mmc_dev(host->mmc),
+			"data error, sending stop command\n");
+		sunxi_mmc_send_manual_stop(host, mrq);
+	}
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+static irqreturn_t sunxi_mmc_irq(int irq, void *dev_id)
+{
+	struct sunxi_mmc_host *host = dev_id;
+	u32 finalize = 0;
+	u32 sdio_int = 0;
+	u32 msk_int;
+	u32 idma_int;
+
+	spin_lock(&host->lock);
+
+	idma_int  = mci_readl(host, REG_IDST);
+	msk_int   = mci_readl(host, REG_MISTA);
+
+	dev_dbg(mmc_dev(host->mmc), "irq: rq %p mi %08x idi %08x\n",
+		host->mrq, msk_int, idma_int);
+
+	if (host->mrq) {
+		if (idma_int & SDXC_IDMACReceiveInt)
+			host->wait_dma = 0;
+
+		host->int_sum |= msk_int;
+
+		/* Wait for CmdDone on RespTimeout before finishing the req */
+		if ((host->int_sum & SDXC_RespTimeout) &&
+				!(host->int_sum & SDXC_CmdDone))
+			mci_writel(host, REG_IMASK,
+				   host->sdio_imask | SDXC_CmdDone);
+		else if (host->int_sum & SDXC_IntErrBit)
+			finalize = 1; /* Don't wait for dma on error */
+		else if (host->int_sum & SDXC_IntDoneBit && !host->wait_dma)
+			finalize = 1; /* Done */
+
+		if (finalize) {
+			mci_writel(host, REG_IMASK, host->sdio_imask);
+			mci_writel(host, REG_IDIE, 0);
+		}
+	}
+
+	if (msk_int & SDXC_SDIOInt)
+		sdio_int = 1;
+
+	mci_writel(host, REG_RINTR, msk_int);
+	mci_writel(host, REG_IDST, idma_int);
+
+	spin_unlock(&host->lock);
+
+	if (finalize)
+		tasklet_schedule(&host->tasklet);
+
+	if (sdio_int)
+		mmc_signal_sdio_irq(host->mmc);
+
+	return IRQ_HANDLED;
+}
+
+static void sunxi_mmc_tasklet(unsigned long data)
+{
+	struct sunxi_mmc_host *smc_host = (struct sunxi_mmc_host *) data;
+	sunxi_mmc_finalize_request(smc_host);
+}
+
+static void sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
+{
+	unsigned long expire = jiffies + msecs_to_jiffies(2000);
+	u32 rval;
+
+	rval = mci_readl(host, REG_CLKCR);
+	rval &= ~(SDXC_CardClkOn | SDXC_LowPowerOn);
+	if (oclk_en)
+		rval |= SDXC_CardClkOn;
+	if (!host->io_flag)
+		rval |= SDXC_LowPowerOn;
+	mci_writel(host, REG_CLKCR, rval);
+
+	rval = SDXC_Start | SDXC_UPCLKOnly | SDXC_WaitPreOver;
+	if (host->voltage_switching)
+		rval |= SDXC_VolSwitch;
+	mci_writel(host, REG_CMDR, rval);
+	do {
+		rval = mci_readl(host, REG_CMDR);
+	} while (time_before(jiffies, expire) && (rval & SDXC_Start));
+
+	if (rval & SDXC_Start) {
+		dev_err(mmc_dev(host->mmc), "fatal err update clk timeout\n");
+		host->ferror = 1;
+	}
+}
+
+static void sunxi_mmc_set_clk_dly(struct sunxi_mmc_host *smc_host,
+				  u32 oclk_dly, u32 sclk_dly)
+{
+	unsigned long iflags;
+	struct clk_hw *hw = __clk_get_hw(smc_host->clk_mod);
+
+	spin_lock_irqsave(&smc_host->lock, iflags);
+	clk_sunxi_mmc_phase_control(hw, sclk_dly, oclk_dly);
+	spin_unlock_irqrestore(&smc_host->lock, iflags);
+}
+
+struct sunxi_mmc_clk_dly mmc_clk_dly[MMC_CLK_MOD_NUM] = {
+	{ MMC_CLK_400K, 0, 7 },
+	{ MMC_CLK_25M, 0, 5 },
+	{ MMC_CLK_50M, 3, 5 },
+	{ MMC_CLK_50MDDR, 2, 4 },
+	{ MMC_CLK_50MDDR_8BIT, 2, 4 },
+	{ MMC_CLK_100M, 1, 4 },
+	{ MMC_CLK_200M, 1, 4 },
+};
+
+static void sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *smc_host,
+				   unsigned int rate)
+{
+	u32 newrate;
+	u32 src_clk;
+	u32 oclk_dly;
+	u32 sclk_dly;
+	u32 temp;
+	struct sunxi_mmc_clk_dly *dly = NULL;
+
+	newrate = clk_round_rate(smc_host->clk_mod, rate);
+	if (smc_host->clk_mod_rate == newrate) {
+		dev_dbg(mmc_dev(smc_host->mmc), "clk already %d, rounded %d\n",
+			rate, newrate);
+		return;
+	}
+
+	dev_dbg(mmc_dev(smc_host->mmc), "setting clk to %d, rounded %d\n",
+		rate, newrate);
+
+	/* setting clock rate */
+	clk_disable(smc_host->clk_mod);
+	clk_set_rate(smc_host->clk_mod, newrate);
+	clk_enable(smc_host->clk_mod);
+	smc_host->clk_mod_rate = newrate = clk_get_rate(smc_host->clk_mod);
+	dev_dbg(mmc_dev(smc_host->mmc), "clk is now %d\n", newrate);
+
+	sunxi_mmc_oclk_onoff(smc_host, 0);
+	/* clear internal divider */
+	temp = mci_readl(smc_host, REG_CLKCR);
+	temp &= ~0xff;
+	mci_writel(smc_host, REG_CLKCR, temp);
+
+	/* determine delays */
+	if (rate <= 400000) {
+		dly = &mmc_clk_dly[MMC_CLK_400K];
+	} else if (rate <= 25000000) {
+		dly = &mmc_clk_dly[MMC_CLK_25M];
+	} else if (rate <= 50000000) {
+		if (smc_host->ddr) {
+			if (smc_host->bus_width == 8)
+				dly = &mmc_clk_dly[MMC_CLK_50MDDR_8BIT];
+			else
+				dly = &mmc_clk_dly[MMC_CLK_50MDDR];
+		} else {
+			dly = &mmc_clk_dly[MMC_CLK_50M];
+		}
+	} else if (rate <= 104000000) {
+		dly = &mmc_clk_dly[MMC_CLK_100M];
+	} else if (rate <= 208000000) {
+		dly = &mmc_clk_dly[MMC_CLK_200M];
+	} else
+		dly = &mmc_clk_dly[MMC_CLK_50M];
+
+	oclk_dly = dly->oclk_dly;
+	sclk_dly = dly->sclk_dly;
+
+	src_clk = clk_get_rate(clk_get_parent(smc_host->clk_mod));
+	if (src_clk >= 300000000 && src_clk <= 400000000) {
+		if (oclk_dly)
+			oclk_dly--;
+		if (sclk_dly)
+			sclk_dly--;
+	}
+
+	sunxi_mmc_set_clk_dly(smc_host, oclk_dly, sclk_dly);
+	sunxi_mmc_oclk_onoff(smc_host, 1);
+
+	/* oclk_onoff sets various irq status bits, clear these */
+	mci_writel(smc_host, REG_RINTR,
+		   mci_readl(smc_host, REG_RINTR) & ~SDXC_SDIOInt);
+}
+
+static void sunxi_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct sunxi_mmc_host *host = mmc_priv(mmc);
+	u32 temp;
+	s32 err;
+
+	/* Set the power state */
+	switch (ios->power_mode) {
+	case MMC_POWER_ON:
+		break;
+
+	case MMC_POWER_UP:
+		if (!IS_ERR(host->vmmc)) {
+			mmc_regulator_set_ocr(host->mmc, host->vmmc, ios->vdd);
+			udelay(200);
+		}
+
+		err =  clk_prepare_enable(host->clk_ahb);
+		if (err) {
+			dev_err(mmc_dev(host->mmc), "AHB clk err %d\n", err);
+			host->ferror = 1;
+			return;
+		}
+		err =  clk_prepare_enable(host->clk_mod);
+		if (err) {
+			dev_err(mmc_dev(host->mmc), "MOD clk err %d\n", err);
+			host->ferror = 1;
+			return;
+		}
+
+		sunxi_mmc_init_host(mmc);
+		enable_irq(host->irq);
+
+		dev_dbg(mmc_dev(host->mmc), "power on!\n");
+		host->ferror = 0;
+		break;
+
+	case MMC_POWER_OFF:
+		dev_dbg(mmc_dev(host->mmc), "power off!\n");
+		disable_irq(host->irq);
+		sunxi_mmc_exit_host(host);
+		clk_disable_unprepare(host->clk_ahb);
+		clk_disable_unprepare(host->clk_mod);
+		if (!IS_ERR(host->vmmc))
+			mmc_regulator_set_ocr(host->mmc, host->vmmc, 0);
+		host->ferror = 0;
+		break;
+	}
+
+	/* set bus width */
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		mci_writel(host, REG_WIDTH, SDXC_WIDTH1);
+		host->bus_width = 1;
+		break;
+	case MMC_BUS_WIDTH_4:
+		mci_writel(host, REG_WIDTH, SDXC_WIDTH4);
+		host->bus_width = 4;
+		break;
+	case MMC_BUS_WIDTH_8:
+		mci_writel(host, REG_WIDTH, SDXC_WIDTH8);
+		host->bus_width = 8;
+		break;
+	}
+
+	/* set ddr mode */
+	temp = mci_readl(host, REG_GCTRL);
+	if (ios->timing == MMC_TIMING_UHS_DDR50) {
+		temp |= SDXC_DDR_MODE;
+		host->ddr = 1;
+	} else {
+		temp &= ~SDXC_DDR_MODE;
+		host->ddr = 0;
+	}
+	mci_writel(host, REG_GCTRL, temp);
+
+	/* set up clock */
+	if (ios->clock && ios->power_mode) {
+		dev_dbg(mmc_dev(host->mmc), "ios->clock: %d\n", ios->clock);
+		sunxi_mmc_clk_set_rate(host, ios->clock);
+		usleep_range(50000, 55000);
+	}
+}
+
+static void sunxi_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
+	unsigned long flags;
+	u32 imask;
+
+	spin_lock_irqsave(&smc_host->lock, flags);
+	imask = mci_readl(smc_host, REG_IMASK);
+	if (enable) {
+		smc_host->sdio_imask = SDXC_SDIOInt;
+		imask |= SDXC_SDIOInt;
+	} else {
+		smc_host->sdio_imask = 0;
+		imask &= ~SDXC_SDIOInt;
+	}
+	mci_writel(smc_host, REG_IMASK, imask);
+	spin_unlock_irqrestore(&smc_host->lock, flags);
+}
+
+static void sunxi_mmc_hw_reset(struct mmc_host *mmc)
+{
+	struct sunxi_mmc_host *smc_host = mmc_priv(mmc);
+	mci_writel(smc_host, REG_HWRST, 0);
+	udelay(10);
+	mci_writel(smc_host, REG_HWRST, 1);
+	udelay(300);
+}
+
+static void sunxi_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct sunxi_mmc_host *host = mmc_priv(mmc);
+	struct mmc_command *cmd = mrq->cmd;
+	struct mmc_data *data = mrq->data;
+	unsigned long iflags;
+	u32 imask = SDXC_IntErrBit;
+	u32 cmd_val = SDXC_Start | (cmd->opcode & 0x3f);
+	u32 byte_cnt = 0;
+	int ret;
+
+	if (!mmc_gpio_get_cd(mmc) || host->ferror) {
+		dev_dbg(mmc_dev(host->mmc), "no medium present\n");
+		mrq->cmd->error = -ENOMEDIUM;
+		mmc_request_done(mmc, mrq);
+		return;
+	}
+
+	if (data) {
+		byte_cnt = data->blksz * data->blocks;
+		mci_writel(host, REG_BLKSZ, data->blksz);
+		mci_writel(host, REG_BCNTR, byte_cnt);
+		ret = sunxi_mmc_prepare_dma(host, data);
+		if (ret < 0) {
+			dev_err(mmc_dev(host->mmc), "prepare DMA failed\n");
+			cmd->error = ret;
+			cmd->data->error = ret;
+			mmc_request_done(host->mmc, mrq);
+			return;
+		}
+	}
+
+	if (cmd->opcode == MMC_GO_IDLE_STATE) {
+		cmd_val |= SDXC_SendInitSeq;
+		imask |= SDXC_CmdDone;
+	}
+
+	if (cmd->opcode == SD_SWITCH_VOLTAGE) {
+		cmd_val |= SDXC_VolSwitch;
+		imask |= SDXC_VolChgDone;
+		host->voltage_switching = 1;
+		sunxi_mmc_oclk_onoff(host, 1);
+	}
+
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		cmd_val |= SDXC_RspExp;
+		if (cmd->flags & MMC_RSP_136)
+			cmd_val |= SDXC_LongRsp;
+		if (cmd->flags & MMC_RSP_CRC)
+			cmd_val |= SDXC_CheckRspCRC;
+
+		if ((cmd->flags & MMC_CMD_MASK) == MMC_CMD_ADTC) {
+			cmd_val |= SDXC_DataExp | SDXC_WaitPreOver;
+			if (cmd->data->flags & MMC_DATA_STREAM) {
+				imask |= SDXC_AutoCMDDone;
+				cmd_val |= SDXC_Seqmod | SDXC_SendAutoStop;
+			}
+			if (cmd->data->stop) {
+				imask |= SDXC_AutoCMDDone;
+				cmd_val |= SDXC_SendAutoStop;
+			} else
+				imask |= SDXC_DataOver;
+
+			if (cmd->data->flags & MMC_DATA_WRITE)
+				cmd_val |= SDXC_Write;
+			else
+				host->wait_dma = 1;
+		} else
+			imask |= SDXC_CmdDone;
+	} else
+		imask |= SDXC_CmdDone;
+
+	dev_dbg(mmc_dev(host->mmc), "cmd %d(%08x) arg %x ie 0x%08x len %d\n",
+		cmd_val & 0x3f, cmd_val, cmd->arg, imask,
+		mrq->data ? mrq->data->blksz * mrq->data->blocks : 0);
+
+	spin_lock_irqsave(&host->lock, iflags);
+	host->mrq = mrq;
+	mci_writel(host, REG_IMASK, host->sdio_imask | imask);
+	spin_unlock_irqrestore(&host->lock, iflags);
+
+	mci_writel(host, REG_CARG, cmd->arg);
+	mci_writel(host, REG_CMDR, cmd_val);
+}
+
+static const struct of_device_id sunxi_mmc_of_match[] = {
+	{ .compatible = "allwinner,sun4i-a10-mmc", },
+	{ .compatible = "allwinner,sun5i-a13-mmc", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
+
+static struct mmc_host_ops sunxi_mmc_ops = {
+	.request	 = sunxi_mmc_request,
+	.set_ios	 = sunxi_mmc_set_ios,
+	.get_ro		 = mmc_gpio_get_ro,
+	.get_cd		 = mmc_gpio_get_cd,
+	.enable_sdio_irq = sunxi_mmc_enable_sdio_irq,
+	.hw_reset	 = sunxi_mmc_hw_reset,
+};
+
+static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
+				      struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	if (of_device_is_compatible(np, "allwinner,sun4i-a10-mmc"))
+		host->idma_des_size_bits = 13;
+	else
+		host->idma_des_size_bits = 16;
+
+	host->vmmc = devm_regulator_get_optional(&pdev->dev, "vmmc");
+	if (IS_ERR(host->vmmc) && PTR_ERR(host->vmmc) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	host->reg_base = devm_ioremap_resource(&pdev->dev,
+			      platform_get_resource(pdev, IORESOURCE_MEM, 0));
+	if (IS_ERR(host->reg_base))
+		return PTR_ERR(host->reg_base);
+
+	host->irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(&pdev->dev, host->irq, sunxi_mmc_irq, 0,
+			       "sunxi-mci", host);
+	if (ret)
+		return ret;
+	disable_irq(host->irq);
+
+	host->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(host->clk_ahb)) {
+		dev_err(&pdev->dev, "Could not get ahb clock\n");
+		return PTR_ERR(host->clk_ahb);
+	}
+
+	host->clk_mod = devm_clk_get(&pdev->dev, "mod");
+	if (IS_ERR(host->clk_mod)) {
+		dev_err(&pdev->dev, "Could not get mod clock\n");
+		return PTR_ERR(host->clk_mod);
+	}
+
+	return 0;
+}
+
+static int sunxi_mmc_probe(struct platform_device *pdev)
+{
+	struct sunxi_mmc_host *host;
+	struct mmc_host *mmc;
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev);
+	if (!mmc) {
+		dev_err(&pdev->dev, "mmc alloc host failed\n");
+		return -ENOMEM;
+	}
+
+	ret = mmc_of_parse(mmc);
+	if (ret)
+		goto error_free_host;
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	spin_lock_init(&host->lock);
+	tasklet_init(&host->tasklet, sunxi_mmc_tasklet, (unsigned long)host);
+
+	ret = sunxi_mmc_resource_request(host, pdev);
+	if (ret)
+		goto error_free_host;
+
+	host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+					  &host->sg_dma, GFP_KERNEL);
+	if (!host->sg_cpu) {
+		dev_err(&pdev->dev, "Failed to allocate DMA descriptor mem\n");
+		ret = -ENOMEM;
+		goto error_free_host;
+	}
+
+	mmc->ops		= &sunxi_mmc_ops;
+	mmc->max_blk_count	= 8192;
+	mmc->max_blk_size	= 4096;
+	mmc->max_segs		= PAGE_SIZE / sizeof(struct sunxi_idma_des);
+	mmc->max_seg_size	= (1 << host->idma_des_size_bits);
+	mmc->max_req_size	= mmc->max_seg_size * mmc->max_segs;
+	/* 400kHz ~ 50MHz */
+	mmc->f_min		=   400000;
+	mmc->f_max		= 50000000;
+	/* available voltages */
+	if (!IS_ERR(host->vmmc))
+		mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vmmc);
+	else
+		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+		MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR50 |
+		MMC_CAP_UHS_DDR50 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL |
+		MMC_CAP_DRIVER_TYPE_A;
+	if (host->bus_width == 4)
+		mmc->caps |= MMC_CAP_4_BIT_DATA;
+	mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP;
+
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto error_free_dma;
+
+	dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq);
+	platform_set_drvdata(pdev, mmc);
+	return 0;
+
+error_free_dma:
+	dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+error_free_host:
+	mmc_free_host(mmc);
+	return ret;
+}
+
+static int sunxi_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_host	*mmc = platform_get_drvdata(pdev);
+	struct sunxi_mmc_host *host = mmc_priv(mmc);
+
+	mmc_remove_host(mmc);
+	sunxi_mmc_exit_host(host);
+	tasklet_disable(&host->tasklet);
+	dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+	mmc_free_host(mmc);
+
+	return 0;
+}
+
+static struct platform_driver sunxi_mmc_driver = {
+	.driver = {
+		.name	= "sunxi-mci",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(sunxi_mmc_of_match),
+	},
+	.probe		= sunxi_mmc_probe,
+	.remove		= sunxi_mmc_remove,
+};
+module_platform_driver(sunxi_mmc_driver);
+
+MODULE_DESCRIPTION("Allwinner's SD/MMC Card Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("David Lanzend?rfer <david.lanzendoerfer@o2s.ch>");
+MODULE_ALIAS("platform:sunxi-mmc");
diff --git a/drivers/mmc/host/sunxi-mci.h b/drivers/mmc/host/sunxi-mci.h
new file mode 100644
index 0000000..f75b2fc
--- /dev/null
+++ b/drivers/mmc/host/sunxi-mci.h
@@ -0,0 +1,239 @@
+/*
+ * Driver for sunxi SD/MMC host controllers
+ * (C) Copyright 2007-2011 Reuuimlla Technology Co., Ltd.
+ * (C) Copyright 2007-2011 Aaron Maoye <leafy.myeh@reuuimllatech.com>
+ * (C) Copyright 2013-2013 O2S GmbH <www.o2s.ch>
+ * (C) Copyright 2013-2013 David Lanzend?rfer <david.lanzendoerfer@o2s.ch>
+ * (C) Copyright 2013-2013 Hans de Goede <hdegoede@redhat.com>
+ *
+ * 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.
+ */
+
+#ifndef __SUNXI_MCI_H__
+#define __SUNXI_MCI_H__
+
+/* register offset define */
+#define SDXC_REG_GCTRL	(0x00) /* SMC Global Control Register */
+#define SDXC_REG_CLKCR	(0x04) /* SMC Clock Control Register */
+#define SDXC_REG_TMOUT	(0x08) /* SMC Time Out Register */
+#define SDXC_REG_WIDTH	(0x0C) /* SMC Bus Width Register */
+#define SDXC_REG_BLKSZ	(0x10) /* SMC Block Size Register */
+#define SDXC_REG_BCNTR	(0x14) /* SMC Byte Count Register */
+#define SDXC_REG_CMDR	(0x18) /* SMC Command Register */
+#define SDXC_REG_CARG	(0x1C) /* SMC Argument Register */
+#define SDXC_REG_RESP0	(0x20) /* SMC Response Register 0 */
+#define SDXC_REG_RESP1	(0x24) /* SMC Response Register 1 */
+#define SDXC_REG_RESP2	(0x28) /* SMC Response Register 2 */
+#define SDXC_REG_RESP3	(0x2C) /* SMC Response Register 3 */
+#define SDXC_REG_IMASK	(0x30) /* SMC Interrupt Mask Register */
+#define SDXC_REG_MISTA	(0x34) /* SMC Masked Interrupt Status Register */
+#define SDXC_REG_RINTR	(0x38) /* SMC Raw Interrupt Status Register */
+#define SDXC_REG_STAS	(0x3C) /* SMC Status Register */
+#define SDXC_REG_FTRGL	(0x40) /* SMC FIFO Threshold Watermark Registe */
+#define SDXC_REG_FUNS	(0x44) /* SMC Function Select Register */
+#define SDXC_REG_CBCR	(0x48) /* SMC CIU Byte Count Register */
+#define SDXC_REG_BBCR	(0x4C) /* SMC BIU Byte Count Register */
+#define SDXC_REG_DBGC	(0x50) /* SMC Debug Enable Register */
+#define SDXC_REG_HWRST	(0x78) /* SMC Card Hardware Reset for Register */
+#define SDXC_REG_DMAC	(0x80) /* SMC IDMAC Control Register */
+#define SDXC_REG_DLBA	(0x84) /* SMC IDMAC Descriptor List Base Addre */
+#define SDXC_REG_IDST	(0x88) /* SMC IDMAC Status Register */
+#define SDXC_REG_IDIE	(0x8C) /* SMC IDMAC Interrupt Enable Register */
+#define SDXC_REG_CHDA	(0x90)
+#define SDXC_REG_CBDA	(0x94)
+
+#define mci_readl(host, reg) \
+	__raw_readl((host)->reg_base + SDXC_##reg)
+#define mci_writel(host, reg, value) \
+	__raw_writel((value), (host)->reg_base + SDXC_##reg)
+
+/* global control register bits */
+#define SDXC_SoftReset		BIT(0)
+#define SDXC_FIFOReset		BIT(1)
+#define SDXC_DMAReset		BIT(2)
+#define SDXC_HWReset		(SDXC_SoftReset|SDXC_FIFOReset|SDXC_DMAReset)
+#define SDXC_INTEnb		BIT(4)
+#define SDXC_DMAEnb		BIT(5)
+#define SDXC_DebounceEnb	BIT(8)
+#define SDXC_PosedgeLatchData	BIT(9)
+#define SDXC_DDR_MODE		BIT(10)
+#define SDXC_MemAccessDone	BIT(29)
+#define SDXC_AccessDoneDirect	BIT(30)
+#define SDXC_ACCESS_BY_AHB	BIT(31)
+#define SDXC_ACCESS_BY_DMA	(0U << 31)
+/* clock control bits */
+#define SDXC_CardClkOn		BIT(16)
+#define SDXC_LowPowerOn		BIT(17)
+/* bus width */
+#define SDXC_WIDTH1		(0)
+#define SDXC_WIDTH4		(1)
+#define SDXC_WIDTH8		(2)
+/* smc command bits */
+#define SDXC_RspExp		BIT(6)
+#define SDXC_LongRsp		BIT(7)
+#define SDXC_CheckRspCRC	BIT(8)
+#define SDXC_DataExp		BIT(9)
+#define SDXC_Write		BIT(10)
+#define SDXC_Seqmod		BIT(11)
+#define SDXC_SendAutoStop	BIT(12)
+#define SDXC_WaitPreOver	BIT(13)
+#define SDXC_StopAbortCMD	BIT(14)
+#define SDXC_SendInitSeq	BIT(15)
+#define SDXC_UPCLKOnly		BIT(21)
+#define SDXC_RdCEATADev		BIT(22)
+#define SDXC_CCSExp		BIT(23)
+#define SDXC_EnbBoot		BIT(24)
+#define SDXC_AltBootOpt		BIT(25)
+#define SDXC_BootACKExp		BIT(26)
+#define SDXC_BootAbort		BIT(27)
+#define SDXC_VolSwitch	        BIT(28)
+#define SDXC_UseHoldReg	        BIT(29)
+#define SDXC_Start	        BIT(31)
+/* interrupt bits */
+#define SDXC_RespErr		BIT(1)
+#define SDXC_CmdDone		BIT(2)
+#define SDXC_DataOver		BIT(3)
+#define SDXC_TxDataReq		BIT(4)
+#define SDXC_RxDataReq		BIT(5)
+#define SDXC_RespCRCErr		BIT(6)
+#define SDXC_DataCRCErr		BIT(7)
+#define SDXC_RespTimeout	BIT(8)
+#define SDXC_DataTimeout	BIT(9)
+#define SDXC_VolChgDone		BIT(10)
+#define SDXC_FIFORunErr		BIT(11)
+#define SDXC_HardWLocked	BIT(12)
+#define SDXC_StartBitErr	BIT(13)
+#define SDXC_AutoCMDDone	BIT(14)
+#define SDXC_EndBitErr		BIT(15)
+#define SDXC_SDIOInt		BIT(16)
+#define SDXC_CardInsert		BIT(30)
+#define SDXC_CardRemove		BIT(31)
+#define SDXC_IntErrBit		(SDXC_RespErr | SDXC_RespCRCErr | \
+				 SDXC_DataCRCErr | SDXC_RespTimeout | \
+				 SDXC_DataTimeout | SDXC_FIFORunErr | \
+				 SDXC_HardWLocked | SDXC_StartBitErr | \
+				 SDXC_EndBitErr) /* 0xbbc2 */
+#define SDXC_IntDoneBit		(SDXC_AutoCMDDone | SDXC_DataOver | \
+				 SDXC_CmdDone | SDXC_VolChgDone)
+/* status */
+#define SDXC_RXWLFlag		BIT(0)
+#define SDXC_TXWLFlag		BIT(1)
+#define SDXC_FIFOEmpty		BIT(2)
+#define SDXC_FIFOFull		BIT(3)
+#define SDXC_CardPresent	BIT(8)
+#define SDXC_CardDataBusy	BIT(9)
+#define SDXC_DataFSMBusy	BIT(10)
+#define SDXC_DMAReq		BIT(31)
+#define SDXC_FIFO_SIZE		(16)
+/* Function select */
+#define SDXC_CEATAOn		(0xceaaU << 16)
+#define SDXC_SendIrqRsp		BIT(0)
+#define SDXC_SDIORdWait		BIT(1)
+#define SDXC_AbtRdData		BIT(2)
+#define SDXC_SendCCSD		BIT(8)
+#define SDXC_SendAutoStopCCSD	BIT(9)
+#define SDXC_CEATADevIntEnb	BIT(10)
+/* IDMA controller bus mod bit field */
+#define SDXC_IDMACSoftRST	BIT(0)
+#define SDXC_IDMACFixBurst	BIT(1)
+#define SDXC_IDMACIDMAOn	BIT(7)
+#define SDXC_IDMACRefetchDES	BIT(31)
+/* IDMA status bit field */
+#define SDXC_IDMACTransmitInt	BIT(0)
+#define SDXC_IDMACReceiveInt	BIT(1)
+#define SDXC_IDMACFatalBusErr	BIT(2)
+#define SDXC_IDMACDesInvalid	BIT(4)
+#define SDXC_IDMACCardErrSum	BIT(5)
+#define SDXC_IDMACNormalIntSum	BIT(8)
+#define SDXC_IDMACAbnormalIntSum BIT(9)
+#define SDXC_IDMACHostAbtInTx	BIT(10)
+#define SDXC_IDMACHostAbtInRx	BIT(10)
+#define SDXC_IDMACIdle		(0U << 13)
+#define SDXC_IDMACSuspend	(1U << 13)
+#define SDXC_IDMACDESCRd	(2U << 13)
+#define SDXC_IDMACDESCCheck	(3U << 13)
+#define SDXC_IDMACRdReqWait	(4U << 13)
+#define SDXC_IDMACWrReqWait	(5U << 13)
+#define SDXC_IDMACRd		(6U << 13)
+#define SDXC_IDMACWr		(7U << 13)
+#define SDXC_IDMACDESCClose	(8U << 13)
+
+struct sunxi_idma_des {
+	u32	config;
+#define SDXC_IDMAC_DES0_DIC	BIT(1)  /* disable interrupt on completion */
+#define SDXC_IDMAC_DES0_LD	BIT(2)  /* last descriptor */
+#define SDXC_IDMAC_DES0_FD	BIT(3)  /* first descriptor */
+#define SDXC_IDMAC_DES0_CH	BIT(4)  /* chain mode */
+#define SDXC_IDMAC_DES0_ER	BIT(5)  /* end of ring */
+#define SDXC_IDMAC_DES0_CES	BIT(30) /* card error summary */
+#define SDXC_IDMAC_DES0_OWN	BIT(31) /* 1-idma owns it, 0-host owns it */
+
+	/*
+	 * If the idma-des-size-bits of property is ie 13, bufsize bits are:
+	 *  Bits  0-12: buf1 size
+	 *  Bits 13-25: buf2 size
+	 *  Bits 26-31: not used
+	 * Since we only ever set buf1 size, we can simply store it directly.
+	 */
+	u32	buf_size;
+	u32	buf_addr_ptr1;
+	u32	buf_addr_ptr2;
+};
+
+struct sunxi_mmc_host {
+	struct mmc_host *mmc;
+	struct regulator *vmmc;
+
+	/* IO mapping base */
+	void __iomem *reg_base;
+
+	spinlock_t lock;
+	struct tasklet_struct tasklet;
+
+	/* clock management */
+	struct clk *clk_ahb;
+	struct clk *clk_mod;
+
+	/* ios information */
+	u32		clk_mod_rate;
+	u32		bus_width;
+	u32		idma_des_size_bits;
+	u32		ddr;
+	u32		voltage_switching;
+
+	/* irq */
+	int		irq;
+	u32		int_sum;
+	u32		sdio_imask;
+
+	/* flags */
+	u32		power_on:1;
+	u32		io_flag:1;
+	u32		wait_dma:1;
+
+	dma_addr_t	sg_dma;
+	void		*sg_cpu;
+
+	struct mmc_request *mrq;
+	u32		ferror;
+};
+
+#define MMC_CLK_400K            0
+#define MMC_CLK_25M             1
+#define MMC_CLK_50M             2
+#define MMC_CLK_50MDDR          3
+#define MMC_CLK_50MDDR_8BIT     4
+#define MMC_CLK_100M            5
+#define MMC_CLK_200M            6
+#define MMC_CLK_MOD_NUM         7
+
+struct sunxi_mmc_clk_dly {
+	u32 mode;
+	u32 oclk_dly;
+	u32 sclk_dly;
+};
+
+#endif

^ permalink raw reply related

* [PATCH v2 2/6] clk: sunxi: Implement MMC phase control
From: David Lanzendörfer @ 2014-02-04 19:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191648.29809.14611.stgit@dizzy-6.o2s.ch>

From: Emilio L?pez <emilio@elopez.com.ar>

Signed-off-by: Emilio L?pez <emilio@elopez.com.ar>
---
 drivers/clk/sunxi/clk-sunxi.c |   35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index abb6c5a..33b9977 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -377,6 +377,41 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
 
 
 /**
+ * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
+ */
+
+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output)
+{
+	#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
+	#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
+
+	struct clk_composite *composite = to_clk_composite(hw);
+	struct clk_hw *rate_hw = composite->rate_hw;
+	struct clk_factors *factors = to_clk_factors(rate_hw);
+	unsigned long flags = 0;
+	u32 reg;
+
+	if (factors->lock)
+		spin_lock_irqsave(factors->lock, flags);
+
+	reg = readl(factors->reg);
+
+	/* set sample clock phase control */
+	reg &= ~(0x7 << 20);
+	reg |= ((sample & 0x7) << 20);
+
+	/* set output clock phase control */
+	reg &= ~(0x7 << 8);
+	reg |= ((output & 0x7) << 8);
+
+	writel(reg, factors->reg);
+
+	if (factors->lock)
+		spin_unlock_irqrestore(factors->lock, flags);
+}
+
+
+/**
  * sunxi_factors_clk_setup() - Setup function for factor clocks
  */
 

^ permalink raw reply related

* [PATCH v2 3/6] ARM: sunxi: clk: export clk_sunxi_mmc_phase_control
From: David Lanzendörfer @ 2014-02-04 19:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191648.29809.14611.stgit@dizzy-6.o2s.ch>

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 include/linux/clk/sunxi.h |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 include/linux/clk/sunxi.h

diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
new file mode 100644
index 0000000..1ef5c89
--- /dev/null
+++ b/include/linux/clk/sunxi.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 - Hans de Goede <hdegoede@redhat.com>
+ *
+ * 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.
+ */
+
+#ifndef __LINUX_CLK_SUNXI_H_
+#define __LINUX_CLK_SUNXI_H_
+
+#include <linux/clk.h>
+
+void clk_sunxi_mmc_phase_control(struct clk_hw *hw, u8 sample, u8 output);
+
+#endif

^ permalink raw reply related

* [PATCH v2 4/6] ARM: dts: sun7i: Add support for mmc
From: David Lanzendörfer @ 2014-02-04 19:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191648.29809.14611.stgit@dizzy-6.o2s.ch>


---
 arch/arm/boot/dts/sun7i-a20-cubieboard2.dts     |    8 +++
 arch/arm/boot/dts/sun7i-a20-cubietruck.dts      |    8 +++
 arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts |   23 +++++++++
 arch/arm/boot/dts/sun7i-a20.dtsi                |   61 +++++++++++++++++++++++
 4 files changed, 100 insertions(+)

diff --git a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
index 5c51cb8..ae800b6 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubieboard2.dts
@@ -34,6 +34,14 @@
 			};
 		};
 
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+			cd-gpios = <&pio 7 1 0>; /* PH1 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
 			led_pins_cubieboard2: led_pins at 0 {
 				allwinner,pins = "PH20", "PH21";
diff --git a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
index f9dcb61..370cef84 100644
--- a/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ b/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -19,6 +19,14 @@
 	compatible = "cubietech,cubietruck", "allwinner,sun7i-a20";
 
 	soc at 01c00000 {
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+			cd-gpios = <&pio 7 1 0>; /* PH1 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
 			led_pins_cubietruck: led_pins at 0 {
 				allwinner,pins = "PH7", "PH11", "PH20", "PH21";
diff --git a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
index ead3013..46dbe5b 100644
--- a/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts
@@ -34,7 +34,30 @@
 			};
 		};
 
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+			cd-gpios = <&pio 7 1 0>; /* PH1 */
+			status = "okay";
+		};
+
+		mmc3: mmc at 01c12000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc3_pins_a>;
+			pinctrl-1 = <&mmc3_cd_pin_olinuxinom>;
+			cd-gpios = <&pio 7 11 0>; /* PH11 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
+			mmc3_cd_pin_olinuxinom: mmc3_cd_pin at 0 {
+				allwinner,pins = "PH11";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
 			led_pins_olinuxino: led_pins at 0 {
 				allwinner,pins = "PH2";
 				allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 119f066..4cd6210 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -355,6 +355,46 @@
 			#size-cells = <0>;
 		};
 
+		mmc0: mmc at 01c0f000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c0f000 0x1000>;
+			clocks = <&ahb_gates 8>, <&mmc0_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <0 32 4>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc1: mmc at 01c10000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c10000 0x1000>;
+			clocks = <&ahb_gates 9>, <&mmc1_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <0 33 4>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc2: mmc at 01c11000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c11000 0x1000>;
+			clocks = <&ahb_gates 10>, <&mmc2_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <0 34 4>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc3: mmc at 01c12000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c12000 0x1000>;
+			clocks = <&ahb_gates 11>, <&mmc3_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <0 35 4>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
 		pio: pinctrl at 01c20800 {
 			compatible = "allwinner,sun7i-a20-pinctrl";
 			reg = <0x01c20800 0x400>;
@@ -432,6 +472,27 @@
 				allwinner,drive = <0>;
 				allwinner,pull = <0>;
 			};
+
+			mmc0_pins_a: mmc0 at 0 {
+				allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+				allwinner,function = "mmc0";
+				allwinner,drive = <3>;
+				allwinner,pull = <0>;
+			};
+
+			mmc0_cd_pin_reference_design: mmc0_cd_pin at 0 {
+				allwinner,pins = "PH1";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			mmc3_pins_a: mmc3 at 0 {
+				allwinner,pins = "PI4","PI5","PI6","PI7","PI8","PI9";
+				allwinner,function = "mmc3";
+				allwinner,drive = <3>;
+				allwinner,pull = <0>;
+			};
 		};
 
 		timer at 01c20c00 {

^ permalink raw reply related

* [PATCH v2 5/6] ARM: dts: sun4i: Add support for mmc
From: David Lanzendörfer @ 2014-02-04 19:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191648.29809.14611.stgit@dizzy-6.o2s.ch>


---
 arch/arm/boot/dts/sun4i-a10-a1000.dts      |    8 ++++
 arch/arm/boot/dts/sun4i-a10-cubieboard.dts |    8 ++++
 arch/arm/boot/dts/sun4i-a10.dtsi           |   54 ++++++++++++++++++++++++++++
 3 files changed, 70 insertions(+)

diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
index d4b081d..a879ef3 100644
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
@@ -35,6 +35,14 @@
 			};
 		};
 
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+			cd-gpios = <&pio 7 1 0>; /* PH1 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
 			emac_power_pin_a1000: emac_power_pin at 0 {
 				allwinner,pins = "PH15";
diff --git a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
index b139ee6..20b976a 100644
--- a/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
+++ b/arch/arm/boot/dts/sun4i-a10-cubieboard.dts
@@ -33,6 +33,14 @@
 			};
 		};
 
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_reference_design>;
+			cd-gpios = <&pio 7 1 0>; /* PH1 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
 			led_pins_cubieboard: led_pins at 0 {
 				allwinner,pins = "PH20", "PH21";
diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 040bb0e..c941ca3 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -330,6 +330,46 @@
 			#size-cells = <0>;
 		};
 
+		mmc0: mmc at 01c0f000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c0f000 0x1000>;
+			clocks = <&ahb_gates 8>, <&mmc0_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <32>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc1: mmc at 01c10000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c10000 0x1000>;
+			clocks = <&ahb_gates 9>, <&mmc1_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <33>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc2: mmc at 01c11000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c11000 0x1000>;
+			clocks = <&ahb_gates 10>, <&mmc2_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <34>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc3: mmc at 01c12000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c12000 0x1000>;
+			clocks = <&ahb_gates 11>, <&mmc3_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <35>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
 		intc: interrupt-controller at 01c20400 {
 			compatible = "allwinner,sun4i-ic";
 			reg = <0x01c20400 0x400>;
@@ -400,6 +440,20 @@
 				allwinner,drive = <0>;
 				allwinner,pull = <0>;
 			};
+
+			mmc0_pins_a: mmc0 at 0 {
+				allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+				allwinner,function = "mmc0";
+				allwinner,drive = <3>;
+				allwinner,pull = <0>;
+			};
+
+			mmc0_cd_pin_reference_design: mmc0_cd_pin at 0 {
+				allwinner,pins = "PH1";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
 		};
 
 		timer at 01c20c00 {

^ permalink raw reply related

* [PATCH v2 6/6] ARM: dts: sun5i: Add support for mmc
From: David Lanzendörfer @ 2014-02-04 19:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191648.29809.14611.stgit@dizzy-6.o2s.ch>


---
 arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts |   30 +++++++++++++++
 arch/arm/boot/dts/sun5i-a10s.dtsi                |   44 ++++++++++++++++++++++
 arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts  |   15 ++++++++
 arch/arm/boot/dts/sun5i-a13-olinuxino.dts        |   15 ++++++++
 arch/arm/boot/dts/sun5i-a13.dtsi                 |   37 +++++++++++++++++++
 5 files changed, 141 insertions(+)

diff --git a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
index 3c9f8b3..7189adf55 100644
--- a/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
@@ -34,7 +34,37 @@
 			};
 		};
 
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_olinuxino_micro>;
+			cd-gpios = <&pio 6 1 0>; /* PG1 */
+			status = "okay";
+		};
+
+		mmc1: mmc at 01c10000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc1_pins_a>;
+			pinctrl-1 = <&mmc1_cd_pin_olinuxino_micro>;
+			cd-gpios = <&pio 6 13 0>; /* PG13 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
+			mmc0_cd_pin_olinuxino_micro: mmc0_cd_pin at 0 {
+				allwinner,pins = "PG1";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
+			mmc1_cd_pin_olinuxino_micro: mmc1_cd_pin at 0 {
+				allwinner,pins = "PG13";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
 			led_pins_olinuxino: led_pins at 0 {
 				allwinner,pins = "PE3";
 				allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index ea16054..abff7f8 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -293,6 +293,36 @@
 			#size-cells = <0>;
 		};
 
+		mmc0: mmc at 01c0f000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c0f000 0x1000>;
+			clocks = <&ahb_gates 8>, <&mmc0_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <32>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc1: mmc at 01c10000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c10000 0x1000>;
+			clocks = <&ahb_gates 9>, <&mmc1_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <33>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc2: mmc at 01c11000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c11000 0x1000>;
+			clocks = <&ahb_gates 10>, <&mmc2_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <34>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
 		intc: interrupt-controller at 01c20400 {
 			compatible = "allwinner,sun4i-ic";
 			reg = <0x01c20400 0x400>;
@@ -363,6 +393,20 @@
 				allwinner,drive = <0>;
 				allwinner,pull = <0>;
 			};
+
+			mmc0_pins_a: mmc0 at 0 {
+				allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+				allwinner,function = "mmc0";
+				allwinner,drive = <3>;
+				allwinner,pull = <0>;
+			};
+
+			mmc1_pins_a: mmc1 at 0 {
+				allwinner,pins = "PG3","PG4","PG5","PG6","PG7","PG8";
+				allwinner,function = "mmc1";
+				allwinner,drive = <3>;
+				allwinner,pull = <0>;
+			};
 		};
 
 		timer at 01c20c00 {
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
index fe2ce0a..6ae5867 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
@@ -20,7 +20,22 @@
 	compatible = "olimex,a13-olinuxino-micro", "allwinner,sun5i-a13";
 
 	soc at 01c00000 {
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_olinuxinom>;
+			cd-gpios = <&pio 6 0 0>; /* PG0 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
+			mmc0_cd_pin_olinuxinom: mmc0_cd_pin at 0 {
+				allwinner,pins = "PG0";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
 			led_pins_olinuxinom: led_pins at 0 {
 				allwinner,pins = "PG9";
 				allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
index a4ba5ff..b23237b 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -19,7 +19,22 @@
 	compatible = "olimex,a13-olinuxino", "allwinner,sun5i-a13";
 
 	soc at 01c00000 {
+		mmc0: mmc at 01c0f000 {
+			pinctrl-names = "default", "default";
+			pinctrl-0 = <&mmc0_pins_a>;
+			pinctrl-1 = <&mmc0_cd_pin_olinuxino>;
+			cd-gpios = <&pio 6 0 0>; /* PG0 */
+			status = "okay";
+		};
+
 		pinctrl at 01c20800 {
+			mmc0_cd_pin_olinuxino: mmc0_cd_pin at 0 {
+				allwinner,pins = "PG0";
+				allwinner,function = "gpio_in";
+				allwinner,drive = <0>;
+				allwinner,pull = <0>;
+			};
+
 			led_pins_olinuxino: led_pins at 0 {
 				allwinner,pins = "PG9";
 				allwinner,function = "gpio_out";
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index 320335a..5d71c82 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -274,6 +274,36 @@
 		#size-cells = <1>;
 		ranges;
 
+		mmc0: mmc at 01c0f000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c0f000 0x1000>;
+			clocks = <&ahb_gates 8>, <&mmc0_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <32>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc1: mmc at 01c10000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c10000 0x1000>;
+			clocks = <&ahb_gates 9>, <&mmc1_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <33>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
+		mmc2: mmc at 01c11000 {
+			compatible = "allwinner,sun5i-a13-mmc";
+			reg = <0x01c11000 0x1000>;
+			clocks = <&ahb_gates 10>, <&mmc2_clk>;
+			clock-names = "ahb", "mod";
+			interrupts = <34>;
+			bus-width = <4>;
+			status = "disabled";
+		};
+
 		intc: interrupt-controller at 01c20400 {
 			compatible = "allwinner,sun4i-ic";
 			reg = <0x01c20400 0x400>;
@@ -326,6 +356,13 @@
 				allwinner,drive = <0>;
 				allwinner,pull = <0>;
 			};
+
+			mmc0_pins_a: mmc0 at 0 {
+				allwinner,pins = "PF0","PF1","PF2","PF3","PF4","PF5";
+				allwinner,function = "mmc0";
+				allwinner,drive = <3>;
+				allwinner,pull = <0>;
+			};
 		};
 
 		timer at 01c20c00 {

^ permalink raw reply related

* [PATCH 09/10] watchdog: xilinx: Add missing binding
From: Arnd Bergmann @ 2014-02-04 19:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4c4539fe-e810-4c0a-9a01-c1e4c67ea661@AM1EHSMHS007.ehs.local>

On Monday 03 February 2014, Michal Simek wrote:
> On 02/03/2014 04:32 PM, Arnd Bergmann wrote:
> > On Monday 03 February 2014 16:13:47 Michal Simek wrote:
> >> Intention wasn't to fix binding but document current one
> >> which is in mainline for a long time.
> > 
> > Ok, I see.
> > 
> >> Apart of this - yes, wdt-enable-once is nowayout and wdt-interval should be timeout
> >> is seconds, and clock-frequency should go out and use CCF for getting clock.
> > 
> > Could we make a common binding then, and document that the xilinx
> > watchdog can optionally provide either one?
> 
> Do you mean to have 2 DT bindings?
> 
> This binding is used from 2011-07.
> It means it was generated for all hw designs at least from this time.
> I would say from DT usage on Microblaze because it is not special case
> in our dt generator.

I certainly wasn't suggesting to break the binding, quite the contrary.
What I tried to say is that the properties look like they should be
useful for different kinds of watchdogs, not just xilinx, so it would
be good to have a common definition using generic strings.

The xilinx driver would definitely have to keep supporting the traditional
property names, but it could also support the generic names in the
future.

> xlnx,XXX are XXX parameters which you have to setup in tools
> and get synthesized. This is valid for all xilinx IPs. We have full
> IP description by generating xlnx,XXX parameters directly from tools
> because we know all variants which can happen.
>
> Just back to your previous post:
> "I'm not sure about the enable-once flag, which seems to just map to the
> "nowayout" watchdog option that is not a hardware feature at all"
> this is hw feature which you can select in tools because this is fpga. :-)

Ah, so you mean the properties are not settings that the driver
programs into the hardware, but they are hardware properties that the
driver reports to user space?

	Arnd

^ permalink raw reply

* Extending OPP bindings
From: Nishanth Menon @ 2014-02-04 19:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204182220.GQ22609@sirena.org.uk>

On 02/04/2014 12:22 PM, Mark Brown wrote:
> On Tue, Feb 04, 2014 at 12:01:11PM -0600, Nishanth Menon wrote:
> 
>> As long as the key to the data sets are all the same (frequency),
>> information in data set #0 is maintained. It would be in our common
>> long term interest to maintain the split.
> 
> You're assuming that the frequency is a unique key here.  That may not
> be the case, for example two OPPs might have the same CPU clock
> (assuming that's the frequency you're referring to) but different bus
> clocking and of course the CPUs or CPU clusters might be individually
> scalable (this is common in big.LITTLE designs I think).
> 
Which is why OPPs are maintained per device, bus OPPs belong to bus
device (in TI terminology, we'd be talking of cross domain dependency
here for maintaining asynchronous bridge timing closure constraints -
but ofcourse, other SoCs may or maynot have such constraints). For
scaling bus frequency, we already have infrastructure in place - clock
notifiers - discussion of using that is much deeper topic of it's own.

for each processor that is uniquely transitioning, we'd have it's own
sets of OPPs - the correct representation of the device node is the
key there.

-- 
Regards,
Nishanth Menon

^ permalink raw reply

* [PATCH v2 0/6] ARM: sunxi: Add driver for SD/MMC hosts found on allwinner sunxi SOCs
From: David Lanzendörfer @ 2014-02-04 19:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204191648.29809.14611.stgit@dizzy-6.o2s.ch>

Hi
I forgot to mention that the autoparenting patch of Emilios is a crucial 
depency...
http://git.o2s.ch/?p=linux-next.git;a=commit;h=f8e936772672a3a6ec934558d2a7aef030c663c4
Without it, the clock will return the wrong value and the card will refuse to 
initialize

regards
david
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140204/201e6182/attachment.sig>

^ permalink raw reply

* [PATCH v2 0/5] net: phy: Ethernet PHY powerdown optimization
From: Sebastian Hesselbarth @ 2014-02-04 19:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20131217.144313.1563516273987934449.davem@davemloft.net>

On 12/17/2013 08:43 PM, David Miller wrote:
> From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Date: Fri, 13 Dec 2013 10:20:24 +0100
>
>> This is v2 of the ethernet PHY power optimization patches to reduce
>> power consumption of network PHYs with link that are either unused or
>> the corresponding netdev is down.
>>
>> Compared to the last version, this patch set drops a patch to disable
>> unused PHYs after late initcall, as it is not compatible with a modular
>> mdio bus [1]. I'll investigate different ways to have a modular mdio bus
>> driver get notified when driver loading is done.
>>
>> Again, a branch with v2 applied to v3.13-rc2 can also be found at
>> https://github.com/shesselba/linux-dove.git topic/ethphy-power-v2
>>
>> [1] http://www.spinics.net/lists/arm-kernel/msg293028.html
>
> Series applied, thanks.
>

David, Mungunthan, Florian,

as expected the above patches create a Linux to bootloader dependency
that surfaces dumb bootloaders not initializing PHYs correctly.

Andrew has a Kirkwood based board that does not power-up and restart
auto-negotiation on the powered down PHY after a warm restart. While
this specific bootloader allows a soft-workaround by issuing the
required PHY writes before accessing the interface, others may not.

I think we should allow the user to soft-disable the automatic
power-down of PHYs, i.e. by exploiting a kernel parameter.

Do you have any preference for naming it? My call would be something
like libphy.suspend_halted = [0,1] with 1 being the default.

Sebastian

^ permalink raw reply

* [PATCH v3 0/4] In-kernel PSCI v0.2 emulation for KVM ARM/ARM64
From: Christoffer Dall @ 2014-02-04 19:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391507296-2099-1-git-send-email-anup.patel@linaro.org>

On Tue, Feb 04, 2014 at 03:18:12PM +0530, Anup Patel wrote:
> Currently, KVM ARM/ARM64 only provides in-kernel emulation of Power State
> and Coordination Interface (PSCI) v0.1.
> 
> This patchset aims at providing newer PSCI v0.2 for KVM ARM/ARM64 VCPUs
> such that it does not break current KVM ARM/ARM64 ABI. Also, the patchset
> provides emulation of only few PSCI v0.2 functions such as PSCI_VERSION,
> CPU_ON, and CPU_OFF. Emulation of other PSCI v0.2 functions will be added
> later.
> 
> The user space tools (i.e. QEMU or KVMTOOL) will have to explicitly enable
> KVM_ARM_VCPU_PSCI_0_2 feature using KVM_ARM_VCPU_INIT ioctl for providing
> PSCI v0.2 to VCPUs.
> 
> Changlog:
> 
> V3:
>  - Make KVM_ARM_VCPU_PSCI_0_2 feature experiementatl for now so that
>    it fails for user space till all mandatory PSCI v0.2 functions are
>    emulated by KVM ARM/ARM64
>  - Have separate patch for making KVM_ARM_VCPU_PSCI_0_2 feature available
>    to user space. This patch can be defferred for now.
> 

I think we just want the feature bit when there's proper PSCI 0.2
support as per Mark's comments, so I'll hold off with reviewing until we
have a more complete patch set.

Thanks,
-Christoffer

^ permalink raw reply

* [PATCH v3 2/5] ASoC: tda998x: add a codec driver for the TDA998x
From: Mark Brown @ 2014-02-04 19:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204195921.5ace6163@armhf>

On Tue, Feb 04, 2014 at 07:59:21PM +0100, Jean-Francois Moine wrote:
> Mark Brown <broonie@kernel.org> wrote:

> > You shouldn't be representing this as a separate node in the DT unless
> > there really is a distinct and reusable IP, otherwise you're putting
> > Linux implementation details in there.  Describe the hardware, not the
> > implemementation.

> If there is no 'compatible' node for the tda998x CODEC in the DT, the
> simple-card is not usable, simply because you want the CODEC DAIs to be
> defined by 'phandle + index' instead of by DAI name.

This is a bit circular, though - it's only happening because you decided
to push everything onto a subnode in the DT.  If you just work with the
existing device this is no different to any other device.

> > > I don't understand. The tda CODEC can only be used with the TDA998x I2C
> > > driver. It might have been included in the tda998x source as well.

> > You shouldn't have the default settings there at all, that's not the
> > normal idiom for MFDs.  I'd also not expect to have to build the CODEC
> > driver just because I built the DRM component.

> As the tda998x handles audio in HDMI, it would be a pity if you should
> connect an other cable to your screen.

My screen doesn't have any speakers anyway :P (I'm writing this on a
computer with the monitor connected via HDMI).  Besides, this is more
about build coverage stuff than anything else.

> So, as I understand from your remarks, the CODEC should be included in
> the tda998x driver, and, then, as the simple-card cannot be used, there
> should be a Cubox specific audio card driver for the (kirkwood audio +
> tda998x HDMI + S/PDIF) set. Am I right?

No, it shouldn't be.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140204/3a6f5542/attachment.sig>

^ permalink raw reply

* [ath9k-devel] [PATCH 1/3] ath9k: Fix build error on ARM
From: Joe Perches @ 2014-02-04 19:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3469296.SINb5BZOG8@wuerfel>

On Tue, 2014-02-04 at 19:40 +0100, Arnd Bergmann wrote:
> On Tuesday 04 February 2014 08:36:36 Joe Perches wrote:
> > On Tue, 2014-02-04 at 08:03 +0100, Holger Schurig wrote:
> > > Joe, look in linux/arch/arm/include/asm/delay.h. The macro udelay
> > > cannot handle large values because of lost-of-precision.
> > > 
> > > IMHO udelay on ARM is broken, because it also cannot work with fast
> > > ARM processors (where bogomips >= 3355, which is in sight now). It's
> > > just not broken enought that someone did something against it ...   so
> > > the current kludge is good enought.
> > 
> > Maybe something like this would be better?
> > 
> 
> I actually like the fact that we get link errors for insane 'udelay'
> times.

For static values yes, for computed values no.

This emits a warning/dump_stack on the non-static
values.  It could also emit some similar #warning
on static values > insane too.

^ permalink raw reply

* [PATCH] ARM: pxa: fix various compilation problems
From: Linus Walleij @ 2014-02-04 19:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4895932.cC8EyYOxb5@wuerfel>

On Tue, Feb 4, 2014 at 3:56 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Tuesday 04 February 2014 13:53:07 Linus Walleij wrote:
>> Hi ARM SoC folks: please apply this patch directly to the ARM
>> SoC tree fixes branch if you are happy with it.
>
> It's also needed for 3.13-backports, right?

Yes. Tagging for stable # v3.13+ should do the trick.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] arm64: Add architecture support for PCI
From: Arnd Bergmann @ 2014-02-04 19:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_JsqLN4RjVzNCfZ50K44RcP61Z8zFOVnpY1+CfVFz_QnSBEg@mail.gmail.com>

On Tuesday 04 February 2014, Rob Herring wrote:
> > Here is how a sane person would read SBSA to create a compliant
> > implementation:
> 
> s/sane/software/

> > Here is how a crazy person would read the same sentence in the SBSA:
> 
> s/crazy/hardware/

Not much of a difference, apparently ...

> My money is on the latter. I think non-PCI implementations of xHCI
> interfaces will be common. This was certainly the case at Calxeda in
> what was believed to be a SBSA compliant SOC.

I just looked up the EHCI and xHCI specs and am shocked to see that
the PCI config space access for both is an optional part of the
spec, so that assertion may well have been correct.

On the other hand, it does seem impossible to create a compliant
AHCI implementation without making it show up as a PCI function,
so any SBSA compliant SoC that contains AHCI already has to have
all the bits for doing the same on USB.

> However, I think PCI
> device or not is the least of the issues and all the other examples
> you list are the difficult ones to deal with.

Agreed. But if they get the difficult problems right, it's
trivial to also do the PCI config space either in the way
that Jason described, or as a separate PCI domain. In the worst
case, it could still be faked up by a secure-mode firmware
catching all config space accesses.

	Arnd

^ permalink raw reply

* [PATCH v2 0/5] Add Broadcom Kona PWM Support
From: Tim Kryger @ 2014-02-04 19:51 UTC (permalink / raw)
  To: linux-arm-kernel

This series introduces the driver for the Kona PWM controller found in
Broadcom mobile SoCs like bcm281xx and updates the device tree and the
defconfig to enable use of this hardware on the bcm28155 AP board.

Changes since v1:
  - Fixed up macros to be clearer and more complete
  - Corrected spelling and punctuation mistakes
  - Added support for polarity
  - Made peripheral clock use more efficient
  - Made prescale and duty computation clearer
  - Moved Makefile addition to keep alphabetical
  - Split complex lines into multiple steps

Tim Kryger (5):
  Documentation: dt: Add Kona PWM binding
  pwm: kona: Introduce Kona PWM controller support
  ARM: dts: Declare the PWM for bcm11351 (bcm281xx)
  ARM: dts: Enable the PWM for bcm28155 AP board
  ARM: bcm_defconfig: Enable PWM and Backlight

 .../devicetree/bindings/pwm/bcm-kona-pwm.txt       |  24 ++
 arch/arm/boot/dts/bcm11351.dtsi                    |   8 +
 arch/arm/boot/dts/bcm28155-ap.dts                  |   4 +
 arch/arm/configs/bcm_defconfig                     |   2 +
 drivers/pwm/Kconfig                                |  10 +
 drivers/pwm/Makefile                               |   1 +
 drivers/pwm/pwm-bcm-kona.c                         | 291 +++++++++++++++++++++
 7 files changed, 340 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/bcm-kona-pwm.txt
 create mode 100644 drivers/pwm/pwm-bcm-kona.c

-- 
1.8.0.1

^ 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