SUPERH platform development
 help / color / mirror / Atom feed
* [RFC][PATCH 1/3] dmaengine: shdma: add .no_error_irq flag
From: Shimoda, Yoshihiro @ 2012-01-05  5:41 UTC (permalink / raw)
  To: linux-sh

The USB-DMAC/SUDMAC don't have the interrupt of DMAC Address Error.
So, this patch adds the .no_error_irq flag.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/dma/shdma.c    |   50 ++++++++++++++++++++++++++---------------------
 include/linux/sh_dma.h |    1 +
 2 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 81809c2..97f7d24 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -1151,7 +1151,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 	struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
 	unsigned long irqflags = IRQF_DISABLED,
 		chan_flag[SH_DMAC_MAX_CHANNELS] = {};
-	int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
+	int errirq = 0, chan_irq[SH_DMAC_MAX_CHANNELS];
 	int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
 	struct sh_dmae_device *shdev;
 	struct resource *chan, *dmars, *errirq_res, *chanirq_res;
@@ -1259,26 +1259,31 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 	shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;

 #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
-	chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
-
-	if (!chanirq_res)
+	if (pdata->no_error_irq) {
 		chanirq_res = errirq_res;
-	else
-		irqres++;
-
-	if (chanirq_res = errirq_res ||
-	    (errirq_res->flags & IORESOURCE_BITS) = IORESOURCE_IRQ_SHAREABLE)
-		irqflags = IRQF_SHARED;
-
-	errirq = errirq_res->start;
-
-	err = request_irq(errirq, sh_dmae_err, irqflags,
-			  "DMAC Address Error", shdev);
-	if (err) {
-		dev_err(&pdev->dev,
-			"DMA failed requesting irq #%d, error %d\n",
-			errirq, err);
-		goto eirq_err;
+	} else {
+		chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+
+		if (!chanirq_res)
+			chanirq_res = errirq_res;
+		else
+			irqres++;
+
+		if (chanirq_res = errirq_res ||
+		    (errirq_res->flags & IORESOURCE_BITS) =
+		    IORESOURCE_IRQ_SHAREABLE)
+			irqflags = IRQF_SHARED;
+
+		errirq = errirq_res->start;
+
+		err = request_irq(errirq, sh_dmae_err, irqflags,
+				  "DMAC Address Error", shdev);
+		if (err) {
+			dev_err(&pdev->dev,
+				"DMA failed requesting irq #%d, error %d\n",
+				errirq, err);
+			goto eirq_err;
+		}
 	}

 #else
@@ -1346,7 +1351,8 @@ chan_probe_err:
 	sh_dmae_chan_remove(shdev);

 #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
-	free_irq(errirq, shdev);
+	if (!pdata->no_error_irq)
+		free_irq(errirq, shdev);
 eirq_err:
 #endif
 rst_err:
@@ -1383,7 +1389,7 @@ static int __exit sh_dmae_remove(struct platform_device *pdev)

 	dma_async_device_unregister(&shdev->common);

-	if (errirq > 0)
+	if (!shdev->pdata->no_error_irq && errirq > 0)
 		free_irq(errirq, shdev);

 	spin_lock_irq(&sh_dmae_lock);
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index cb2dd11..b638f42 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -68,6 +68,7 @@ struct sh_dmae_pdata {
 	unsigned int dmaor_is_32bit:1;
 	unsigned int needs_tend_set:1;
 	unsigned int no_dmars:1;
+	unsigned int no_error_irq:1;
 };

 /* DMA register */
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH 1/2] usb: renesas_usbhs: add IRQ resource decoding for IRQF_SHARED
From: Kuninori Morimoto @ 2012-01-05  5:31 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <4F05318D.6070505@renesas.com>


Hi Shimoda-san

Thank you for your patch.

> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> ---
>  drivers/usb/renesas_usbhs/common.c |   11 ++++++-----
>  drivers/usb/renesas_usbhs/common.h |    1 +
>  drivers/usb/renesas_usbhs/mod.c    |    2 +-
>  3 files changed, 8 insertions(+), 6 deletions(-)

Can you please add the reason why this IRQF_SHARED is needed on renesas_usbhs ?

Best regards
---
Kuninori Morimoto

^ permalink raw reply

* [PATCH 2/2] usb: renesas_usbhs: add support for SUDMAC
From: Shimoda, Yoshihiro @ 2012-01-05  5:13 UTC (permalink / raw)
  To: linux-sh

The SUDMAC uses 8-bit width only. So, when the driver uses SUDMAC,
we have to clear the MBW_32.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/usb/renesas_usbhs/fifo.c  |    6 +++++-
 include/linux/usb/renesas_usbhs.h |    1 +
 2 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index ffdf5d1..918a1da 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -23,6 +23,7 @@
 #define usbhsf_get_cfifo(p)	(&((p)->fifo_info.cfifo))
 #define usbhsf_get_d0fifo(p)	(&((p)->fifo_info.d0fifo))
 #define usbhsf_get_d1fifo(p)	(&((p)->fifo_info.d1fifo))
+#define usbhsf_is_cfifo(p, f)	(usbhsf_get_cfifo(p) = f)

 #define usbhsf_fifo_is_busy(f)	((f)->pipe) /* see usbhs_pipe_select_fifo */

@@ -304,7 +305,10 @@ static int usbhsf_fifo_select(struct usbhs_pipe *pipe,
 	}

 	/* "base" will be used below  */
-	usbhs_write(priv, fifo->sel, base | MBW_32);
+	if (usbhs_get_dparam(priv, has_sudmac) && !usbhsf_is_cfifo(priv, fifo))
+		usbhs_write(priv, fifo->sel, base);
+	else
+		usbhs_write(priv, fifo->sel, base | MBW_32);

 	/* check ISEL and CURPIPE value */
 	while (timeout--) {
diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h
index e5a40c3..f60db75 100644
--- a/include/linux/usb/renesas_usbhs.h
+++ b/include/linux/usb/renesas_usbhs.h
@@ -141,6 +141,7 @@ struct renesas_usbhs_driver_param {
 	 * option:
 	 */
 	u32 has_otg:1; /* for controlling PWEN/EXTLP */
+	u32 has_sudmac:1; /* for SUDMAC */
 };

 /*
-- 
1.7.1

^ permalink raw reply related

* [PATCH 1/2] usb: renesas_usbhs: add IRQ resource decoding for
From: Shimoda, Yoshihiro @ 2012-01-05  5:13 UTC (permalink / raw)
  To: linux-sh

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/usb/renesas_usbhs/common.c |   11 ++++++-----
 drivers/usb/renesas_usbhs/common.h |    1 +
 drivers/usb/renesas_usbhs/mod.c    |    2 +-
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index 08c679c..75f7d08 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -410,8 +410,7 @@ static int usbhs_probe(struct platform_device *pdev)
 	struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
 	struct renesas_usbhs_driver_callback *dfunc;
 	struct usbhs_priv *priv;
-	struct resource *res;
-	unsigned int irq;
+	struct resource *res, *irq_res;
 	int ret;

 	/* check platform information */
@@ -423,8 +422,8 @@ static int usbhs_probe(struct platform_device *pdev)

 	/* platform data */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (!res || (int)irq <= 0) {
+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res || !irq_res) {
 		dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n");
 		return -ENODEV;
 	}
@@ -473,7 +472,9 @@ static int usbhs_probe(struct platform_device *pdev)
 	/*
 	 * priv settings
 	 */
-	priv->irq	= irq;
+	priv->irq	= irq_res->start;
+	if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE)
+		priv->irqflags = IRQF_SHARED;
 	priv->pdev	= pdev;
 	INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
 	spin_lock_init(usbhs_priv_to_lock(priv));
diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h
index 8729da5..353ab51 100644
--- a/drivers/usb/renesas_usbhs/common.h
+++ b/drivers/usb/renesas_usbhs/common.h
@@ -241,6 +241,7 @@ struct usbhs_priv {

 	void __iomem *base;
 	unsigned int irq;
+	unsigned long irqflags;

 	struct renesas_usbhs_platform_callback	pfunc;
 	struct renesas_usbhs_driver_param	dparam;
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c
index ad96a38..9499fae 100644
--- a/drivers/usb/renesas_usbhs/mod.c
+++ b/drivers/usb/renesas_usbhs/mod.c
@@ -150,7 +150,7 @@ int usbhs_mod_probe(struct usbhs_priv *priv)

 	/* irq settings */
 	ret = request_irq(priv->irq, usbhs_interrupt,
-			  0, dev_name(dev), priv);
+			  priv->irqflags, dev_name(dev), priv);
 	if (ret) {
 		dev_err(dev, "irq request err\n");
 		goto mod_init_gadget_err;
-- 
1.7.1

^ permalink raw reply related

* [PATCH] sh: add platform_device for renesas_usbhs in board-sh7757lcr
From: Shimoda, Yoshihiro @ 2012-01-05  5:08 UTC (permalink / raw)
  To: linux-sh

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 arch/sh/boards/board-sh7757lcr.c |   39 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
index 895e337..0838154 100644
--- a/arch/sh/boards/board-sh7757lcr.c
+++ b/arch/sh/boards/board-sh7757lcr.c
@@ -19,6 +19,7 @@
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/sh_eth.h>
+#include <linux/usb/renesas_usbhs.h>
 #include <cpu/sh7757.h>
 #include <asm/heartbeat.h>

@@ -264,6 +265,43 @@ static struct platform_device sdhi_device = {
 	},
 };

+static int usbhs0_get_id(struct platform_device *pdev)
+{
+	return USBHS_GADGET;
+}
+
+static struct renesas_usbhs_platform_info usb0_data = {
+	.platform_callback = {
+		.get_id = usbhs0_get_id,
+	},
+	.driver_param = {
+		.buswait_bwait = 5,
+	}
+};
+
+static struct resource usb0_resources[] = {
+	[0] = {
+		.start	= 0xfe450000,
+		.end	= 0xfe4501ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 50,
+		.end	= 50,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device usb0_device = {
+	.name		= "renesas_usbhs",
+	.id		= 0,
+	.dev = {
+		.platform_data		= &usb0_data,
+	},
+	.num_resources	= ARRAY_SIZE(usb0_resources),
+	.resource	= usb0_resources,
+};
+
 static struct platform_device *sh7757lcr_devices[] __initdata = {
 	&heartbeat_device,
 	&sh7757_eth0_device,
@@ -272,6 +310,7 @@ static struct platform_device *sh7757lcr_devices[] __initdata = {
 	&sh7757_eth_giga1_device,
 	&sh_mmcif_device,
 	&sdhi_device,
+	&usb0_device,
 };

 static struct flash_platform_data spi_flash_data = {
-- 
1.7.1

^ permalink raw reply related

* [PATCH] sh: modify clock-sh7757 for renesas_usbhs
From: Shimoda, Yoshihiro @ 2012-01-05  5:08 UTC (permalink / raw)
  To: linux-sh

The renesas_usbhs driver doesn't use the clk functions. So, even if we
adds "CLKDEV_DEV_ID("renesas_usbhs.0", ...)" only, we cannot use the USB
controller because clk_late_init() will disable the clock by "usb0".
So, the patch also removes the "CLKDEV_CON_ID("usb0", ...)".

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 arch/sh/kernel/cpu/sh4a/clock-sh7757.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
index 19222da..0fbff14 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
@@ -129,7 +129,7 @@ static struct clk_lookup lookups[] = {
 	CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),

 	CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
-	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
+	CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP102]),
 	CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };

-- 
1.7.1

^ permalink raw reply related

* [PATCH 2/2] ARM: mach-shmobile: specify CHCLR registers on SH7372
From: Guennadi Liakhovetski @ 2012-01-04 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vinod Koul, linux-sh, linux-pm, Rafael J. Wysocki, Magnus Damm
In-Reply-To: <Pine.LNX.4.64.1201041528570.30506@axis700.grange>

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 arch/arm/mach-shmobile/setup-sh7372.c |   15 ++++++++++++---
 1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 2380389..83dc940 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -445,31 +445,39 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
 	},
 };
 
+#define SH7372_CHCLR 0x220
+
 static const struct sh_dmae_channel sh7372_dmae_channels[] = {
 	{
 		.offset = 0,
 		.dmars = 0,
 		.dmars_bit = 0,
+		.chclr_offset = SH7372_CHCLR + 0,
 	}, {
 		.offset = 0x10,
 		.dmars = 0,
 		.dmars_bit = 8,
+		.chclr_offset = SH7372_CHCLR + 0x10,
 	}, {
 		.offset = 0x20,
 		.dmars = 4,
 		.dmars_bit = 0,
+		.chclr_offset = SH7372_CHCLR + 0x20,
 	}, {
 		.offset = 0x30,
 		.dmars = 4,
 		.dmars_bit = 8,
+		.chclr_offset = SH7372_CHCLR + 0x30,
 	}, {
 		.offset = 0x50,
 		.dmars = 8,
 		.dmars_bit = 0,
+		.chclr_offset = SH7372_CHCLR + 0x50,
 	}, {
 		.offset = 0x60,
 		.dmars = 8,
 		.dmars_bit = 8,
+		.chclr_offset = SH7372_CHCLR + 0x60,
 	}
 };
 
@@ -487,6 +495,7 @@ static struct sh_dmae_pdata dma_platform_data = {
 	.ts_shift	= ts_shift,
 	.ts_shift_num	= ARRAY_SIZE(ts_shift),
 	.dmaor_init	= DMAOR_DME,
+	.chclr_present	= 1,
 };
 
 /* Resource order important! */
@@ -494,7 +503,7 @@ static struct resource sh7372_dmae0_resources[] = {
 	{
 		/* Channel registers and DMAOR */
 		.start	= 0xfe008020,
-		.end	= 0xfe00808f,
+		.end	= 0xfe00828f,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -522,7 +531,7 @@ static struct resource sh7372_dmae1_resources[] = {
 	{
 		/* Channel registers and DMAOR */
 		.start	= 0xfe018020,
-		.end	= 0xfe01808f,
+		.end	= 0xfe01828f,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
@@ -550,7 +559,7 @@ static struct resource sh7372_dmae2_resources[] = {
 	{
 		/* Channel registers and DMAOR */
 		.start	= 0xfe028020,
-		.end	= 0xfe02808f,
+		.end	= 0xfe02828f,
 		.flags	= IORESOURCE_MEM,
 	},
 	{
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 1/2] dma: shdma: fix runtime PM: clear channel buffers on
From: Guennadi Liakhovetski @ 2012-01-04 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vinod Koul, linux-sh, linux-pm, Rafael J. Wysocki, Magnus Damm
In-Reply-To: <Pine.LNX.4.64.1201041528570.30506@axis700.grange>

On platforms, supporting power domains, if the domain, containing a DMAC
instance is powered down, the driver fails to resume correctly. On those
platforms DMAC channels have an additional CHCLR register for clearing
channel buffers. Using this register during runtime resume fixes the
problem.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/dma/shdma.c    |   47 +++++++++++++++++++++++++++++++----------------
 include/linux/sh_dma.h |    2 ++
 2 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 81809c2..e1a2fa6 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -57,6 +57,15 @@ static LIST_HEAD(sh_dmae_devices);
 static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)];
 
 static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
+static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
+
+static void chclr_write(struct sh_dmae_chan *sh_dc, u32 data)
+{
+	struct sh_dmae_device *shdev = to_sh_dev(sh_dc);
+
+	__raw_writel(data, shdev->chan_reg +
+		     shdev->pdata->channel[sh_dc->id].chclr_offset);
+}
 
 static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
 {
@@ -129,6 +138,15 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
 
 	dmaor = dmaor_read(shdev) & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME);
 
+	if (shdev->pdata->chclr_present) {
+		int i;
+		for (i = 0; i < shdev->pdata->channel_num; i++) {
+			struct sh_dmae_chan *sh_chan = shdev->chan[i];
+			if (sh_chan)
+				chclr_write(sh_chan, 0);
+		}
+	}
+
 	dmaor_write(shdev, dmaor | shdev->pdata->dmaor_init);
 
 	dmaor = dmaor_read(shdev);
@@ -139,6 +157,10 @@ static int sh_dmae_rst(struct sh_dmae_device *shdev)
 		dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n");
 		return -EIO;
 	}
+	if (shdev->pdata->dmaor_init & ~dmaor)
+		dev_warn(shdev->common.dev,
+			 "DMAOR=0x%x hasn't latched the initial value 0x%x.\n",
+			 dmaor, shdev->pdata->dmaor_init);
 	return 0;
 }
 
@@ -259,8 +281,6 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
 	return 0;
 }
 
-static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan);
-
 static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
 {
 	struct sh_desc *desc = tx_to_sh_desc(tx), *chunk, *last = desc, *c;
@@ -340,6 +360,8 @@ static dma_cookie_t sh_dmae_tx_submit(struct dma_async_tx_descriptor *tx)
 				sh_chan_xfer_ld_queue(sh_chan);
 			sh_chan->pm_state = DMAE_PM_ESTABLISHED;
 		}
+	} else {
+		sh_chan->pm_state = DMAE_PM_PENDING;
 	}
 
 	spin_unlock_irq(&sh_chan->desc_lock);
@@ -1225,6 +1247,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, shdev);
 
+	shdev->common.dev = &pdev->dev;
+
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_get_sync(&pdev->dev);
 
@@ -1254,7 +1278,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
 	shdev->common.device_prep_slave_sg = sh_dmae_prep_slave_sg;
 	shdev->common.device_control = sh_dmae_control;
 
-	shdev->common.dev = &pdev->dev;
 	/* Default transfer size of 32 bytes requires 32-byte alignment */
 	shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
 
@@ -1435,22 +1458,17 @@ static int sh_dmae_runtime_resume(struct device *dev)
 #ifdef CONFIG_PM
 static int sh_dmae_suspend(struct device *dev)
 {
-	struct sh_dmae_device *shdev = dev_get_drvdata(dev);
-	int i;
-
-	for (i = 0; i < shdev->pdata->channel_num; i++) {
-		struct sh_dmae_chan *sh_chan = shdev->chan[i];
-		if (sh_chan->descs_allocated)
-			sh_chan->pm_error = pm_runtime_put_sync(dev);
-	}
-
 	return 0;
 }
 
 static int sh_dmae_resume(struct device *dev)
 {
 	struct sh_dmae_device *shdev = dev_get_drvdata(dev);
-	int i;
+	int i, ret;
+
+	ret = sh_dmae_rst(shdev);
+	if (ret < 0)
+		dev_err(dev, "Failed to reset!\n");
 
 	for (i = 0; i < shdev->pdata->channel_num; i++) {
 		struct sh_dmae_chan *sh_chan = shdev->chan[i];
@@ -1459,9 +1477,6 @@ static int sh_dmae_resume(struct device *dev)
 		if (!sh_chan->descs_allocated)
 			continue;
 
-		if (!sh_chan->pm_error)
-			pm_runtime_get_sync(dev);
-
 		if (param) {
 			const struct sh_dmae_slave_config *cfg = param->config;
 			dmae_set_dmars(sh_chan, cfg->mid_rid);
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index cb2dd11..e11e171 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -48,6 +48,7 @@ struct sh_dmae_channel {
 	unsigned int	offset;
 	unsigned int	dmars;
 	unsigned int	dmars_bit;
+	unsigned int	chclr_offset;
 };
 
 struct sh_dmae_pdata {
@@ -68,6 +69,7 @@ struct sh_dmae_pdata {
 	unsigned int dmaor_is_32bit:1;
 	unsigned int needs_tend_set:1;
 	unsigned int no_dmars:1;
+	unsigned int chclr_present:1;
 };
 
 /* DMA register */
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 0/2] dma: shdma: clear buffers on reset
From: Guennadi Liakhovetski @ 2012-01-04 14:34 UTC (permalink / raw)
  To: linux-kernel
  Cc: Vinod Koul, linux-sh, linux-pm, Rafael J. Wysocki, Magnus Damm

This patch set fixes a runtime PM problem on shdma, whereby it fails to 
recover after the power domain has been switched off.

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply

* [PATCH] ARM: mach-shmobile: fix SDHI0 hotplug sense
From: Guennadi Liakhovetski @ 2012-01-04 14:22 UTC (permalink / raw)
  To: linux-sh

In most cases it suffices to only trigger SD-card interrupts on one edge
due to GPIO level bouncing, but sometimes it does indeed happen, that only
one interrupt is produced on a card insertion or removal, which is then
missed, if the wrong trigger sense is configured. To avoid this configure
the GPIO to produce interrupts on both edges.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 arch/arm/mach-shmobile/board-mackerel.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index b35343a..3139ced 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1011,7 +1011,7 @@ static struct sh_mobile_sdhi_info sdhi0_info = {
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
 	.cd_gpio	= GPIO_PORT172,
 	.cd_irq		= evt2irq(0x3340),
-	.cd_flags	= IRQF_TRIGGER_FALLING,
+	.cd_flags	= IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 };
 
 static struct resource sdhi0_resources[] = {
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 11/11] mmc: tmio: cosmetic: prettify the tmio_mmc_set_ios() function
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/tmio_mmc_pio.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 9106b3d..f68e6f3 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -752,6 +752,7 @@ fail:
 static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct tmio_mmc_host *host = mmc_priv(mmc);
+	struct device *dev = &host->pdev->dev;
 	unsigned long flags;
 
 	mutex_lock(&host->ios_lock);
@@ -759,13 +760,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	spin_lock_irqsave(&host->lock, flags);
 	if (host->mrq) {
 		if (IS_ERR(host->mrq)) {
-			dev_dbg(&host->pdev->dev,
+			dev_dbg(dev,
 				"%s.%d: concurrent .set_ios(), clk %u, mode %u\n",
 				current->comm, task_pid_nr(current),
 				ios->clock, ios->power_mode);
 			host->mrq = ERR_PTR(-EINTR);
 		} else {
-			dev_dbg(&host->pdev->dev,
+			dev_dbg(dev,
 				"%s.%d: CMD%u active since %lu, now %lu!\n",
 				current->comm, task_pid_nr(current),
 				host->mrq->cmd->opcode, host->last_req_ts, jiffies);
@@ -788,7 +789,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	 */
 	if (ios->power_mode = MMC_POWER_ON && ios->clock) {
 		if (!host->power) {
-			pm_runtime_get_sync(&host->pdev->dev);
+			pm_runtime_get_sync(dev);
 			host->power = true;
 		}
 		tmio_mmc_set_clock(host, ios->clock);
@@ -802,7 +803,7 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 			host->set_pwr(host->pdev, 0);
 		if (host->power) {
 			host->power = false;
-			pm_runtime_put(&host->pdev->dev);
+			pm_runtime_put(dev);
 		}
 		tmio_mmc_clk_stop(host);
 	}
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 10/11] mmc: tmio: reconfigure the controller on runtime resume
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

After the controller has been runtime suspended it has to be reset and DMA
has to be re-enabled, if it is used.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/tmio_mmc_pio.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 1811006..9106b3d 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -1031,6 +1031,10 @@ EXPORT_SYMBOL(tmio_mmc_host_suspend);
 int tmio_mmc_host_resume(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+
+	tmio_mmc_reset(host);
+	tmio_mmc_enable_dma(host, true);
 
 	/* The MMC core will perform the complete set up */
 	return mmc_resume_host(mmc);
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 09/11] mmc: sh_mobile_sdhi: do not manage PM clocks manually on ARM
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

On ARM the same clock is used by the PM subsystem and by the driver
directly. This leads to the clock staying permanently on, independent of
the runtime PM state. This patch makes clock enable and disable calls in
the driver SuperH-specific.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/sh_mobile_sdhi.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index a8d353e..0df69ab 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -117,7 +117,9 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 		goto eclkget;
 	}
 
+#if defined(CONFIG_SUPERH)
 	clk_enable(priv->clk);
+#endif
 
 	mmc_data->hclk = clk_get_rate(priv->clk);
 	mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
@@ -235,7 +237,9 @@ eirq_sdio:
 eirq_card_detect:
 	tmio_mmc_host_remove(host);
 eprobe:
+#if defined(CONFIG_SUPERH)
 	clk_disable(priv->clk);
+#endif
 	clk_put(priv->clk);
 eclkget:
 	kfree(priv);
@@ -261,7 +265,9 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
 		free_irq(irq, host);
 	}
 
+#if defined(CONFIG_SUPERH)
 	clk_disable(priv->clk);
+#endif
 	clk_put(priv->clk);
 	kfree(priv);
 
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 08/11] mmc: tmio_mmc: remove unused sdio_irq_enabled flag
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

The sdio_irq_enabled member of struct tmio_mmc_host is a left-over from the
previously removed SDIO IRQ workaround. It is no longer needed and can now
be removed too.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/tmio_mmc.h     |    1 -
 drivers/mmc/host/tmio_mmc_pio.c |    2 --
 2 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 0c39002..62d0d14 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -47,7 +47,6 @@ struct tmio_mmc_host {
 	struct mmc_request      *mrq;
 	struct mmc_data         *data;
 	struct mmc_host         *mmc;
-	unsigned int		sdio_irq_enabled;
 
 	/* Controller power state */
 	bool			power;
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 478e57b..1811006 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -127,7 +127,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 	struct tmio_mmc_host *host = mmc_priv(mmc);
 
 	if (enable) {
-		host->sdio_irq_enabled = 1;
 		host->sdio_irq_mask = TMIO_SDIO_MASK_ALL &
 					~TMIO_SDIO_STAT_IOIRQ;
 		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
@@ -136,7 +135,6 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
 		host->sdio_irq_mask = TMIO_SDIO_MASK_ALL;
 		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask);
 		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
-		host->sdio_irq_enabled = 0;
 	}
 }
 
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 07/11] mmc: tmio_mmc: power status flag doesn't have to be exposed in platform data
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

The controller power status flag does not have to be accessed from the
hot-plug detection code any more, it can now be removed from the platform
data and put in the controller private struct.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/tmio_mmc.h     |    3 +++
 drivers/mmc/host/tmio_mmc_pio.c |   13 ++++++-------
 include/linux/mfd/tmio.h        |    1 -
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 9fb6e6b..0c39002 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -49,6 +49,9 @@ struct tmio_mmc_host {
 	struct mmc_host         *mmc;
 	unsigned int		sdio_irq_enabled;
 
+	/* Controller power state */
+	bool			power;
+
 	/* Callbacks for clock / power control */
 	void (*set_pwr)(struct platform_device *host, int state);
 	void (*set_clk_div)(struct platform_device *host, int state);
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 41b7eff..478e57b 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -754,7 +754,6 @@ fail:
 static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct tmio_mmc_host *host = mmc_priv(mmc);
-	struct tmio_mmc_data *pdata = host->pdata;
 	unsigned long flags;
 
 	mutex_lock(&host->ios_lock);
@@ -784,15 +783,15 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	/*
-	 * pdata->power toggles between false and true in both cases - either
+	 * host->power toggles between false and true in both cases - either
 	 * or not the controller can be runtime-suspended during inactivity. But
 	 * if the controller has to be kept on, the runtime-pm usage_count is
 	 * kept positive, so no suspending actually takes place.
 	 */
 	if (ios->power_mode = MMC_POWER_ON && ios->clock) {
-		if (!pdata->power) {
+		if (!host->power) {
 			pm_runtime_get_sync(&host->pdev->dev);
-			pdata->power = true;
+			host->power = true;
 		}
 		tmio_mmc_set_clock(host, ios->clock);
 		/* power up SD bus */
@@ -803,8 +802,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	} else if (ios->power_mode != MMC_POWER_UP) {
 		if (host->set_pwr && ios->power_mode = MMC_POWER_OFF)
 			host->set_pwr(host->pdev, 0);
-		if (pdata->power) {
-			pdata->power = false;
+		if (host->power) {
+			host->power = false;
 			pm_runtime_put(&host->pdev->dev);
 		}
 		tmio_mmc_clk_stop(host);
@@ -914,7 +913,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 	_host->native_hotplug = !(pdata->flags & TMIO_MMC_HAS_COLD_CD ||
 				  mmc->caps & MMC_CAP_NEEDS_POLL ||
 				  mmc->caps & MMC_CAP_NONREMOVABLE);
-	pdata->power = false;
+	_host->power = false;
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_resume(&pdev->dev);
 	if (ret < 0)
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 08fb7d2..367c65c6 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -98,7 +98,6 @@ struct tmio_mmc_data {
 	u32				ocr_mask;	/* available voltages */
 	struct tmio_mmc_dma		*dma;
 	struct device			*dev;
-	bool				power;
 	unsigned int			cd_gpio;
 	unsigned int			cd_irq;
 	unsigned long			cd_flags;
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 06/11] mfd: tmio: remove now unneeded tmio_mmc_cd_wakeup()
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

Now, that all users of tmio_mmc_cd_wakeup() have been converted over to
drivers/mmc/core/cd-gpio.c, that function can be removed.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 include/linux/mfd/tmio.h |   11 -----------
 1 files changed, 0 insertions(+), 11 deletions(-)

diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 4ef9307..08fb7d2 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -4,7 +4,6 @@
 #include <linux/device.h>
 #include <linux/fb.h>
 #include <linux/io.h>
-#include <linux/jiffies.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 
@@ -110,16 +109,6 @@ struct tmio_mmc_data {
 };
 
 /*
- * This function is deprecated and will be removed soon. Please, convert your
- * platform to use drivers/mmc/core/cd-gpio.c
- */
-static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata)
-{
-	if (pdata)
-		mmc_detect_change(dev_get_drvdata(dev), msecs_to_jiffies(100));
-}
-
-/*
  * data for the NAND controller
  */
 struct tmio_nand_data {
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 05/11] ARM: mach-shmobile: convert ag5evm to use the generic MMC GPIO hotplug helper
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---

Only compile-tested.

 arch/arm/mach-shmobile/board-ag5evm.c |   24 ++++--------------------
 1 files changed, 4 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index b862e9f..b1db188 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -340,23 +340,15 @@ static struct platform_device mipidsi0_device = {
 };
 
 /* SDHI0 */
-static irqreturn_t ag5evm_sdhi0_gpio_cd(int irq, void *arg)
-{
-	struct device *dev = arg;
-	struct sh_mobile_sdhi_info *info = dev->platform_data;
-	struct tmio_mmc_data *pdata = info->pdata;
-
-	tmio_mmc_cd_wakeup(pdata);
-
-	return IRQ_HANDLED;
-}
-
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
-	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT,
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_HAS_COLD_CD,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
 	.tmio_ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
+	.cd_gpio	= GPIO_PORT251,
+	.cd_irq		= intcs_evt2irq(0x3c0),
+	.cd_flags	= IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -560,7 +552,6 @@ static void __init ag5evm_init(void)
 	__raw_writel(0x2a809010, DSI0PHYCR);
 
 	/* enable SDHI0 on CN15 [SD I/F] */
-	gpio_request(GPIO_FN_SDHICD0, NULL);
 	gpio_request(GPIO_FN_SDHIWP0, NULL);
 	gpio_request(GPIO_FN_SDHICMD0, NULL);
 	gpio_request(GPIO_FN_SDHICLK0, NULL);
@@ -569,13 +560,6 @@ static void __init ag5evm_init(void)
 	gpio_request(GPIO_FN_SDHID0_1, NULL);
 	gpio_request(GPIO_FN_SDHID0_0, NULL);
 
-	if (!request_irq(intcs_evt2irq(0x3c0), ag5evm_sdhi0_gpio_cd,
-			 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-			 "sdhi0 cd", &sdhi0_device.dev))
-		sdhi0_info.tmio_flags |= TMIO_MMC_HAS_COLD_CD;
-	else
-		pr_warn("Unable to setup SDHI0 GPIO IRQ\n");
-
 	/* enable SDHI1 on CN4 [WLAN I/F] */
 	gpio_request(GPIO_FN_SDHICLK1, NULL);
 	gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 04/11] ARM: mach-shmobile: convert mackerel to use the generic MMC GPIO hotplug helper
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 arch/arm/mach-shmobile/board-mackerel.c |   24 ++++--------------------
 1 files changed, 4 insertions(+), 20 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 9c5e598..b35343a 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1004,21 +1004,14 @@ static int slot_cn7_get_cd(struct platform_device *pdev)
 }
 
 /* SDHI0 */
-static irqreturn_t mackerel_sdhi0_gpio_cd(int irq, void *arg)
-{
-	struct device *dev = arg;
-	struct sh_mobile_sdhi_info *info = dev->platform_data;
-	struct tmio_mmc_data *pdata = info->pdata;
-
-	tmio_mmc_cd_wakeup(pdata);
-
-	return IRQ_HANDLED;
-}
-
 static struct sh_mobile_sdhi_info sdhi0_info = {
 	.dma_slave_tx	= SHDMA_SLAVE_SDHI0_TX,
 	.dma_slave_rx	= SHDMA_SLAVE_SDHI0_RX,
+	.tmio_flags	= TMIO_MMC_HAS_COLD_CD,
 	.tmio_caps	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+	.cd_gpio	= GPIO_PORT172,
+	.cd_irq		= evt2irq(0x3340),
+	.cd_flags	= IRQF_TRIGGER_FALLING,
 };
 
 static struct resource sdhi0_resources[] = {
@@ -1408,7 +1401,6 @@ static void __init mackerel_init(void)
 {
 	u32 srcr4;
 	struct clk *clk;
-	int ret;
 
 	sh7372_pinmux_init();
 
@@ -1505,7 +1497,6 @@ static void __init mackerel_init(void)
 	irq_set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
 
 	/* enable SDHI0 */
-	gpio_request(GPIO_FN_SDHICD0, NULL);
 	gpio_request(GPIO_FN_SDHIWP0, NULL);
 	gpio_request(GPIO_FN_SDHICMD0, NULL);
 	gpio_request(GPIO_FN_SDHICLK0, NULL);
@@ -1514,13 +1505,6 @@ static void __init mackerel_init(void)
 	gpio_request(GPIO_FN_SDHID0_1, NULL);
 	gpio_request(GPIO_FN_SDHID0_0, NULL);
 
-	ret = request_irq(evt2irq(0x3340), mackerel_sdhi0_gpio_cd,
-			  IRQF_TRIGGER_FALLING, "sdhi0 cd", &sdhi0_device.dev);
-	if (!ret)
-		sdhi0_info.tmio_flags |= TMIO_MMC_HAS_COLD_CD;
-	else
-		pr_err("Cannot get IRQ #%d: %d\n", evt2irq(0x3340), ret);
-
 #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
 	/* enable SDHI1 */
 	gpio_request(GPIO_FN_SDHICMD1, NULL);
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 03/11] mmc: sh_mobile_sdhi: pass card hotplug GPIO number and flags to TMIO MMC
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

To use TMIO MMC driver ability to interface to the generic MMC GPIO card
hotplug detection helper, the SDHI driver has to pass the GPIO number and
IRQ flags down from its own platform data.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/sh_mobile_sdhi.c  |    5 ++++-
 include/linux/mmc/sh_mobile_sdhi.h |    3 +++
 2 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 58da3c4..a8d353e 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -129,6 +129,9 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 			mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
 		mmc_data->ocr_mask = p->tmio_ocr_mask;
 		mmc_data->capabilities |= p->tmio_caps;
+		mmc_data->cd_gpio = p->cd_gpio;
+		mmc_data->cd_irq = p->cd_irq;
+		mmc_data->cd_flags = p->cd_flags;
 
 		if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
 			priv->param_tx.slave_id = p->dma_slave_tx;
@@ -211,7 +214,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 
 	dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
 		 mmc_hostname(host->mmc), (unsigned long)
-		 (platform_get_resource(pdev,IORESOURCE_MEM, 0)->start),
+		 (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start),
 		 mmc_data->hclk / 1000000);
 
 	return ret;
diff --git a/include/linux/mmc/sh_mobile_sdhi.h b/include/linux/mmc/sh_mobile_sdhi.h
index 71b8054..86347f6 100644
--- a/include/linux/mmc/sh_mobile_sdhi.h
+++ b/include/linux/mmc/sh_mobile_sdhi.h
@@ -16,6 +16,9 @@ struct sh_mobile_sdhi_info {
 	unsigned long tmio_flags;
 	unsigned long tmio_caps;
 	u32 tmio_ocr_mask;	/* available MMC voltages */
+	unsigned int cd_gpio;
+	unsigned int cd_irq;
+	unsigned long cd_flags;
 	struct tmio_mmc_data *pdata;
 	void (*set_pwr)(struct platform_device *pdev, int state);
 	int (*get_cd)(struct platform_device *pdev);
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 02/11] mmc: tmio_mmc: support the generic MMC GPIO card hotplug helper
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

If the platform specified a GPIO number and IRQ trigger polarity flags, use
the generic MMC GPIO card hotplug helper.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/tmio_mmc.h     |    4 --
 drivers/mmc/host/tmio_mmc_pio.c |   69 +++++++++++++++++----------------------
 include/linux/mfd/tmio.h        |   19 +++++++---
 3 files changed, 43 insertions(+), 49 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 9aa6a18..9fb6e6b 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -53,10 +53,6 @@ struct tmio_mmc_host {
 	void (*set_pwr)(struct platform_device *host, int state);
 	void (*set_clk_div)(struct platform_device *host, int state);
 
-	int			pm_error;
-	/* recognise system-wide suspend in runtime PM methods */
-	bool			pm_global;
-
 	/* pio related stuff */
 	struct scatterlist      *sg_ptr;
 	struct scatterlist      *sg_orig;
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index 1a9e975..41b7eff 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/mfd/tmio.h>
+#include <linux/mmc/cd-gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/tmio.h>
 #include <linux/module.h>
@@ -783,8 +784,10 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	spin_unlock_irqrestore(&host->lock, flags);
 
 	/*
-	 * pdata->power = false only if COLD_CD is available, otherwise only
-	 * in short time intervals during probing or resuming
+	 * pdata->power toggles between false and true in both cases - either
+	 * or not the controller can be runtime-suspended during inactivity. But
+	 * if the controller has to be kept on, the runtime-pm usage_count is
+	 * kept positive, so no suspending actually takes place.
 	 */
 	if (ios->power_mode = MMC_POWER_ON && ios->clock) {
 		if (!pdata->power) {
@@ -924,9 +927,9 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 	 *  3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL
 	 *  4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE
 	 *
-	 *  While we increment the rtpm counter for all scenarios when the mmc
-	 *  core activates us by calling an appropriate set_ios(), we must
-	 *  additionally ensure that in case 2) the tmio mmc hardware stays
+	 *  While we increment the runtime PM counter for all scenarios when
+	 *  the mmc core activates us by calling an appropriate set_ios(), we
+	 *  must additionally ensure that in case 2) the tmio mmc hardware stays
 	 *  powered on during runtime for the card detection to work.
 	 */
 	if (_host->native_hotplug)
@@ -960,6 +963,16 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 
 	tmio_mmc_enable_mmc_irqs(_host, irq_mask);
 
+	if (pdata->flags & TMIO_MMC_HAS_COLD_CD &&
+	    pdata->cd_flags & IRQF_TRIGGER_MASK) {
+		ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio, pdata->cd_irq,
+					  pdata->cd_flags);
+		if (ret < 0) {
+			tmio_mmc_host_remove(_host);
+			return ret;
+		}
+	}
+
 	*host = _host;
 
 	return 0;
@@ -977,18 +990,21 @@ EXPORT_SYMBOL(tmio_mmc_host_probe);
 void tmio_mmc_host_remove(struct tmio_mmc_host *host)
 {
 	struct platform_device *pdev = host->pdev;
+	struct tmio_mmc_data *pdata = host->pdata;
+	struct mmc_host *mmc = host->mmc;
+
+	if (pdata->flags & TMIO_MMC_HAS_COLD_CD &&
+	    pdata->cd_flags & IRQF_TRIGGER_MASK)
+		/*
+		 * This means we can miss a card-eject, but this is anyway
+		 * possible, because of delayed processing of hotplug events.
+		 */
+		mmc_cd_gpio_free(mmc);
 
-	/*
-	 * We don't have to manipulate pdata->power here: if there is a card in
-	 * the slot, the runtime PM is active and our .runtime_resume() will not
-	 * be run. If there is no card in the slot and the platform can suspend
-	 * the controller, the runtime PM is suspended and pdata->power = false,
-	 * so, our .runtime_resume() will not try to detect a card in the slot.
-	 */
 	if (!host->native_hotplug)
 		pm_runtime_get_sync(&pdev->dev);
 
-	mmc_remove_host(host->mmc);
+	mmc_remove_host(mmc);
 	cancel_work_sync(&host->done);
 	cancel_delayed_work_sync(&host->delayed_reset_work);
 	tmio_mmc_release_dma(host);
@@ -997,7 +1013,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
 	pm_runtime_disable(&pdev->dev);
 
 	iounmap(host->ctl);
-	mmc_free_host(host->mmc);
+	mmc_free_host(mmc);
 }
 EXPORT_SYMBOL(tmio_mmc_host_remove);
 
@@ -1011,8 +1027,6 @@ int tmio_mmc_host_suspend(struct device *dev)
 	if (!ret)
 		tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL);
 
-	host->pm_error = pm_runtime_put_sync(dev);
-
 	return ret;
 }
 EXPORT_SYMBOL(tmio_mmc_host_suspend);
@@ -1020,22 +1034,8 @@ EXPORT_SYMBOL(tmio_mmc_host_suspend);
 int tmio_mmc_host_resume(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
-	struct tmio_mmc_host *host = mmc_priv(mmc);
 
 	/* The MMC core will perform the complete set up */
-	host->pdata->power = false;
-
-	host->pm_global = true;
-	if (!host->pm_error)
-		pm_runtime_get_sync(dev);
-
-	if (host->pm_global) {
-		/* Runtime PM resume callback didn't run */
-		tmio_mmc_reset(host);
-		tmio_mmc_enable_dma(host, true);
-		host->pm_global = false;
-	}
-
 	return mmc_resume_host(mmc);
 }
 EXPORT_SYMBOL(tmio_mmc_host_resume);
@@ -1052,19 +1052,10 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
 	struct tmio_mmc_host *host = mmc_priv(mmc);
-	struct tmio_mmc_data *pdata = host->pdata;
 
 	tmio_mmc_reset(host);
 	tmio_mmc_enable_dma(host, true);
 
-	if (pdata->power) {
-		/* Only entered after a card-insert interrupt */
-		if (!mmc->card)
-			tmio_mmc_set_ios(mmc, &mmc->ios);
-		mmc_detect_change(mmc, msecs_to_jiffies(100));
-	}
-	host->pm_global = false;
-
 	return 0;
 }
 EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 0dc9804..4ef9307 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -1,8 +1,10 @@
 #ifndef MFD_TMIO_H
 #define MFD_TMIO_H
 
+#include <linux/device.h>
 #include <linux/fb.h>
 #include <linux/io.h>
+#include <linux/jiffies.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 
@@ -64,8 +66,8 @@
 #define TMIO_MMC_SDIO_IRQ		(1 << 2)
 /*
  * Some platforms can detect card insertion events with controller powered
- * down, in which case they have to call tmio_mmc_cd_wakeup() to power up the
- * controller and report the event to the driver.
+ * down, using a GPIO IRQ, in which case they have to fill in cd_irq, cd_gpio,
+ * and cd_flags fields of struct tmio_mmc_data.
  */
 #define TMIO_MMC_HAS_COLD_CD		(1 << 3)
 /*
@@ -98,18 +100,23 @@ struct tmio_mmc_data {
 	struct tmio_mmc_dma		*dma;
 	struct device			*dev;
 	bool				power;
+	unsigned int			cd_gpio;
+	unsigned int			cd_irq;
+	unsigned long			cd_flags;
 	void (*set_pwr)(struct platform_device *host, int state);
 	void (*set_clk_div)(struct platform_device *host, int state);
 	int (*get_cd)(struct platform_device *host);
 	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
 };
 
+/*
+ * This function is deprecated and will be removed soon. Please, convert your
+ * platform to use drivers/mmc/core/cd-gpio.c
+ */
 static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata)
 {
-	if (pdata && !pdata->power) {
-		pdata->power = true;
-		pm_runtime_get(pdata->dev);
-	}
+	if (pdata)
+		mmc_detect_change(dev_get_drvdata(dev), msecs_to_jiffies(100));
 }
 
 /*
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 01/11] mmc: tmio: calculate the native hotplug condition only once
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz
In-Reply-To: <1325686636-23905-1-git-send-email-g.liakhovetski@gmx.de>

The condition, whether we have to use the native TMIO card hotplug
detection interrupt, is rather complex, it is better to only calculate it
once and store in the private data.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/tmio_mmc.h     |    1 +
 drivers/mmc/host/tmio_mmc_pio.c |   11 +++++------
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index a95e6d9..9aa6a18 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -86,6 +86,7 @@ struct tmio_mmc_host {
 	spinlock_t		lock;		/* protect host private data */
 	unsigned long		last_req_ts;
 	struct mutex		ios_lock;	/* protect set_ios() context */
+	bool			native_hotplug;
 };
 
 int tmio_mmc_host_probe(struct tmio_mmc_host **host,
diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
index abad01b..1a9e975 100644
--- a/drivers/mmc/host/tmio_mmc_pio.c
+++ b/drivers/mmc/host/tmio_mmc_pio.c
@@ -908,6 +908,9 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 	else
 		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
+	_host->native_hotplug = !(pdata->flags & TMIO_MMC_HAS_COLD_CD ||
+				  mmc->caps & MMC_CAP_NEEDS_POLL ||
+				  mmc->caps & MMC_CAP_NONREMOVABLE);
 	pdata->power = false;
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_resume(&pdev->dev);
@@ -926,9 +929,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 	 *  additionally ensure that in case 2) the tmio mmc hardware stays
 	 *  powered on during runtime for the card detection to work.
 	 */
-	if (!(pdata->flags & TMIO_MMC_HAS_COLD_CD
-		|| mmc->caps & MMC_CAP_NEEDS_POLL
-		|| mmc->caps & MMC_CAP_NONREMOVABLE))
+	if (_host->native_hotplug)
 		pm_runtime_get_noresume(&pdev->dev);
 
 	tmio_mmc_clk_stop(_host);
@@ -984,9 +985,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
 	 * the controller, the runtime PM is suspended and pdata->power = false,
 	 * so, our .runtime_resume() will not try to detect a card in the slot.
 	 */
-	if (host->pdata->flags & TMIO_MMC_HAS_COLD_CD
-		|| host->mmc->caps & MMC_CAP_NEEDS_POLL
-		|| host->mmc->caps & MMC_CAP_NONREMOVABLE)
+	if (!host->native_hotplug)
 		pm_runtime_get_sync(&pdev->dev);
 
 	mmc_remove_host(host->mmc);
-- 
1.7.2.5


^ permalink raw reply related

* [PATCH 00/11] mmc: tmio/sdhi: hotplug & PM
From: Guennadi Liakhovetski @ 2012-01-04 14:17 UTC (permalink / raw)
  To: linux-mmc
  Cc: Chris Ball, Paul Mundt, Magnus Damm, linux-sh, Rafael J. Wysocki,
	Samuel Ortiz

This patch series uses a previously proposed generic GPIO card hotplug 
handler, fixes multiple PM issues, adds some cosmetic clean up. Not all of 
these patches really depend on each other, but it's easier to preserve the 
original order. Some patches, e.g., #9, are an RFC so far and might have to 
be reworked a bit.

Guennadi Liakhovetski (11):
  mmc: tmio: calculate the native hotplug condition only once
  mmc: tmio_mmc: support the generic MMC GPIO card hotplug helper
  mmc: sh_mobile_sdhi: pass card hotplug GPIO number and flags to TMIO
    MMC
  ARM: mach-shmobile: convert mackerel to use the generic MMC GPIO
    hotplug helper
  ARM: mach-shmobile: convert ag5evm to use the generic MMC GPIO
    hotplug helper
  mfd: tmio: remove now unneeded tmio_mmc_cd_wakeup()
  mmc: tmio_mmc: power status flag doesn't have to be exposed in
    platform data
  mmc: tmio_mmc: remove unused sdio_irq_enabled flag
  mmc: sh_mobile_sdhi: do not manage PM clocks manually on ARM
  mmc: tmio: reconfigure the controller on runtime resume
  mmc: tmio: cosmetic: prettify the tmio_mmc_set_ios() function

 arch/arm/mach-shmobile/board-ag5evm.c   |   24 +------
 arch/arm/mach-shmobile/board-mackerel.c |   24 +------
 drivers/mmc/host/sh_mobile_sdhi.c       |   11 +++-
 drivers/mmc/host/tmio_mmc.h             |    9 +--
 drivers/mmc/host/tmio_mmc_pio.c         |  104 ++++++++++++++-----------------
 include/linux/mfd/tmio.h                |   17 ++---
 include/linux/mmc/sh_mobile_sdhi.h      |    3 +
 7 files changed, 79 insertions(+), 113 deletions(-)

-- 
1.7.2.5

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply

* Re: Dreamcast build broken
From: Oleg Endo @ 2012-01-03  2:38 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <4EC81660.3010109@gmail.com>

On Mon, 2012-01-02 at 22:57 +0100, Paul Cercueil wrote:
> Le 17/12/2011 11:24, Adrian McMenamin a écrit :
> > On 25 November 2011 16:24, Paul Cercueil<pcercuei@gmail.com>  wrote:
> >> Le 24/11/2011 08:29, Paul Mundt a écrit :
> >>>
> >
> >> However, starting from commit 37b7a97884ba64bf7d403351ac2a9476ab4f1bba and
> >> up to the latest vanilla Linux 3.1,
> >> the vmlinux binary won't start on my dreamcast or on the lxdream emulator.
> >>
> > No output at all?
> 
> Hi,
> Sorry for the late reply.
> 
> That's right, there is no output at all. Perhaps the binary starts 
> correctly but then it crashes before the activation of the framebuffer.
> 
> I am facing another issue about the dreamcast build: the entry point of 
> the kernel is set to 0x8c002000, which does not appear to be correct. 
> When booting a CD, the bootloader (contained inside the IP.bin file) 
> loads the main executable at 0x8c010000.
> 

This is not entirely correct.  IP.BIN code does (normally) does not load
the main executable.  When the original SEGA BootROM boots from a CD-ROM
(not GD-ROM), it loads the "hidden" IP.BIN at 0x8C008000 and the
"1ST_READ.BIN" (typical name, could be different) to 0x8C010000. After
that it will start executing code contained in IP.BIN, which can perform
additional startup things.  One common technique for bootable CD-ROMs
was to put the 1ST_READ.BIN descrambling code into IP.BIN.

For more details see http://mc.pp.se/dc/ip.bin.html


> On a side note, the kernel inside the old DCLinux (based on Linux 2.4) 
> has an entry point set to 0x8c012000.

Could make sense if there are some additional things happening in
IP.BIN.  However, setting the entry point to 0x8C002000 seems incorrect
indeed, as this conflicts with the memory area that is used by the
resident GDC driver code of the original SEGA BootROM.  With a custom
IP.BIN it _is_ possible to copy the already loaded 1ST_READ.BIN to a
lower memory address than 0x8C010000 (e.g. 0x8C002000), but it will
render the resident BootROM code useless.  If the resident BootROM
functions are not used by the software being executed there will be no
further consequences and some additional KBytes of RAM available ;)

Cheers,
Oleg


^ permalink raw reply

* Re: Dreamcast build broken
From: Paul Cercueil @ 2012-01-02 21:57 UTC (permalink / raw)
  To: linux-sh
In-Reply-To: <4EC81660.3010109@gmail.com>

Le 17/12/2011 11:24, Adrian McMenamin a écrit :
> On 25 November 2011 16:24, Paul Cercueil<pcercuei@gmail.com>  wrote:
>> Le 24/11/2011 08:29, Paul Mundt a écrit :
>>>
>
>> However, starting from commit 37b7a97884ba64bf7d403351ac2a9476ab4f1bba and
>> up to the latest vanilla Linux 3.1,
>> the vmlinux binary won't start on my dreamcast or on the lxdream emulator.
>>
> No output at all?

Hi,
Sorry for the late reply.

That's right, there is no output at all. Perhaps the binary starts 
correctly but then it crashes before the activation of the framebuffer.

I am facing another issue about the dreamcast build: the entry point of 
the kernel is set to 0x8c002000, which does not appear to be correct. 
When booting a CD, the bootloader (contained inside the IP.bin file) 
loads the main executable at 0x8c010000.

On a side note, the kernel inside the old DCLinux (based on Linux 2.4) 
has an entry point set to 0x8c012000.

^ permalink raw reply

* RE: [PATCH 00/14] DMA-mapping framework redesign preparation
From: Marek Szyprowski @ 2011-12-28 12:52 UTC (permalink / raw)
  To: 'James Bottomley'
  Cc: 'Matthew Wilcox', linux-kernel,
	'Benjamin Herrenschmidt', 'Thomas Gleixner',
	'Andrew Morton', 'Arnd Bergmann',
	'Stephen Rothwell', microblaze-uclinux, linux-arch, x86,
	linux-sh, linux-alpha, sparclinux, linux-ia64, linuxppc-dev,
	linux-mips, discuss, linux-arm-kernel, linux-mm, linaro-mm-sig,
	'Jonathan Corbet', 'Kyungmin Park',
	Andrzej Pietrasiewicz
In-Reply-To: <1325008393.14252.5.camel@dabdike>

Hello,

On Tuesday, December 27, 2011 6:53 PM James Bottomley wrote:

> On Tue, 2011-12-27 at 09:25 +0100, Marek Szyprowski wrote:
> [...]
> > > > Usually these drivers don't touch the buffer data at all, so the mapping
> > > > in kernel virtual address space is not needed. We can introduce
> > > > DMA_ATTRIB_NO_KERNEL_MAPPING attribute which lets kernel to skip/ignore
> > > > creation of kernel virtual mapping. This way we can save previous
> > > > vmalloc area and simply some mapping operation on a few architectures.
> > >
> > > I really think this wants to be a separate function.  dma_alloc_coherent
> > > is for allocating memory to be shared between the kernel and a driver;
> > > we already have dma_map_sg for mapping userspace I/O as an alternative
> > > interface.  This feels like it's something different again rather than
> > > an option to dma_alloc_coherent.
> >
> > That is just a starting point for the discussion.
> >
> > I thought about this API a bit and came to conclusion that there is no much
> > difference between a dma_alloc_coherent which creates a mapping in kernel
> > virtual space and the one that does not. It is just a hint from the driver
> > that it will not use that mapping at all. Of course this attribute makes sense
> > only together with adding a dma_mmap_attrs() call, because otherwise drivers
> > won't be able to get access to the buffer data.
> 
> This depends.  On Virtually indexed systems like PA-RISC, there are two
> ways of making a DMA range coherent.  One is to make the range uncached.
> This is incredibly slow and not what we do by default, but it can be
> used to make multiple mappings coherent.  The other is to load the
> virtual address up as a coherence index into the IOMMU.  This makes it a
> full peer in the coherence process, but means we can only designate a
> single virtual range to be coherent (not multiple mappings unless they
> happen to be congruent).  Perhaps it doesn't matter that much, since I
> don't see a use for this on PA, but if any other architecture works the
> same, you'd have to designate a single mapping as the coherent one and
> essentially promise not to use the other mapping if we followed our
> normal coherence protocols.
> 
> Obviously, the usual range we currently make coherent is the kernel
> mapping (that's actually the only virtual address we have by the time
> we're deep in the iommu code), so designating a different virtual
> address would need some surgery to the guts of the iommu code.

I see, in this case not much can be achieved by dropping the kernel
mapping for the allocated buffer. I'm also not sure how to mmap the buffer
into userspace meet the cpu requirements? Is it possible to use non-cached
mapping in userspace together with coherent mapping in kernel virtual
space?

However on some other architectures this attribute allows using HIGH_MEM
for the allocated coherent buffer. The other possibility is to allocate it
in chunks and map them contiguously into dma address space. With 
NO_KERNEL_MAPPING attribute we avoid consuming vmalloc range for the newly
allocated buffer for which we cannot use the linear mapping (because it is
scattered).

Of course this attribute will be implemented by the architectures where it
gives some benefits. All other can simply ignore it and return plain
coherent buffer with ordinary kernel virtual mapping. The driver will just
ignore it.

Best regards
-- 
Marek Szyprowski
Samsung Poland R&D Center




^ 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