LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 3/3] mpc512x_dma: add MPC8308 support
From: Wolfgang Denk @ 2010-09-28 13:09 UTC (permalink / raw)
  To: Ilya Yanok; +Cc: vlad, linuxppc-dev, Piotr Ziecik, dzu
In-Reply-To: <1285676696-5358-4-git-send-email-yanok@emcraft.com>

Dear Ilya Yanok,

In message <1285676696-5358-4-git-send-email-yanok@emcraft.com> you wrote:
> MPC8308 has pretty much the same DMA controller as MPC5121 and
> this patch adds support for MPC8308 to the mpc512x_dma driver.
> 
> Signed-off-by: Ilya Yanok <yanok@emcraft.com>
> Cc: Piotr Ziecik <kosmo@semihalf.com>
> ---
>  drivers/dma/Kconfig       |    2 +-
>  drivers/dma/mpc512x_dma.c |   95 +++++++++++++++++++++++++++++++++-----------
>  2 files changed, 72 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 9520cf0..5c5e95b 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -100,7 +100,7 @@ config FSL_DMA
>  
>  config MPC512X_DMA
>  	tristate "Freescale MPC512x built-in DMA engine support"
> -	depends on PPC_MPC512x
> +	depends on PPC_MPC512x || PPC_MPC831x

Is MPC831x correct here? My understanding is that MPC831x processors
have yet other DMA cotnrollers, and we're on a MPC8308 here?

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
"A little knowledge is a dangerous thing."                - Doug Gwyn

^ permalink raw reply

* Re: [PATCH 4/8] v2 Allow memory block to span multiple memory sections
From: Robin Holt @ 2010-09-28 12:48 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linuxppc-dev, Greg KH, linux-kernel, Dave Hansen, linux-mm,
	KAMEZAWA Hiroyuki
In-Reply-To: <4CA0EFAA.8050000@austin.ibm.com>

> +u32 __weak memory_block_size_bytes(void)
> +{
> +	return MIN_MEMORY_BLOCK_SIZE;
> +}
> +
> +static u32 get_memory_block_size(void)

Can we make this an unsigned long?  We are testing on a system whose
smallest possible configuration is 4GB per socket with 512 sockets.
We would like to be able to specify this as 2GB by default (results
in the least lost memory) and suggest we add a command line option
which overrides this value.  We have many installations where 16GB may
be optimal.  Large configurations will certainly become more prevalent.

...
> @@ -551,12 +608,16 @@
>  	unsigned int i;
>  	int ret;
>  	int err;
> +	int block_sz;

This one needs to match the return above.  In our tests, we ended up
with a negative sections_per_block which caused very unexpected results.

Robin

^ permalink raw reply

* Re: [PATCH 8/8] v2 Update memory hotplug documentation
From: Avi Kivity @ 2010-09-28 12:45 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linuxppc-dev, Greg KH, linux-kernel, Dave Hansen, linux-mm,
	KAMEZAWA Hiroyuki
In-Reply-To: <4CA0F076.1070803@austin.ibm.com>

  On 09/27/2010 09:28 PM, Nathan Fontenot wrote:
>
>   For example, assume 1GiB section size. A device for a memory starting at
>   0x100000000 is /sys/device/system/memory/memory4
>   (0x100000000 / 1Gib = 4)
>   This device covers address range [0x100000000 ... 0x140000000)
>
> -Under each section, you can see 4 files.
> +Under each section, you can see 5 files.

Shouldn't this be, 4 or 5 files depending on kernel version?

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply

* Re: [PATCH 0/8] v2 De-Couple sysfs memory directories from memory sections
From: Avi Kivity @ 2010-09-28 12:44 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linuxppc-dev, Greg KH, linux-kernel, Dave Hansen, linux-mm,
	KAMEZAWA Hiroyuki
In-Reply-To: <4CA0EBEB.1030204@austin.ibm.com>

  On 09/27/2010 09:09 PM, Nathan Fontenot wrote:
> This set of patches decouples the concept that a single memory
> section corresponds to a single directory in
> /sys/devices/system/memory/.  On systems
> with large amounts of memory (1+ TB) there are perfomance issues
> related to creating the large number of sysfs directories.  For
> a powerpc machine with 1 TB of memory we are creating 63,000+
> directories.  This is resulting in boot times of around 45-50
> minutes for systems with 1 TB of memory and 8 hours for systems
> with 2 TB of memory.  With this patch set applied I am now seeing
> boot times of 5 minutes or less.
>
> The root of this issue is in sysfs directory creation. Every time
> a directory is created a string compare is done against all sibling
> directories to ensure we do not create duplicates.  The list of
> directory nodes in sysfs is kept as an unsorted list which results
> in this being an exponentially longer operation as the number of
> directories are created.
>
> The solution solved by this patch set is to allow a single
> directory in sysfs to span multiple memory sections.  This is
> controlled by an optional architecturally defined function
> memory_block_size_bytes().  The default definition of this
> routine returns a memory block size equal to the memory section
> size. This maintains the current layout of sysfs memory
> directories as it appears to userspace to remain the same as it
> is today.
>

Why not update sysfs directory creation to be fast, for example by using 
an rbtree instead of a linked list.  This fixes an implementation 
problem in the kernel instead of working around it and creating a new ABI.

New ABIs mean old tools won't work, and new tools need to understand 
both ABIs.

-- 
error compiling committee.c: too many arguments to function

^ permalink raw reply

* Re: [PATCH 0/8] v2 De-Couple sysfs memory directories from memory sections
From: Robin Holt @ 2010-09-28 12:38 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linuxppc-dev, Greg KH, linux-kernel, Dave Hansen, linux-mm,
	KAMEZAWA Hiroyuki
In-Reply-To: <4CA0EBEB.1030204@austin.ibm.com>

I was tasked with looking at a slowdown in similar sized SGI machines
booting x86_64.  Jack Steiner had already looked into the memory_dev_init.
I was looking at link_mem_sections().

I made a dramatic improvement on a 16TB machine in that function by
merely caching the most recent memory section and checking to see if
the next memory section happens to be the subsequent in the linked list
of kobjects.

That simple cache reduced the time for link_mem_sections from 1 hour 27
minutes down to 46 seconds.

I would like to propose we implement something along those lines also,
but I am currently swamped.  I can probably get you a patch tomorrow
afternoon that applies at the end of this set.

Thanks,
Robin

On Mon, Sep 27, 2010 at 02:09:31PM -0500, Nathan Fontenot wrote:
> This set of patches decouples the concept that a single memory
> section corresponds to a single directory in 
> /sys/devices/system/memory/.  On systems
> with large amounts of memory (1+ TB) there are perfomance issues
> related to creating the large number of sysfs directories.  For
> a powerpc machine with 1 TB of memory we are creating 63,000+
> directories.  This is resulting in boot times of around 45-50
> minutes for systems with 1 TB of memory and 8 hours for systems
> with 2 TB of memory.  With this patch set applied I am now seeing
> boot times of 5 minutes or less.
> 
> The root of this issue is in sysfs directory creation. Every time
> a directory is created a string compare is done against all sibling
> directories to ensure we do not create duplicates.  The list of
> directory nodes in sysfs is kept as an unsorted list which results
> in this being an exponentially longer operation as the number of
> directories are created.
> 
> The solution solved by this patch set is to allow a single
> directory in sysfs to span multiple memory sections.  This is
> controlled by an optional architecturally defined function
> memory_block_size_bytes().  The default definition of this
> routine returns a memory block size equal to the memory section
> size. This maintains the current layout of sysfs memory
> directories as it appears to userspace to remain the same as it
> is today.
> 
> For architectures that define their own version of this routine,
> as is done for powerpc in this patchset, the view in userspace
> would change such that each memoryXXX directory would span
> multiple memory sections.  The number of sections spanned would
> depend on the value reported by memory_block_size_bytes.
> 
> In both cases a new file 'end_phys_index' is created in each
> memoryXXX directory.  This file will contain the physical id
> of the last memory section covered by the sysfs directory.  For
> the default case, the value in 'end_phys_index' will be the same
> as in the existing 'phys_index' file.
> 
> This version of the patch set includes an update to to properly
> report block_size_bytes, phys_index, and end_phys_index.  Additionally,
> the patch that adds the end_phys_index sysfs file is now patch 5/8
> instead of being patch 2/8 as in the previous version of the patches.
> 
> -Nathan Fontenot
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* [PATCH 1/3] mpc512x_dma: scatter/gather fix
From: Ilya Yanok @ 2010-09-28 12:24 UTC (permalink / raw)
  To: linuxppc-dev, wd, dzu, vlad; +Cc: Piotr Ziecik, Ilya Yanok
In-Reply-To: <1285676696-5358-1-git-send-email-yanok@emcraft.com>

While testing mpc512x-dma driver with dmatest module I've found that
I can hang the mpc512x-dma issueing request from multiple threads to
the single channel.
(insmod dmatest.ko max_channels=1 threads_per_chan=16)
After investingating this case I've managed to find that this happens
if and only if we have more than one quequed requests.
In this case the driver tries to make use of hardware scatter/gather
functionality. I've found two problems with scatter/gather:
 1. When TCD is copied form RAM to the TCD register space with memcpy_io()
e_sg bit eventually gets cleared. This results in only first TCD being
executed. I've added setting of e_sg bit excplicitly in the TCD registers.
BTW, what is the correct way to do this? (How can I use setbits with bitfield
structure?) After that hardware loads consecutive TCDs and we hit the
second issue.
 2. Existing code clears int_maj bit in the last TCD so we never get
an interrupt on transfefr completion.

With these fixes my tests with many threads of single channel succeed but
tests that use many channels simultaneously still don't work reliable.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
Cc: Piotr Ziecik <kosmo@semihalf.com>
---
 drivers/dma/mpc512x_dma.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 4e9cbf3..1bc04aa 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -252,11 +252,13 @@ static void mpc_dma_execute(struct mpc_dma_chan *mchan)
 		prev = mdesc;
 	}
 
-	prev->tcd->start = 0;
 	prev->tcd->int_maj = 1;
 
 	/* Send first descriptor in chain into hardware */
 	memcpy_toio(&mdma->tcd[cid], first->tcd, sizeof(struct mpc_dma_tcd));
+
+	if (first != prev)
+		mdma->tcd[cid].e_sg = 1;
 	out_8(&mdma->regs->dmassrt, cid);
 }
 
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH 2/3] mpc512x_dma: fix the hanged transfer issue
From: Ilya Yanok @ 2010-09-28 12:24 UTC (permalink / raw)
  To: linuxppc-dev, wd, dzu, vlad; +Cc: Piotr Ziecik, Ilya Yanok
In-Reply-To: <1285676696-5358-1-git-send-email-yanok@emcraft.com>

Current code clears interrupt active status _after_ submiting new
transfers. This leaves a possibility of clearing the interrupt for this
new transfer (if it is triggered fast enough) and thus lose this
interrupt. We want to clear interrupt active status _before_ new
transfers is submited and for current channel only.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
Cc: Piotr Ziecik <kosmo@semihalf.com>
---
 drivers/dma/mpc512x_dma.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 1bc04aa..0717527 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -276,6 +276,9 @@ static void mpc_dma_irq_process(struct mpc_dma *mdma, u32 is, u32 es, int off)
 
 		spin_lock(&mchan->lock);
 
+		out_8(&mdma->regs->dmacint, ch + off);
+		out_8(&mdma->regs->dmacerr, ch + off);
+
 		/* Check error status */
 		if (es & (1 << ch))
 			list_for_each_entry(mdesc, &mchan->active, node)
@@ -309,12 +312,6 @@ static irqreturn_t mpc_dma_irq(int irq, void *data)
 	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl),
 					in_be32(&mdma->regs->dmaerrl), 0);
 
-	/* Ack interrupt on all channels */
-	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
-
 	/* Schedule tasklet */
 	tasklet_schedule(&mdma->tasklet);
 
-- 
1.7.2.3

^ permalink raw reply related

* [PATCH 3/3] mpc512x_dma: add MPC8308 support
From: Ilya Yanok @ 2010-09-28 12:24 UTC (permalink / raw)
  To: linuxppc-dev, wd, dzu, vlad; +Cc: Piotr Ziecik, Ilya Yanok
In-Reply-To: <1285676696-5358-1-git-send-email-yanok@emcraft.com>

MPC8308 has pretty much the same DMA controller as MPC5121 and
this patch adds support for MPC8308 to the mpc512x_dma driver.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
Cc: Piotr Ziecik <kosmo@semihalf.com>
---
 drivers/dma/Kconfig       |    2 +-
 drivers/dma/mpc512x_dma.c |   95 +++++++++++++++++++++++++++++++++-----------
 2 files changed, 72 insertions(+), 25 deletions(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 9520cf0..5c5e95b 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -100,7 +100,7 @@ config FSL_DMA
 
 config MPC512X_DMA
 	tristate "Freescale MPC512x built-in DMA engine support"
-	depends on PPC_MPC512x
+	depends on PPC_MPC512x || PPC_MPC831x
 	select DMA_ENGINE
 	---help---
 	  Enable support for the Freescale MPC512x built-in DMA engine.
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 0717527..97b92ec 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008.
  * Copyright (C) Semihalf 2009
+ * Copyright (C) Ilya Yanok, Emcraft Systems 2010
  *
  * Written by Piotr Ziecik <kosmo@semihalf.com>. Hardware description
  * (defines, structures and comments) was taken from MPC5121 DMA driver
@@ -70,6 +71,8 @@
 #define MPC_DMA_DMAES_SBE	(1 << 1)
 #define MPC_DMA_DMAES_DBE	(1 << 0)
 
+#define MPC_DMA_DMAGPOR_SNOOP_ENABLE	(1 << 6)
+
 #define MPC_DMA_TSIZE_1		0x00
 #define MPC_DMA_TSIZE_2		0x01
 #define MPC_DMA_TSIZE_4		0x02
@@ -104,7 +107,10 @@ struct __attribute__ ((__packed__)) mpc_dma_regs {
 	/* 0x30 */
 	u32 dmahrsh;		/* DMA hw request status high(ch63~32) */
 	u32 dmahrsl;		/* DMA hardware request status low(ch31~0) */
-	u32 dmaihsa;		/* DMA interrupt high select AXE(ch63~32) */
+	union {
+		u32 dmaihsa;	/* DMA interrupt high select AXE(ch63~32) */
+		u32 dmagpor;	/* (General purpose register on MPC8308) */
+	};
 	u32 dmailsa;		/* DMA interrupt low select AXE(ch31~0) */
 	/* 0x40 ~ 0xff */
 	u32 reserve0[48];	/* Reserved */
@@ -195,7 +201,9 @@ struct mpc_dma {
 	struct mpc_dma_regs __iomem	*regs;
 	struct mpc_dma_tcd __iomem	*tcd;
 	int				irq;
+	int				irq2;
 	uint				error_status;
+	int				is_mpc8308;
 
 	/* Lock for error_status field in this structure */
 	spinlock_t			error_status_lock;
@@ -307,8 +315,10 @@ static irqreturn_t mpc_dma_irq(int irq, void *data)
 	spin_unlock(&mdma->error_status_lock);
 
 	/* Handle interrupt on each channel */
-	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
+	if (mdma->dma.chancnt > 32) {
+		mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmainth),
 					in_be32(&mdma->regs->dmaerrh), 32);
+	}
 	mpc_dma_irq_process(mdma, in_be32(&mdma->regs->dmaintl),
 					in_be32(&mdma->regs->dmaerrl), 0);
 
@@ -562,6 +572,7 @@ static struct dma_async_tx_descriptor *
 mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 					size_t len, unsigned long flags)
 {
+	struct mpc_dma *mdma = dma_chan_to_mpc_dma(chan);
 	struct mpc_dma_chan *mchan = dma_chan_to_mpc_dma_chan(chan);
 	struct mpc_dma_desc *mdesc = NULL;
 	struct mpc_dma_tcd *tcd;
@@ -590,7 +601,8 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 		tcd->dsize = MPC_DMA_TSIZE_32;
 		tcd->soff = 32;
 		tcd->doff = 32;
-	} else if (IS_ALIGNED(src | dst | len, 16)) {
+	} else if (!mdma->is_mpc8308 && IS_ALIGNED(src | dst | len, 16)) {
+		/* MPC8308 doesn't support 16 byte transfers */
 		tcd->ssize = MPC_DMA_TSIZE_16;
 		tcd->dsize = MPC_DMA_TSIZE_16;
 		tcd->soff = 16;
@@ -650,6 +662,15 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
 		return -EINVAL;
 	}
 
+	if (of_device_is_compatible(dn, "fsl,mpc8308-dma")) {
+		mdma->is_mpc8308 = 1;
+		mdma->irq2 = irq_of_parse_and_map(dn, 1);
+		if (mdma->irq2 == NO_IRQ) {
+			dev_err(dev, "Error mapping IRQ!\n");
+			return -EINVAL;
+		}
+	}
+
 	retval = of_address_to_resource(dn, 0, &res);
 	if (retval) {
 		dev_err(dev, "Error parsing memory region!\n");
@@ -680,11 +701,23 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
 		return -EINVAL;
 	}
 
+	if (mdma->is_mpc8308) {
+		retval = devm_request_irq(dev, mdma->irq2, &mpc_dma_irq, 0,
+				DRV_NAME, mdma);
+		if (retval) {
+			dev_err(dev, "Error requesting IRQ2!\n");
+			return -EINVAL;
+		}
+	}
+
 	spin_lock_init(&mdma->error_status_lock);
 
 	dma = &mdma->dma;
 	dma->dev = dev;
-	dma->chancnt = MPC_DMA_CHANNELS;
+	if (!mdma->is_mpc8308)
+		dma->chancnt = MPC_DMA_CHANNELS;
+	else
+		dma->chancnt = 16; /* MPC8308 DMA has only 16 channels */
 	dma->device_alloc_chan_resources = mpc_dma_alloc_chan_resources;
 	dma->device_free_chan_resources = mpc_dma_free_chan_resources;
 	dma->device_issue_pending = mpc_dma_issue_pending;
@@ -720,26 +753,40 @@ static int __devinit mpc_dma_probe(struct platform_device *op,
 	 * - Round-robin group arbitration,
 	 * - Round-robin channel arbitration.
 	 */
-	out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
-				MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
-
-	/* Disable hardware DMA requests */
-	out_be32(&mdma->regs->dmaerqh, 0);
-	out_be32(&mdma->regs->dmaerql, 0);
-
-	/* Disable error interrupts */
-	out_be32(&mdma->regs->dmaeeih, 0);
-	out_be32(&mdma->regs->dmaeeil, 0);
-
-	/* Clear interrupts status */
-	out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
-	out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
-
-	/* Route interrupts to IPIC */
-	out_be32(&mdma->regs->dmaihsa, 0);
-	out_be32(&mdma->regs->dmailsa, 0);
+	if (!mdma->is_mpc8308) {
+		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_EDCG |
+					MPC_DMA_DMACR_ERGA | MPC_DMA_DMACR_ERCA);
+
+		/* Disable hardware DMA requests */
+		out_be32(&mdma->regs->dmaerqh, 0);
+		out_be32(&mdma->regs->dmaerql, 0);
+
+		/* Disable error interrupts */
+		out_be32(&mdma->regs->dmaeeih, 0);
+		out_be32(&mdma->regs->dmaeeil, 0);
+
+		/* Clear interrupts status */
+		out_be32(&mdma->regs->dmainth, 0xFFFFFFFF);
+		out_be32(&mdma->regs->dmaintl, 0xFFFFFFFF);
+		out_be32(&mdma->regs->dmaerrh, 0xFFFFFFFF);
+		out_be32(&mdma->regs->dmaerrl, 0xFFFFFFFF);
+
+		/* Route interrupts to IPIC */
+		out_be32(&mdma->regs->dmaihsa, 0);
+		out_be32(&mdma->regs->dmailsa, 0);
+	} else {
+		/* MPC8308 has 16 channels and lacks some registers */
+		out_be32(&mdma->regs->dmacr, MPC_DMA_DMACR_ERCA);
+
+		/* enable snooping */
+		out_be32(&mdma->regs->dmagpor, MPC_DMA_DMAGPOR_SNOOP_ENABLE);
+		/* Disable error interrupts */
+		out_be32(&mdma->regs->dmaeeil, 0);
+
+		/* Clear interrupts status */
+		out_be32(&mdma->regs->dmaintl, 0xFFFF);
+		out_be32(&mdma->regs->dmaerrl, 0xFFFF);
+	}
 
 	/* Register DMA engine */
 	dev_set_drvdata(dev, mdma);
-- 
1.7.2.3

^ permalink raw reply related

* [RFC][PATCH 0/3] fixes and MPC8308 support for the mpc512x_dma driver
From: Ilya Yanok @ 2010-09-28 12:24 UTC (permalink / raw)
  To: linuxppc-dev, wd, dzu, vlad; +Cc: Piotr Ziecik, Ilya Yanok

Hello everybody,

I've found that mpc512x_dma doesn't work reliable in my tests (dmatest
module and NetPipe with CONFIG_NET_DMA enabled).
These patches fixes two issues I've found: inproper handling of
scatter/gather transfers and missing interrupts.
The third patch adds support for MPC8308 which has pretty much the same
DMA controller as MPC5121.

The first patch has an issue: I'm accessing IO space with direct memory
access not via accessor functions. I don't know how to use accessor
functions with bitfield structures.

Any comments would be appreciated.

With these patches applied my tests succeed both on MPC5121 and MPC8308.

Regards, Ilya.

Signed-off-by: Ilya Yanok <yanok@emcraft.com>
Cc: Piotr Ziecik <kosmo@semihalf.com>

^ permalink raw reply

* Re: [PATCH v2 1/3] powerpc/fsl_soc.c: remove FSL USB platform code
From: Anton Vorontsov @ 2010-09-28 11:40 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: David Brownell, Wolfgang Denk, Detlev Zundel, linux-usb,
	linuxppc-dev, Greg Kroah-Hartman
In-Reply-To: <1285666594-21150-2-git-send-email-agust@denx.de>

On Tue, Sep 28, 2010 at 11:36:32AM +0200, Anatolij Gustschin wrote:
> This removed code will be replaced by simple of_platform
> driver for creation of FSL USB platform devices which is
> added by next patch of the series.
> 
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: Kumar Gala <galak@kernel.crashing.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---

This is not bisectable. You have to merge 1/3 and 2/3.

Thanks,

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* Re: [PATCH v2 2/3] USB: add of_platform glue driver for FSL USB DR controller
From: Anatolij Gustschin @ 2010-09-28 11:35 UTC (permalink / raw)
  To: Grant Likely
  Cc: Greg Kroah-Hartman, Wolfgang Denk, Detlev Zundel, linux-usb,
	linuxppc-dev, David Brownell
In-Reply-To: <AANLkTinnodk8wA2aHXBjmZRhv_OFS+zQdb5Tc6of36jQ@mail.gmail.com>

Hi Grant,

On Tue, 28 Sep 2010 19:01:28 +0900
Grant Likely <grant.likely@secretlab.ca> wrote:
...
> Looks pretty good.  Comments below.  Main comment is that with the
> recent changes in mainline, this no longer needs to be an
> of_platform_driver.  It can be a plain old platform_driver instead.
> It gets registered as a platform_driver anyway, but of_platform_driver
> is a shim that adds a bit of overhead, so it is best to avoid it.
> I'll detail the changes you need to make in my comments below.

Thanks. I'll change to platform_driver. My reply below.

...
> > +{
> > + =A0 =A0 =A0 struct device_node *np =3D ofdev->dev.of_node;
> > + =A0 =A0 =A0 struct platform_device *usb_dev;
> > + =A0 =A0 =A0 struct fsl_usb2_platform_data data, *pdata;
> > + =A0 =A0 =A0 struct fsl_usb2_dev_data *dev_data;
> > + =A0 =A0 =A0 const unsigned char *prop;
> > + =A0 =A0 =A0 static unsigned int idx;
> > + =A0 =A0 =A0 int i;
> > +
> > + =A0 =A0 =A0 if (!of_device_is_available(np))
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> > +
> > + =A0 =A0 =A0 pdata =3D match->data;
> > + =A0 =A0 =A0 if (!pdata) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(&data, 0, sizeof(data));
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata =3D &data;
> > + =A0 =A0 =A0 }
>=20
> This is bad behaviour.  *match->data must not be modified in probe
> because multiple instances of the device can exist.  The target of
> pdata is modified later in the probe routine.
>=20
> However, the above 4 lines can be removed entirely since none of the
> fsl_usb2_mph_dr_of_match entries actually set the data pointer.  The
> local 'data' structure can be used directly.

A match entry for mpc5121 is added by the third patch. I'll fix
this so that only local 'data' structure is modified later in the
probe routine.

Thanks,
Anatolij

^ permalink raw reply

* Doubt about Linux PCIe infraestructure
From: Carlos Roberto Moratelli @ 2010-09-28 11:16 UTC (permalink / raw)
  To: linuxppc-dev

Hi,

I have a simple doubt about linux PCI/PCIe infraestructure.  

When I register a PCI driver using pci_register_driver() will the 
probe function be automatically called or will it just be called if PCI 
infraestructure match a Vendor and Device id on bus?

I am loading a PCI driver that register itself using 
pci_register_driver() but the probe function isn't called.

thanks,

Carlos R. Moratelli

^ permalink raw reply

* Re: Reserved pages in PowerPC
From: Ankita Garg @ 2010-09-28 10:28 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-mm
In-Reply-To: <1284673951.30449.93.camel@pasglop>

Hi Ben,

On Fri, Sep 17, 2010 at 07:52:31AM +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2010-09-16 at 17:38 +0530, Ankita Garg wrote:
> > Thanks Ben for taking a look at this. So I checked the rtas messages
> > on
> > the serial console and see the following:
> > 
> > instantiating rtas at 0x000000000f632000... done
> > 
> > Which does not correspond to the higher addresses that I see as
> > reserved
> > (observation on a 16G machine). 
> 
> Well, I'd suggest you audit prom_init.c which builds the reserve map,
> and the various memblock_reserve() calls in prom.c
>

I studied and instrumented memblock_reserve() and also reserve_mem().
However, all the reserved addresses seem to correspond to lower memory.
I also observed that these reserved addresses are accessed quite rapidly
when a workload is being run.. 

-- 
Regards,
Ankita Garg (ankita@in.ibm.com)
Linux Technology Center
IBM India Systems & Technology Labs,
Bangalore, India

^ permalink raw reply

* Re: [PATCH v2 2/3] USB: add of_platform glue driver for FSL USB DR controller
From: Grant Likely @ 2010-09-28 10:01 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: Greg Kroah-Hartman, Wolfgang Denk, Detlev Zundel, linux-usb,
	linuxppc-dev, David Brownell
In-Reply-To: <1285666594-21150-3-git-send-email-agust@denx.de>

Hi Anatolij

Looks pretty good.  Comments below.  Main comment is that with the
recent changes in mainline, this no longer needs to be an
of_platform_driver.  It can be a plain old platform_driver instead.
It gets registered as a platform_driver anyway, but of_platform_driver
is a shim that adds a bit of overhead, so it is best to avoid it.
I'll detail the changes you need to make in my comments below.

On Tue, Sep 28, 2010 at 6:36 PM, Anatolij Gustschin <agust@denx.de> wrote:
> The driver creates platform devices based on the information
> from USB nodes in the flat device tree. This is the replacement
> for old arch fsl_soc usb code removed by the previous patch.
> It uses usual of-style binding, available EHCI-HCD and UDC
> drivers can be bound to the created devices. The new of-style
> driver additionaly instantiates USB OTG platform device, as the
> appropriate USB OTG driver will be added soon.
>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> Cc: Kumar Gala <galak@kernel.crashing.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> ---
> v2:
> =A0- drop unneeded PPC_OF dependency
> =A0- fix spelling bug in mode table and fix coding style
> =A0- print a warning if no valid dr_mode found
> =A0- add remove hook to unregister platform devices
> =A0 created by probe. So the driver can be unbound
> =A0- fix OTG platform device creation order
> =A0- drop fs_initcall, replaced by module_init() now
> =A0- add module_exit(), MODULE_DESCRIPTION, MODULE_LICENSE
>
> =A0drivers/usb/gadget/Kconfig =A0 =A0 =A0 | =A0 =A01 +
> =A0drivers/usb/host/Kconfig =A0 =A0 =A0 =A0 | =A0 =A04 +
> =A0drivers/usb/host/Makefile =A0 =A0 =A0 =A0| =A0 =A01 +
> =A0drivers/usb/host/fsl-mph-dr-of.c | =A0213 ++++++++++++++++++++++++++++=
++++++++++
> =A04 files changed, 219 insertions(+), 0 deletions(-)
> =A0create mode 100644 drivers/usb/host/fsl-mph-dr-of.c
>
> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
> index fab765d..0fe5bc8 100644
> --- a/drivers/usb/gadget/Kconfig
> +++ b/drivers/usb/gadget/Kconfig
> @@ -158,6 +158,7 @@ config USB_GADGET_FSL_USB2
> =A0 =A0 =A0 =A0boolean "Freescale Highspeed USB DR Peripheral Controller"
> =A0 =A0 =A0 =A0depends on FSL_SOC || ARCH_MXC
> =A0 =A0 =A0 =A0select USB_GADGET_DUALSPEED
> + =A0 =A0 =A0 select USB_FSL_MPH_DR_OF
> =A0 =A0 =A0 =A0help
> =A0 =A0 =A0 =A0 =A0 Some of Freescale PowerPC processors have a High Spee=
d
> =A0 =A0 =A0 =A0 =A0 Dual-Role(DR) USB controller, which supports device m=
ode.
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 2d926ce..f3a90b0 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -112,10 +112,14 @@ config XPS_USB_HCD_XILINX
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0support both high speed and full speed dev=
ices, or high speed
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0devices only.
>
> +config USB_FSL_MPH_DR_OF
> + =A0 =A0 =A0 tristate
> +
> =A0config USB_EHCI_FSL
> =A0 =A0 =A0 =A0bool "Support for Freescale on-chip EHCI USB controller"
> =A0 =A0 =A0 =A0depends on USB_EHCI_HCD && FSL_SOC
> =A0 =A0 =A0 =A0select USB_EHCI_ROOT_HUB_TT
> + =A0 =A0 =A0 select USB_FSL_MPH_DR_OF
> =A0 =A0 =A0 =A0---help---
> =A0 =A0 =A0 =A0 =A0Variation of ARC USB block used in some Freescale chip=
s.
>
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index b6315aa..aacbe82 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -33,4 +33,5 @@ obj-$(CONFIG_USB_R8A66597_HCD) =A0 =A0 =A0 =A0+=3D r8a6=
6597-hcd.o
> =A0obj-$(CONFIG_USB_ISP1760_HCD) =A0+=3D isp1760.o
> =A0obj-$(CONFIG_USB_HWA_HCD) =A0 =A0 =A0+=3D hwa-hc.o
> =A0obj-$(CONFIG_USB_IMX21_HCD) =A0 =A0+=3D imx21-hcd.o
> +obj-$(CONFIG_USB_FSL_MPH_DR_OF) =A0 =A0 =A0 =A0+=3D fsl-mph-dr-of.o
>
> diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-=
dr-of.c
> new file mode 100644
> index 0000000..ee8cb94
> --- /dev/null
> +++ b/drivers/usb/host/fsl-mph-dr-of.c
> @@ -0,0 +1,213 @@
> +/*
> + * Setup platform devices needed by the Freescale multi-port host
> + * and/or dual-role USB controller modules based on the description
> + * in flat device tree.
> + *
> + * This program is free software; you can redistribute =A0it and/or modi=
fy it
> + * under =A0the terms of =A0the GNU General =A0Public License as publish=
ed by the
> + * Free Software Foundation; =A0either version 2 of the =A0License, or (=
at your
> + * option) any later version.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/platform_device.h>
> +#include <linux/fsl_devices.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of_platform.h>
> +
> +struct fsl_usb2_dev_data {
> + =A0 =A0 =A0 char *dr_mode; =A0 =A0 =A0 =A0 =A0/* controller mode */
> + =A0 =A0 =A0 char *drivers[3]; =A0 =A0 =A0 /* drivers to instantiate for=
 this mode */
> + =A0 =A0 =A0 enum fsl_usb2_operating_modes op_mode; =A0/* operating mode=
 */
> +};
> +
> +struct fsl_usb2_dev_data dr_mode_data[] __devinitdata =3D {
> + =A0 =A0 =A0 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .dr_mode =3D "host",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .drivers =3D { "fsl-ehci", NULL, NULL, },
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .op_mode =3D FSL_USB2_DR_HOST,
> + =A0 =A0 =A0 },
> + =A0 =A0 =A0 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .dr_mode =3D "otg",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .drivers =3D { "fsl-usb2-otg", "fsl-ehci", =
"fsl-usb2-udc", },
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .op_mode =3D FSL_USB2_DR_OTG,
> + =A0 =A0 =A0 },
> + =A0 =A0 =A0 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .dr_mode =3D "peripheral",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .drivers =3D { "fsl-usb2-udc", NULL, NULL, =
},
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .op_mode =3D FSL_USB2_DR_DEVICE,
> + =A0 =A0 =A0 },
> +};
> +
> +struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node=
 *np)
> +{
> + =A0 =A0 =A0 const unsigned char *prop;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 prop =3D of_get_property(np, "dr_mode", NULL);
> + =A0 =A0 =A0 if (prop) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (i =3D 0; i < ARRAY_SIZE(dr_mode_data);=
 i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!strcmp(prop, dr_mode_d=
ata[i].dr_mode))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return &dr_=
mode_data[i];
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 pr_warn("%s: Invalid 'dr_mode' property, fallback to host m=
ode\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 np->full_name);
> + =A0 =A0 =A0 return &dr_mode_data[0]; /* mode not specified, use host */
> +}
> +
> +static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *p=
hy_type)
> +{
> + =A0 =A0 =A0 if (!phy_type)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return FSL_USB2_PHY_NONE;
> + =A0 =A0 =A0 if (!strcasecmp(phy_type, "ulpi"))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return FSL_USB2_PHY_ULPI;
> + =A0 =A0 =A0 if (!strcasecmp(phy_type, "utmi"))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return FSL_USB2_PHY_UTMI;
> + =A0 =A0 =A0 if (!strcasecmp(phy_type, "utmi_wide"))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return FSL_USB2_PHY_UTMI_WIDE;
> + =A0 =A0 =A0 if (!strcasecmp(phy_type, "serial"))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return FSL_USB2_PHY_SERIAL;
> +
> + =A0 =A0 =A0 return FSL_USB2_PHY_NONE;
> +}
> +
> +struct platform_device * __devinit fsl_usb2_device_register(
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 struct platform_device *ofdev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 struct fsl_usb2_platform_data *pdata,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 const char *name, int id)
> +{
> + =A0 =A0 =A0 struct platform_device *pdev;
> + =A0 =A0 =A0 const struct resource *res =3D ofdev->resource;
> + =A0 =A0 =A0 unsigned int num =3D ofdev->num_resources;
> + =A0 =A0 =A0 int retval;
> +
> + =A0 =A0 =A0 pdev =3D platform_device_alloc(name, id);
> + =A0 =A0 =A0 if (!pdev) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval =3D -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto error;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 pdev->dev.parent =3D &ofdev->dev;
> +
> + =A0 =A0 =A0 pdev->dev.coherent_dma_mask =3D ofdev->dev.coherent_dma_mas=
k;
> + =A0 =A0 =A0 pdev->dev.dma_mask =3D &pdev->archdata.dma_mask;
> + =A0 =A0 =A0 *pdev->dev.dma_mask =3D *ofdev->dev.dma_mask;
> +
> + =A0 =A0 =A0 retval =3D platform_device_add_data(pdev, pdata, sizeof(*pd=
ata));
> + =A0 =A0 =A0 if (retval)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto error;
> +
> + =A0 =A0 =A0 if (num) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval =3D platform_device_add_resources(pd=
ev, res, num);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (retval)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto error;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 retval =3D platform_device_add(pdev);
> + =A0 =A0 =A0 if (retval)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto error;
> +
> + =A0 =A0 =A0 return pdev;
> +
> +error:
> + =A0 =A0 =A0 platform_device_put(pdev);
> + =A0 =A0 =A0 return ERR_PTR(retval);
> +}
> +
> +static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *of=
dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0const struct of_device_id *match)

Change to:
static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev=
)

You can get the 'match' pointer by calling of_match_device().

> +{
> + =A0 =A0 =A0 struct device_node *np =3D ofdev->dev.of_node;
> + =A0 =A0 =A0 struct platform_device *usb_dev;
> + =A0 =A0 =A0 struct fsl_usb2_platform_data data, *pdata;
> + =A0 =A0 =A0 struct fsl_usb2_dev_data *dev_data;
> + =A0 =A0 =A0 const unsigned char *prop;
> + =A0 =A0 =A0 static unsigned int idx;
> + =A0 =A0 =A0 int i;
> +
> + =A0 =A0 =A0 if (!of_device_is_available(np))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> +
> + =A0 =A0 =A0 pdata =3D match->data;
> + =A0 =A0 =A0 if (!pdata) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(&data, 0, sizeof(data));
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata =3D &data;
> + =A0 =A0 =A0 }

This is bad behaviour.  *match->data must not be modified in probe
because multiple instances of the device can exist.  The target of
pdata is modified later in the probe routine.

However, the above 4 lines can be removed entirely since none of the
fsl_usb2_mph_dr_of_match entries actually set the data pointer.  The
local 'data' structure can be used directly.

> +
> + =A0 =A0 =A0 dev_data =3D get_dr_mode_data(np);
> +
> + =A0 =A0 =A0 if (of_device_is_compatible(np, "fsl-usb2-mph")) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "port0", NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->port_enables |=3D FS=
L_USB2_PORT0_ENABLED;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "port1", NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->port_enables |=3D FS=
L_USB2_PORT1_ENABLED;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->operating_mode =3D FSL_USB2_MPH_HOST=
;
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* setup mode selected in the device tree *=
/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->operating_mode =3D dev_data->op_mode=
;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 prop =3D of_get_property(np, "phy_type", NULL);
> + =A0 =A0 =A0 pdata->phy_mode =3D determine_usb_phy(prop);
> +
> + =A0 =A0 =A0 for (i =3D 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!dev_data->drivers[i])
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 usb_dev =3D fsl_usb2_device_register(ofdev,=
 pdata,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 dev_data->drivers[i], idx);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (IS_ERR(usb_dev)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&ofdev->dev, "Can't=
 register usb device\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return PTR_ERR(usb_dev);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 idx++;
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static int __devexit __unregister_subdev(struct device *dev, void *d)
> +{
> + =A0 =A0 =A0 platform_device_unregister(to_platform_device(dev));
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *o=
fdev)
> +{
> + =A0 =A0 =A0 device_for_each_child(&ofdev->dev, NULL, __unregister_subde=
v);
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static const struct of_device_id fsl_usb2_mph_dr_of_match[] =3D {
> + =A0 =A0 =A0 { .compatible =3D "fsl-usb2-mph", },
> + =A0 =A0 =A0 { .compatible =3D "fsl-usb2-dr", },
> + =A0 =A0 =A0 {},
> +};
> +
> +static struct of_platform_driver fsl_usb2_mph_dr_driver =3D {
> + =A0 =A0 =A0 .driver =3D {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .name =3D "fsl-usb2-mph-dr",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .owner =3D THIS_MODULE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 .of_match_table =3D fsl_usb2_mph_dr_of_matc=
h,
> + =A0 =A0 =A0 },
> + =A0 =A0 =A0 .probe =A0=3D fsl_usb2_mph_dr_of_probe,
> + =A0 =A0 =A0 .remove =3D __devexit_p(fsl_usb2_mph_dr_of_remove),
> +};

Change of_platform_driver to platform_driver

> +
> +static int __init fsl_usb2_mph_dr_init(void)
> +{
> + =A0 =A0 =A0 return of_register_platform_driver(&fsl_usb2_mph_dr_driver)=
;

change to platform_driver_register()

> +}
> +module_init(fsl_usb2_mph_dr_init);
> +
> +static void __exit fsl_usb2_mph_dr_exit(void)
> +{
> + =A0 =A0 =A0 of_unregister_platform_driver(&fsl_usb2_mph_dr_driver);

change to platform_driver_unregister()

> +}
> +module_exit(fsl_usb2_mph_dr_exit);
> +
> +MODULE_DESCRIPTION("FSL MPH DR OF devices driver");
> +MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
> +MODULE_LICENSE("GPL");
> --
> 1.7.0.4
>
>



--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH 2/8] v2 Add section count to memory_block struct
From: Robin Holt @ 2010-09-28  9:31 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linuxppc-dev, Greg KH, linux-kernel, Dave Hansen, linux-mm,
	KAMEZAWA Hiroyuki
In-Reply-To: <4CA0EEF0.70402@austin.ibm.com>

In the next patch, you introduce a mutex for adding/removing memory blocks.
Is there really a need for this to be atomic?  If you reorder the patches
so the mutex comes first, would the atomic be needed any longer?

Robin

On Mon, Sep 27, 2010 at 02:22:24PM -0500, Nathan Fontenot wrote:
> Add a section count property to the memory_block struct to track the number
> of memory sections that have been added/removed from a memory block. This
> allows us to know when the last memory section of a memory block has been
> removed so we can remove the memory block.
> 
> Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
> 
> ---
>  drivers/base/memory.c  |   16 ++++++++++------
>  include/linux/memory.h |    3 +++
>  2 files changed, 13 insertions(+), 6 deletions(-)
> 
> Index: linux-next/drivers/base/memory.c
> ===================================================================
> --- linux-next.orig/drivers/base/memory.c	2010-09-27 09:17:20.000000000 -0500
> +++ linux-next/drivers/base/memory.c	2010-09-27 09:31:35.000000000 -0500
> @@ -478,6 +478,7 @@
>  
>  	mem->phys_index = __section_nr(section);
>  	mem->state = state;
> +	atomic_inc(&mem->section_count);
>  	mutex_init(&mem->state_mutex);
>  	start_pfn = section_nr_to_pfn(mem->phys_index);
>  	mem->phys_device = arch_get_memory_phys_device(start_pfn);
> @@ -505,12 +506,15 @@
>  	struct memory_block *mem;
>  
>  	mem = find_memory_block(section);
> -	unregister_mem_sect_under_nodes(mem);
> -	mem_remove_simple_file(mem, phys_index);
> -	mem_remove_simple_file(mem, state);
> -	mem_remove_simple_file(mem, phys_device);
> -	mem_remove_simple_file(mem, removable);
> -	unregister_memory(mem, section);
> +
> +	if (atomic_dec_and_test(&mem->section_count)) {
> +		unregister_mem_sect_under_nodes(mem);
> +		mem_remove_simple_file(mem, phys_index);
> +		mem_remove_simple_file(mem, state);
> +		mem_remove_simple_file(mem, phys_device);
> +		mem_remove_simple_file(mem, removable);
> +		unregister_memory(mem, section);
> +	}
>  
>  	return 0;
>  }
> Index: linux-next/include/linux/memory.h
> ===================================================================
> --- linux-next.orig/include/linux/memory.h	2010-09-27 09:17:20.000000000 -0500
> +++ linux-next/include/linux/memory.h	2010-09-27 09:22:56.000000000 -0500
> @@ -19,10 +19,13 @@
>  #include <linux/node.h>
>  #include <linux/compiler.h>
>  #include <linux/mutex.h>
> +#include <asm/atomic.h>
>  
>  struct memory_block {
>  	unsigned long phys_index;
>  	unsigned long state;
> +	atomic_t section_count;
> +
>  	/*
>  	 * This serializes all state change requests.  It isn't
>  	 * held during creation because the control files are
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* [PATCH v2 3/3] USB: add USB EHCI support for MPC5121 SoC
From: Anatolij Gustschin @ 2010-09-28  9:36 UTC (permalink / raw)
  To: linux-usb
  Cc: David Brownell, Wolfgang Denk, Detlev Zundel, Greg Kroah-Hartman,
	linuxppc-dev, Anatolij Gustschin
In-Reply-To: <1285666594-21150-1-git-send-email-agust@denx.de>

Extends FSL EHCI platform driver glue layer to support
MPC5121 USB controllers. MPC5121 Rev 2.0 silicon EHCI
registers are in big endian format. The appropriate flags
are set using the information in the platform data structure.
MPC83xx system interface registers are not available on
MPC512x, so the access to these registers is isolated in
MPC512x case. Furthermore the USB controller clocks
must be enabled before 512x register accesses which is
done by providing platform specific init callback.

The MPC512x internal USB PHY doesn't provide supply voltage.
For boards using different power switches allow specifying
DRVVBUS and PWR_FAULT signal polarity of the MPC5121 internal
PHY using "fsl,invert-drvvbus" and "fsl,invert-pwr-fault"
properties in the device tree USB nodes. Adds documentation
for this new device tree bindings.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
v2:
 - rebased on linux-next
 - remove host mode setting in usb_hcd_fsl_probe() since
   this is set in tdi_reset() anyway
 - drop now unneeded defines previously used for host
   mode setting
   
 Documentation/powerpc/dts-bindings/fsl/usb.txt |   22 +++++
 drivers/usb/Kconfig                            |    1 +
 drivers/usb/host/Kconfig                       |    6 +-
 drivers/usb/host/ehci-fsl.c                    |   99 +++++++++++++++++-------
 drivers/usb/host/ehci-fsl.h                    |   13 +++-
 drivers/usb/host/ehci-mem.c                    |    2 +-
 drivers/usb/host/fsl-mph-dr-of.c               |   89 +++++++++++++++++++++
 include/linux/fsl_devices.h                    |   15 ++++
 8 files changed, 215 insertions(+), 32 deletions(-)

diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentation/powerpc/dts-bindings/fsl/usb.txt
index b001524..bd5723f 100644
--- a/Documentation/powerpc/dts-bindings/fsl/usb.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/usb.txt
@@ -8,6 +8,7 @@ and additions :
 Required properties :
  - compatible : Should be "fsl-usb2-mph" for multi port host USB
    controllers, or "fsl-usb2-dr" for dual role USB controllers
+   or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
  - phy_type : For multi port host USB controllers, should be one of
    "ulpi", or "serial". For dual role USB controllers, should be
    one of "ulpi", "utmi", "utmi_wide", or "serial".
@@ -33,6 +34,12 @@ Recommended properties :
  - interrupt-parent : the phandle for the interrupt controller that
    services interrupts for this device.
 
+Optional properties :
+ - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
+   port power polarity of internal PHY signal DRVVBUS is inverted.
+ - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
+   the PWR_FAULT signal polarity is inverted.
+
 Example multi port host USB controller device node :
 	usb@22000 {
 		compatible = "fsl-usb2-mph";
@@ -57,3 +64,18 @@ Example dual role USB controller device node :
 		dr_mode = "otg";
 		phy = "ulpi";
 	};
+
+Example dual role USB controller device node for MPC5121ADS:
+
+	usb@4000 {
+		compatible = "fsl,mpc5121-usb2-dr";
+		reg = <0x4000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-parent = < &ipic >;
+		interrupts = <44 0x8>;
+		dr_mode = "otg";
+		phy_type = "utmi_wide";
+		fsl,invert-drvvbus;
+		fsl,invert-pwr-fault;
+	};
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4aa00e6..67eb377 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -59,6 +59,7 @@ config USB_ARCH_HAS_OHCI
 config USB_ARCH_HAS_EHCI
 	boolean
 	default y if PPC_83xx
+	default y if PPC_MPC512x
 	default y if SOC_AU1200
 	default y if ARCH_IXP4XX
 	default y if ARCH_W90X900
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f3a90b0..bf2e7d2 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -93,12 +93,14 @@ config USB_EHCI_TT_NEWSCHED
 
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
-	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
+	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || ARCH_IXP4XX || \
+				    XPS_USB_HCD_XILINX || PPC_MPC512x)
 	default y
 
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
-	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
+	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
+				    PPC_MPC512x)
 	default y
 
 config XPS_USB_HCD_XILINX
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 8600317..86e4289 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -116,13 +116,33 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 		goto err3;
 	}
 
-	/* Enable USB controller */
-	temp = in_be32(hcd->regs + 0x500);
-	out_be32(hcd->regs + 0x500, temp | 0x4);
+	pdata->regs = hcd->regs;
 
-	/* Set to Host mode */
-	temp = in_le32(hcd->regs + 0x1a8);
-	out_le32(hcd->regs + 0x1a8, temp | 0x3);
+	/*
+	 * do platform specific init: check the clock, grab/config pins, etc.
+	 */
+	if (pdata->init && pdata->init(pdev)) {
+		retval = -ENODEV;
+		goto err3;
+	}
+
+	/*
+	 * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs
+	 * flag for 83xx or 8536 system interface registers.
+	 */
+	if (pdata->big_endian_mmio)
+		temp = in_be32(hcd->regs + FSL_SOC_USB_ID);
+	else
+		temp = in_le32(hcd->regs + FSL_SOC_USB_ID);
+
+	if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK))
+		pdata->have_sysif_regs = 1;
+
+	/* Enable USB controller, 83xx or 8536 */
+	if (pdata->have_sysif_regs)
+		setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+
+	/* Don't need to set host mode here. It will be done by tdi_reset() */
 
 	retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval != 0)
@@ -137,6 +157,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 	usb_put_hcd(hcd);
       err1:
 	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
+	if (pdata->exit)
+		pdata->exit(pdev);
 	return retval;
 }
 
@@ -154,17 +176,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
 static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
 			       struct platform_device *pdev)
 {
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
 	usb_remove_hcd(hcd);
+
+	/*
+	 * do platform specific un-initialization:
+	 * release iomux pins, disable clock, etc.
+	 */
+	if (pdata->exit)
+		pdata->exit(pdev);
 	iounmap(hcd->regs);
 	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	usb_put_hcd(hcd);
 }
 
-static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
-			      enum fsl_usb2_phy_modes phy_mode,
-			      unsigned int port_offset)
+static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
+			       enum fsl_usb2_phy_modes phy_mode,
+			       unsigned int port_offset)
 {
-	u32 portsc = 0;
+	u32 portsc;
+
+	portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
+	portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
+
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
 		portsc |= PORT_PTS_ULPI;
@@ -184,20 +219,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
 	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 }
 
-static void mpc83xx_usb_setup(struct usb_hcd *hcd)
+static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
 {
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct usb_hcd *hcd = ehci_to_hcd(ehci);
 	struct fsl_usb2_platform_data *pdata;
 	void __iomem *non_ehci = hcd->regs;
 	u32 temp;
 
-	pdata =
-	    (struct fsl_usb2_platform_data *)hcd->self.controller->
-	    platform_data;
+	pdata = hcd->self.controller->platform_data;
+
 	/* Enable PHY interface in the control reg. */
-	temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
-	out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
-	out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	if (pdata->have_sysif_regs) {
+		temp = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+		out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
+		out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
+	}
 
 #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
 	/*
@@ -214,7 +250,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
 
 	if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
 			(pdata->operating_mode == FSL_USB2_DR_OTG))
-		mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+		ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 
 	if (pdata->operating_mode == FSL_USB2_MPH_HOST) {
 		unsigned int chip, rev, svr;
@@ -228,25 +264,27 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
 			ehci->has_fsl_port_bug = 1;
 
 		if (pdata->port_enables & FSL_USB2_PORT0_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 0);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0);
 		if (pdata->port_enables & FSL_USB2_PORT1_ENABLED)
-			mpc83xx_setup_phy(ehci, pdata->phy_mode, 1);
+			ehci_fsl_setup_phy(ehci, pdata->phy_mode, 1);
 	}
 
+	if (pdata->have_sysif_regs) {
 #ifdef CONFIG_PPC_85xx
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
 #else
-	out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
-	out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
+		out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
+		out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
 #endif
-	out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+		out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
+	}
 }
 
 /* called after powerup, by probe or system-pm "wakeup" */
 static int ehci_fsl_reinit(struct ehci_hcd *ehci)
 {
-	mpc83xx_usb_setup(ehci_to_hcd(ehci));
+	ehci_fsl_usb_setup(ehci);
 	ehci_port_power(ehci, 0);
 
 	return 0;
@@ -257,6 +295,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
+	struct fsl_usb2_platform_data *pdata;
+
+	pdata = hcd->self.controller->platform_data;
+	ehci->big_endian_desc = pdata->big_endian_desc;
+	ehci->big_endian_mmio = pdata->big_endian_mmio;
 
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
@@ -370,7 +413,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
 	 * generic hardware linkage
 	 */
 	.irq = ehci_irq,
-	.flags = HCD_USB2,
+	.flags = HCD_USB2 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index eb537aa..2c83537 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2005 freescale semiconductor
+/* Copyright (C) 2005-2010 Freescale Semiconductor, Inc.
  * Copyright (c) 2005 MontaVista Software
  *
  * This program is free software; you can redistribute  it and/or modify it
@@ -19,6 +19,9 @@
 #define _EHCI_FSL_H
 
 /* offsets for the non-ehci registers in the FSL SOC USB controller */
+#define FSL_SOC_USB_ID		0x0
+#define ID_MSK			0x3f
+#define NID_MSK			0x3f00
 #define FSL_SOC_USB_ULPIVP	0x170
 #define FSL_SOC_USB_PORTSC1	0x184
 #define PORT_PTS_MSK		(3<<30)
@@ -27,6 +30,14 @@
 #define	PORT_PTS_SERIAL		(3<<30)
 #define PORT_PTS_PTW		(1<<28)
 #define FSL_SOC_USB_PORTSC2	0x188
+
+#define FSL_SOC_USB_USBGENCTRL	0x200
+#define USBGENCTRL_PPP		(1 << 3)
+#define USBGENCTRL_PFP		(1 << 2)
+#define FSL_SOC_USB_ISIPHYCTRL	0x204
+#define ISIPHYCTRL_PXE		(1)
+#define ISIPHYCTRL_PHYE		(1 << 4)
+
 #define FSL_SOC_USB_SNOOP1	0x400	/* NOTE: big-endian */
 #define FSL_SOC_USB_SNOOP2	0x404	/* NOTE: big-endian */
 #define FSL_SOC_USB_AGECNTTHRSH	0x408	/* NOTE: big-endian */
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index 1f3f01e..d36e4e7 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -40,7 +40,7 @@ static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd,
 {
 	memset (qtd, 0, sizeof *qtd);
 	qtd->qtd_dma = dma;
-	qtd->hw_token = cpu_to_le32 (QTD_STS_HALT);
+	qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
 	qtd->hw_next = EHCI_LIST_END(ehci);
 	qtd->hw_alt_next = EHCI_LIST_END(ehci);
 	INIT_LIST_HEAD (&qtd->qtd_list);
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index ee8cb94..7e99ddd 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of_platform.h>
+#include <linux/clk.h>
 
 struct fsl_usb2_dev_data {
 	char *dr_mode;		/* controller mode */
@@ -147,6 +148,12 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev,
 
 		pdata->operating_mode = FSL_USB2_MPH_HOST;
 	} else {
+		if (of_get_property(np, "fsl,invert-drvvbus", NULL))
+			pdata->invert_drvvbus = 1;
+
+		if (of_get_property(np, "fsl,invert-pwr-fault", NULL))
+			pdata->invert_pwr_fault = 1;
+
 		/* setup mode selected in the device tree */
 		pdata->operating_mode = dev_data->op_mode;
 	}
@@ -180,9 +187,91 @@ static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
 	return 0;
 }
 
+#ifdef CONFIG_PPC_MPC512x
+
+#define USBGENCTRL		0x200		/* NOTE: big endian */
+#define GC_WU_INT_CLR		(1 << 5)	/* Wakeup int clear */
+#define GC_ULPI_SEL		(1 << 4)	/* ULPI i/f select (usb0 only)*/
+#define GC_PPP			(1 << 3)	/* Inv. Port Power Polarity */
+#define GC_PFP			(1 << 2)	/* Inv. Power Fault Polarity */
+#define GC_WU_ULPI_EN		(1 << 1)	/* Wakeup on ULPI event */
+#define GC_WU_IE		(1 << 1)	/* Wakeup interrupt enable */
+
+#define ISIPHYCTRL		0x204		/* NOTE: big endian */
+#define PHYCTRL_PHYE		(1 << 4)	/* On-chip UTMI PHY enable */
+#define PHYCTRL_BSENH		(1 << 3)	/* Bit Stuff Enable High */
+#define PHYCTRL_BSEN		(1 << 2)	/* Bit Stuff Enable */
+#define PHYCTRL_LSFE		(1 << 1)	/* Line State Filter Enable */
+#define PHYCTRL_PXE		(1 << 0)	/* PHY oscillator enable */
+
+int fsl_usb2_mpc5121_init(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *clk;
+	char clk_name[10];
+	int base, clk_num;
+
+	base = pdev->resource->start & 0xf000;
+	if (base == 0x3000)
+		clk_num = 1;
+	else if (base == 0x4000)
+		clk_num = 2;
+	else
+		return -ENODEV;
+
+	snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
+	clk = clk_get(&pdev->dev, clk_name);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "failed to get clk\n");
+		return PTR_ERR(clk);
+	}
+
+	clk_enable(clk);
+	pdata->clk = clk;
+
+	if (pdata->phy_mode == FSL_USB2_PHY_UTMI_WIDE) {
+		u32 reg = 0;
+
+		if (pdata->invert_drvvbus)
+			reg |= GC_PPP;
+
+		if (pdata->invert_pwr_fault)
+			reg |= GC_PFP;
+
+		out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_PHYE | PHYCTRL_PXE);
+		out_be32(pdata->regs + USBGENCTRL, reg);
+	}
+	return 0;
+}
+
+static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
+{
+	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
+
+	pdata->regs = NULL;
+
+	if (pdata->clk) {
+		clk_disable(pdata->clk);
+		clk_put(pdata->clk);
+	}
+}
+
+struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = {
+	.big_endian_desc = 1,
+	.big_endian_mmio = 1,
+	.es = 1,
+	.le_setup_buf = 1,
+	.init = fsl_usb2_mpc5121_init,
+	.exit = fsl_usb2_mpc5121_exit,
+};
+#endif /* CONFIG_PPC_MPC512x */
+
 static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
 	{ .compatible = "fsl-usb2-mph", },
 	{ .compatible = "fsl-usb2-dr", },
+#ifdef CONFIG_PPC_MPC512x
+	{ .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, },
+#endif
 	{},
 };
 
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 28e33fe..d5f9a74 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -58,11 +58,26 @@ enum fsl_usb2_phy_modes {
 	FSL_USB2_PHY_SERIAL,
 };
 
+struct clk;
+struct platform_device;
+
 struct fsl_usb2_platform_data {
 	/* board specific information */
 	enum fsl_usb2_operating_modes	operating_mode;
 	enum fsl_usb2_phy_modes		phy_mode;
 	unsigned int			port_enables;
+
+	int		(*init)(struct platform_device *);
+	void		(*exit)(struct platform_device *);
+	void __iomem	*regs;		/* ioremap'd register base */
+	struct clk	*clk;
+	unsigned	big_endian_mmio:1;
+	unsigned	big_endian_desc:1;
+	unsigned	es:1;		/* need USBMODE:ES */
+	unsigned	le_setup_buf:1;
+	unsigned	have_sysif_regs:1;
+	unsigned	invert_drvvbus:1;
+	unsigned	invert_pwr_fault:1;
 };
 
 /* Flags in fsl_usb2_mph_platform_data */
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH v2 2/3] USB: add of_platform glue driver for FSL USB DR controller
From: Anatolij Gustschin @ 2010-09-28  9:36 UTC (permalink / raw)
  To: linux-usb
  Cc: David Brownell, Wolfgang Denk, Detlev Zundel, Greg Kroah-Hartman,
	linuxppc-dev, Anatolij Gustschin
In-Reply-To: <1285666594-21150-1-git-send-email-agust@denx.de>

The driver creates platform devices based on the information
from USB nodes in the flat device tree. This is the replacement
for old arch fsl_soc usb code removed by the previous patch.
It uses usual of-style binding, available EHCI-HCD and UDC
drivers can be bound to the created devices. The new of-style
driver additionaly instantiates USB OTG platform device, as the
appropriate USB OTG driver will be added soon.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
v2:
 - drop unneeded PPC_OF dependency
 - fix spelling bug in mode table and fix coding style
 - print a warning if no valid dr_mode found
 - add remove hook to unregister platform devices
   created by probe. So the driver can be unbound
 - fix OTG platform device creation order
 - drop fs_initcall, replaced by module_init() now
 - add module_exit(), MODULE_DESCRIPTION, MODULE_LICENSE

 drivers/usb/gadget/Kconfig       |    1 +
 drivers/usb/host/Kconfig         |    4 +
 drivers/usb/host/Makefile        |    1 +
 drivers/usb/host/fsl-mph-dr-of.c |  213 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 219 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/host/fsl-mph-dr-of.c

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index fab765d..0fe5bc8 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -158,6 +158,7 @@ config USB_GADGET_FSL_USB2
 	boolean "Freescale Highspeed USB DR Peripheral Controller"
 	depends on FSL_SOC || ARCH_MXC
 	select USB_GADGET_DUALSPEED
+	select USB_FSL_MPH_DR_OF
 	help
 	   Some of Freescale PowerPC processors have a High Speed
 	   Dual-Role(DR) USB controller, which supports device mode.
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 2d926ce..f3a90b0 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -112,10 +112,14 @@ config XPS_USB_HCD_XILINX
 		support both high speed and full speed devices, or high speed
 		devices only.
 
+config USB_FSL_MPH_DR_OF
+	tristate
+
 config USB_EHCI_FSL
 	bool "Support for Freescale on-chip EHCI USB controller"
 	depends on USB_EHCI_HCD && FSL_SOC
 	select USB_EHCI_ROOT_HUB_TT
+	select USB_FSL_MPH_DR_OF
 	---help---
 	  Variation of ARC USB block used in some Freescale chips.
 
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index b6315aa..aacbe82 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -33,4 +33,5 @@ obj-$(CONFIG_USB_R8A66597_HCD)	+= r8a66597-hcd.o
 obj-$(CONFIG_USB_ISP1760_HCD)	+= isp1760.o
 obj-$(CONFIG_USB_HWA_HCD)	+= hwa-hc.o
 obj-$(CONFIG_USB_IMX21_HCD)	+= imx21-hcd.o
+obj-$(CONFIG_USB_FSL_MPH_DR_OF)	+= fsl-mph-dr-of.o
 
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
new file mode 100644
index 0000000..ee8cb94
--- /dev/null
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -0,0 +1,213 @@
+/*
+ * Setup platform devices needed by the Freescale multi-port host
+ * and/or dual-role USB controller modules based on the description
+ * in flat device tree.
+ *
+ * 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/platform_device.h>
+#include <linux/fsl_devices.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+
+struct fsl_usb2_dev_data {
+	char *dr_mode;		/* controller mode */
+	char *drivers[3];	/* drivers to instantiate for this mode */
+	enum fsl_usb2_operating_modes op_mode;	/* operating mode */
+};
+
+struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = {
+	{
+		.dr_mode = "host",
+		.drivers = { "fsl-ehci", NULL, NULL, },
+		.op_mode = FSL_USB2_DR_HOST,
+	},
+	{
+		.dr_mode = "otg",
+		.drivers = { "fsl-usb2-otg", "fsl-ehci", "fsl-usb2-udc", },
+		.op_mode = FSL_USB2_DR_OTG,
+	},
+	{
+		.dr_mode = "peripheral",
+		.drivers = { "fsl-usb2-udc", NULL, NULL, },
+		.op_mode = FSL_USB2_DR_DEVICE,
+	},
+};
+
+struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np)
+{
+	const unsigned char *prop;
+	int i;
+
+	prop = of_get_property(np, "dr_mode", NULL);
+	if (prop) {
+		for (i = 0; i < ARRAY_SIZE(dr_mode_data); i++) {
+			if (!strcmp(prop, dr_mode_data[i].dr_mode))
+				return &dr_mode_data[i];
+		}
+	}
+	pr_warn("%s: Invalid 'dr_mode' property, fallback to host mode\n",
+		np->full_name);
+	return &dr_mode_data[0]; /* mode not specified, use host */
+}
+
+static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type)
+{
+	if (!phy_type)
+		return FSL_USB2_PHY_NONE;
+	if (!strcasecmp(phy_type, "ulpi"))
+		return FSL_USB2_PHY_ULPI;
+	if (!strcasecmp(phy_type, "utmi"))
+		return FSL_USB2_PHY_UTMI;
+	if (!strcasecmp(phy_type, "utmi_wide"))
+		return FSL_USB2_PHY_UTMI_WIDE;
+	if (!strcasecmp(phy_type, "serial"))
+		return FSL_USB2_PHY_SERIAL;
+
+	return FSL_USB2_PHY_NONE;
+}
+
+struct platform_device * __devinit fsl_usb2_device_register(
+					struct platform_device *ofdev,
+					struct fsl_usb2_platform_data *pdata,
+					const char *name, int id)
+{
+	struct platform_device *pdev;
+	const struct resource *res = ofdev->resource;
+	unsigned int num = ofdev->num_resources;
+	int retval;
+
+	pdev = platform_device_alloc(name, id);
+	if (!pdev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	pdev->dev.parent = &ofdev->dev;
+
+	pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
+	pdev->dev.dma_mask = &pdev->archdata.dma_mask;
+	*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
+
+	retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+	if (retval)
+		goto error;
+
+	if (num) {
+		retval = platform_device_add_resources(pdev, res, num);
+		if (retval)
+			goto error;
+	}
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto error;
+
+	return pdev;
+
+error:
+	platform_device_put(pdev);
+	return ERR_PTR(retval);
+}
+
+static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev,
+					   const struct of_device_id *match)
+{
+	struct device_node *np = ofdev->dev.of_node;
+	struct platform_device *usb_dev;
+	struct fsl_usb2_platform_data data, *pdata;
+	struct fsl_usb2_dev_data *dev_data;
+	const unsigned char *prop;
+	static unsigned int idx;
+	int i;
+
+	if (!of_device_is_available(np))
+		return -ENODEV;
+
+	pdata = match->data;
+	if (!pdata) {
+		memset(&data, 0, sizeof(data));
+		pdata = &data;
+	}
+
+	dev_data = get_dr_mode_data(np);
+
+	if (of_device_is_compatible(np, "fsl-usb2-mph")) {
+		if (of_get_property(np, "port0", NULL))
+			pdata->port_enables |= FSL_USB2_PORT0_ENABLED;
+
+		if (of_get_property(np, "port1", NULL))
+			pdata->port_enables |= FSL_USB2_PORT1_ENABLED;
+
+		pdata->operating_mode = FSL_USB2_MPH_HOST;
+	} else {
+		/* setup mode selected in the device tree */
+		pdata->operating_mode = dev_data->op_mode;
+	}
+
+	prop = of_get_property(np, "phy_type", NULL);
+	pdata->phy_mode = determine_usb_phy(prop);
+
+	for (i = 0; i < ARRAY_SIZE(dev_data->drivers); i++) {
+		if (!dev_data->drivers[i])
+			continue;
+		usb_dev = fsl_usb2_device_register(ofdev, pdata,
+					dev_data->drivers[i], idx);
+		if (IS_ERR(usb_dev)) {
+			dev_err(&ofdev->dev, "Can't register usb device\n");
+			return PTR_ERR(usb_dev);
+		}
+	}
+	idx++;
+	return 0;
+}
+
+static int __devexit __unregister_subdev(struct device *dev, void *d)
+{
+	platform_device_unregister(to_platform_device(dev));
+	return 0;
+}
+
+static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev)
+{
+	device_for_each_child(&ofdev->dev, NULL, __unregister_subdev);
+	return 0;
+}
+
+static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
+	{ .compatible = "fsl-usb2-mph", },
+	{ .compatible = "fsl-usb2-dr", },
+	{},
+};
+
+static struct of_platform_driver fsl_usb2_mph_dr_driver = {
+	.driver = {
+		.name = "fsl-usb2-mph-dr",
+		.owner = THIS_MODULE,
+		.of_match_table = fsl_usb2_mph_dr_of_match,
+	},
+	.probe	= fsl_usb2_mph_dr_of_probe,
+	.remove	= __devexit_p(fsl_usb2_mph_dr_of_remove),
+};
+
+static int __init fsl_usb2_mph_dr_init(void)
+{
+	return of_register_platform_driver(&fsl_usb2_mph_dr_driver);
+}
+module_init(fsl_usb2_mph_dr_init);
+
+static void __exit fsl_usb2_mph_dr_exit(void)
+{
+	of_unregister_platform_driver(&fsl_usb2_mph_dr_driver);
+}
+module_exit(fsl_usb2_mph_dr_exit);
+
+MODULE_DESCRIPTION("FSL MPH DR OF devices driver");
+MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
+MODULE_LICENSE("GPL");
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH v2 1/3] powerpc/fsl_soc.c: remove FSL USB platform code
From: Anatolij Gustschin @ 2010-09-28  9:36 UTC (permalink / raw)
  To: linux-usb
  Cc: David Brownell, Wolfgang Denk, Detlev Zundel, Greg Kroah-Hartman,
	linuxppc-dev, Anatolij Gustschin
In-Reply-To: <1285666594-21150-1-git-send-email-agust@denx.de>

This removed code will be replaced by simple of_platform
driver for creation of FSL USB platform devices which is
added by next patch of the series.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
---
 arch/powerpc/sysdev/fsl_soc.c |  163 -----------------------------------------
 1 files changed, 0 insertions(+), 163 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index b91f7ac..49a51f1 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -209,169 +209,6 @@ static int __init of_add_fixed_phys(void)
 arch_initcall(of_add_fixed_phys);
 #endif /* CONFIG_FIXED_PHY */
 
-static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
-{
-	if (!phy_type)
-		return FSL_USB2_PHY_NONE;
-	if (!strcasecmp(phy_type, "ulpi"))
-		return FSL_USB2_PHY_ULPI;
-	if (!strcasecmp(phy_type, "utmi"))
-		return FSL_USB2_PHY_UTMI;
-	if (!strcasecmp(phy_type, "utmi_wide"))
-		return FSL_USB2_PHY_UTMI_WIDE;
-	if (!strcasecmp(phy_type, "serial"))
-		return FSL_USB2_PHY_SERIAL;
-
-	return FSL_USB2_PHY_NONE;
-}
-
-static int __init fsl_usb_of_init(void)
-{
-	struct device_node *np;
-	unsigned int i = 0;
-	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
-		*usb_dev_dr_client = NULL;
-	int ret;
-
-	for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
-		struct resource r[2];
-		struct fsl_usb2_platform_data usb_data;
-		const unsigned char *prop = NULL;
-
-		memset(&r, 0, sizeof(r));
-		memset(&usb_data, 0, sizeof(usb_data));
-
-		ret = of_address_to_resource(np, 0, &r[0]);
-		if (ret)
-			goto err;
-
-		of_irq_to_resource(np, 0, &r[1]);
-
-		usb_dev_mph =
-		    platform_device_register_simple("fsl-ehci", i, r, 2);
-		if (IS_ERR(usb_dev_mph)) {
-			ret = PTR_ERR(usb_dev_mph);
-			goto err;
-		}
-
-		usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
-
-		usb_data.operating_mode = FSL_USB2_MPH_HOST;
-
-		prop = of_get_property(np, "port0", NULL);
-		if (prop)
-			usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
-
-		prop = of_get_property(np, "port1", NULL);
-		if (prop)
-			usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
-
-		prop = of_get_property(np, "phy_type", NULL);
-		usb_data.phy_mode = determine_usb_phy(prop);
-
-		ret =
-		    platform_device_add_data(usb_dev_mph, &usb_data,
-					     sizeof(struct
-						    fsl_usb2_platform_data));
-		if (ret)
-			goto unreg_mph;
-		i++;
-	}
-
-	for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
-		struct resource r[2];
-		struct fsl_usb2_platform_data usb_data;
-		const unsigned char *prop = NULL;
-
-		if (!of_device_is_available(np))
-			continue;
-
-		memset(&r, 0, sizeof(r));
-		memset(&usb_data, 0, sizeof(usb_data));
-
-		ret = of_address_to_resource(np, 0, &r[0]);
-		if (ret)
-			goto unreg_mph;
-
-		of_irq_to_resource(np, 0, &r[1]);
-
-		prop = of_get_property(np, "dr_mode", NULL);
-
-		if (!prop || !strcmp(prop, "host")) {
-			usb_data.operating_mode = FSL_USB2_DR_HOST;
-			usb_dev_dr_host = platform_device_register_simple(
-					"fsl-ehci", i, r, 2);
-			if (IS_ERR(usb_dev_dr_host)) {
-				ret = PTR_ERR(usb_dev_dr_host);
-				goto err;
-			}
-		} else if (prop && !strcmp(prop, "peripheral")) {
-			usb_data.operating_mode = FSL_USB2_DR_DEVICE;
-			usb_dev_dr_client = platform_device_register_simple(
-					"fsl-usb2-udc", i, r, 2);
-			if (IS_ERR(usb_dev_dr_client)) {
-				ret = PTR_ERR(usb_dev_dr_client);
-				goto err;
-			}
-		} else if (prop && !strcmp(prop, "otg")) {
-			usb_data.operating_mode = FSL_USB2_DR_OTG;
-			usb_dev_dr_host = platform_device_register_simple(
-					"fsl-ehci", i, r, 2);
-			if (IS_ERR(usb_dev_dr_host)) {
-				ret = PTR_ERR(usb_dev_dr_host);
-				goto err;
-			}
-			usb_dev_dr_client = platform_device_register_simple(
-					"fsl-usb2-udc", i, r, 2);
-			if (IS_ERR(usb_dev_dr_client)) {
-				ret = PTR_ERR(usb_dev_dr_client);
-				goto err;
-			}
-		} else {
-			ret = -EINVAL;
-			goto err;
-		}
-
-		prop = of_get_property(np, "phy_type", NULL);
-		usb_data.phy_mode = determine_usb_phy(prop);
-
-		if (usb_dev_dr_host) {
-			usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
-			usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
-				dev.coherent_dma_mask;
-			if ((ret = platform_device_add_data(usb_dev_dr_host,
-						&usb_data, sizeof(struct
-						fsl_usb2_platform_data))))
-				goto unreg_dr;
-		}
-		if (usb_dev_dr_client) {
-			usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
-			usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
-				dev.coherent_dma_mask;
-			if ((ret = platform_device_add_data(usb_dev_dr_client,
-						&usb_data, sizeof(struct
-						fsl_usb2_platform_data))))
-				goto unreg_dr;
-		}
-		i++;
-	}
-	return 0;
-
-unreg_dr:
-	if (usb_dev_dr_host)
-		platform_device_unregister(usb_dev_dr_host);
-	if (usb_dev_dr_client)
-		platform_device_unregister(usb_dev_dr_client);
-unreg_mph:
-	if (usb_dev_mph)
-		platform_device_unregister(usb_dev_mph);
-err:
-	return ret;
-}
-
-arch_initcall(fsl_usb_of_init);
-
 #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
 static __be32 __iomem *rstcr;
 
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH v2 0/3] Add USB Host support for MPC5121 SoC
From: Anatolij Gustschin @ 2010-09-28  9:36 UTC (permalink / raw)
  To: linux-usb
  Cc: David Brownell, Wolfgang Denk, Detlev Zundel, Greg Kroah-Hartman,
	linuxppc-dev, Anatolij Gustschin

This is version 2 of patches to add MPC512x USB support in
mainline kernel. USB OTG support is not included in this
patch series, it will be submitted later.

The patches have been rebased on current linux-next tree
and reworked to address comments from Grant.

Anatolij Gustschin (3):
  powerpc/fsl_soc.c: remove FSL USB platform code
  USB: add of_platform glue driver for FSL USB DR controller
  USB: add USB EHCI support for MPC5121 SoC

 Documentation/powerpc/dts-bindings/fsl/usb.txt |   22 ++
 arch/powerpc/sysdev/fsl_soc.c                  |  163 -------------
 drivers/usb/Kconfig                            |    1 +
 drivers/usb/gadget/Kconfig                     |    1 +
 drivers/usb/host/Kconfig                       |   10 +-
 drivers/usb/host/Makefile                      |    1 +
 drivers/usb/host/ehci-fsl.c                    |   99 ++++++---
 drivers/usb/host/ehci-fsl.h                    |   13 +-
 drivers/usb/host/ehci-mem.c                    |    2 +-
 drivers/usb/host/fsl-mph-dr-of.c               |  302 ++++++++++++++++++++++++
 include/linux/fsl_devices.h                    |   15 ++
 11 files changed, 434 insertions(+), 195 deletions(-)
 create mode 100644 drivers/usb/host/fsl-mph-dr-of.c

^ permalink raw reply

* Re: [PATCH 6/8] v2 Update node sysfs code
From: Robin Holt @ 2010-09-28  9:29 UTC (permalink / raw)
  To: Nathan Fontenot
  Cc: linuxppc-dev, Greg KH, linux-kernel, Dave Hansen, linux-mm,
	KAMEZAWA Hiroyuki
In-Reply-To: <4CA0F00D.9000702@austin.ibm.com>

This patch may work, but it appears it is lacking in, at least the
link_mem_sections() function.  Assuming you have a memory block covering
2GB and a section size of 128MB (some values we are toying with for
large SGI machines), you end up calling register_mem_sect_under_node()
16 times which then takes the same steps.

I think you also need:

Index: linux-2.6.32/drivers/base/node.c
===================================================================
--- linux-2.6.32.orig/drivers/base/node.c	2010-09-28 04:18:53.848448349 -0500
+++ linux-2.6.32/drivers/base/node.c	2010-09-28 04:21:35.169446261 -0500
@@ -342,6 +342,7 @@
 		if (!err)
 			err = ret;
 
+		pfn = section_nr_to_pfn(mem_blk->end_phys_index);
 		/* discard ref obtained in find_memory_block() */
 		kobject_put(&mem_blk->sysdev.kobj);
 	}

Also, I don't think I much care for the weirdness that occurs if a
memory block spans two nodes.  I have not thought through how possible
(or likely) this is, but the code certainly permits it.  If that were
the case, how would we know which sections need to be taken offline, etc?
I wonder how much this will muddy up the information available in sysfs.

Thanks,
Robin

On Mon, Sep 27, 2010 at 02:27:09PM -0500, Nathan Fontenot wrote:
> Update the node sysfs code to be aware of the new capability for a memory
> block to contain multiple memory sections.  This requires an additional
> parameter to unregister_mem_sect_under_nodes so that we know which memory
> section of the memory block to unregister.
> 
> Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
> 
> ---
>  drivers/base/memory.c |    2 +-
>  drivers/base/node.c   |   12 ++++++++----
>  include/linux/node.h  |    6 ++++--
>  3 files changed, 13 insertions(+), 7 deletions(-)
> 
> Index: linux-next/drivers/base/node.c
> ===================================================================
> --- linux-next.orig/drivers/base/node.c	2010-09-27 13:49:36.000000000 -0500
> +++ linux-next/drivers/base/node.c	2010-09-27 13:50:43.000000000 -0500
> @@ -346,8 +346,10 @@
>  		return -EFAULT;
>  	if (!node_online(nid))
>  		return 0;
> -	sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
> -	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
> +
> +	sect_start_pfn = section_nr_to_pfn(mem_blk->start_phys_index);
> +	sect_end_pfn = section_nr_to_pfn(mem_blk->end_phys_index);
> +	sect_end_pfn += PAGES_PER_SECTION - 1;
>  	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
>  		int page_nid;
>  
> @@ -371,7 +373,8 @@
>  }
>  
>  /* unregister memory section under all nodes that it spans */
> -int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
> +int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
> +				    unsigned long phys_index)
>  {
>  	NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL);
>  	unsigned long pfn, sect_start_pfn, sect_end_pfn;
> @@ -383,7 +386,8 @@
>  	if (!unlinked_nodes)
>  		return -ENOMEM;
>  	nodes_clear(*unlinked_nodes);
> -	sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
> +
> +	sect_start_pfn = section_nr_to_pfn(phys_index);
>  	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
>  	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
>  		int nid;
> Index: linux-next/drivers/base/memory.c
> ===================================================================
> --- linux-next.orig/drivers/base/memory.c	2010-09-27 13:50:38.000000000 -0500
> +++ linux-next/drivers/base/memory.c	2010-09-27 13:50:43.000000000 -0500
> @@ -587,9 +587,9 @@
>  
>  	mutex_lock(&mem_sysfs_mutex);
>  	mem = find_memory_block(section);
> +	unregister_mem_sect_under_nodes(mem, __section_nr(section));
>  
>  	if (atomic_dec_and_test(&mem->section_count)) {
> -		unregister_mem_sect_under_nodes(mem);
>  		mem_remove_simple_file(mem, phys_index);
>  		mem_remove_simple_file(mem, end_phys_index);
>  		mem_remove_simple_file(mem, state);
> Index: linux-next/include/linux/node.h
> ===================================================================
> --- linux-next.orig/include/linux/node.h	2010-09-27 13:49:36.000000000 -0500
> +++ linux-next/include/linux/node.h	2010-09-27 13:50:43.000000000 -0500
> @@ -44,7 +44,8 @@
>  extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid);
>  extern int register_mem_sect_under_node(struct memory_block *mem_blk,
>  						int nid);
> -extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk);
> +extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
> +					   unsigned long phys_index);
>  
>  #ifdef CONFIG_HUGETLBFS
>  extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
> @@ -72,7 +73,8 @@
>  {
>  	return 0;
>  }
> -static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
> +static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
> +						  unsigned long phys_index)
>  {
>  	return 0;
>  }
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH RFCv2 1/2] dmaengine: add support for scatterlist to scatterlist transfers
From: Per Förlin @ 2010-09-28  7:13 UTC (permalink / raw)
  To: Ira W. Snyder
  Cc: Linus Walleij, Dan Williams, linuxppc-dev@lists.ozlabs.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <20100927172356.GA805@ovro.caltech.edu>

> On Mon, Sep 27, 2010 at 05:23:34PM +0200, Linus Walleij wrote:
>> 2010/9/25 Ira W. Snyder <iws@ovro.caltech.edu>:
>>
>>> This adds support for scatterlist to scatterlist DMA transfers.
>>
>> This is a good idea, we have a local function to do this in DMA40 already,
>> stedma40_memcpy_sg().
>>
> 
> I think that having two devices that want to implement this
> functionality as part of the DMAEngine API is a good argument for making
> it available as part of the core API. I think it would be good to add
> this to struct dma_device, and add a capability (DMA_SG?) for it as
> well.
> 
> I have looked at the stedma40_memcpy_sg() function, and I think we would
> want to extend it slightly for the generic API. Is there any good reason
> to prohibit scatterlists with different numbers of elements?
No

/Per

^ permalink raw reply

* Re: [PATCH v6 0/8] ptp: IEEE 1588 hardware clock support
From: Richard Cochran @ 2010-09-28  6:47 UTC (permalink / raw)
  To: Alan Cox
  Cc: John Stultz, Rodolfo Giometti, Arnd Bergmann, Peter Zijlstra,
	linux-api, devicetree-discuss, linux-kernel, Thomas Gleixner,
	netdev, Christoph Lameter, linuxppc-dev, David Miller,
	linux-arm-kernel, Krzysztof Halasa
In-Reply-To: <20100927180558.52817d5f@lxorguk.ukuu.org.uk>

On Mon, Sep 27, 2010 at 06:05:58PM +0100, Alan Cox wrote:
> On Mon, 27 Sep 2010 10:56:09 -0500 (CDT)
> Christoph Lameter <cl@linux.com> wrote:
> 
> > 
> > On Fri, 24 Sep 2010, Alan Cox wrote:
> > 
> > > Whether you add new syscalls or do the fd passing using flags and hide
> > > the ugly bits in glibc is another question.
> > 
> > Use device specific ioctls instead of syscalls?
> 
> Some of the ioctls are probably not device specific, the job of the OS in
> part is to present a unified interface. We already have a mess of HPET
> and RTC driver ioctls.

Yes, and the whole point of introducing a PTP hardare clock API was to
avoid each new clock driver introducing yet another ioctl interface.

I had proposed a standard ioctl interface for PTP hardware clocks, but
that interface was rightly criticized for duplicating the posix clock
API. It does not make sense to have multiple interfaces with the exact
same functionality.

It is impossible to support every last feature of every possible
hardware clock with a generic interface, so there will always need to
be special ioctls for such features.

However, some clock functions *are* completely generic and apply to
every clock:

- set time
- get time
- adjust the frequency by N ppb
- shift the time by a given offset

The first two are provided by the posix clock interface, the third by
the NTP adjtimex call, which also can support (by a single mode
extension) the last item.

Richard

^ permalink raw reply

* Re: [PATCH v6 0/8] ptp: IEEE 1588 hardware clock support
From: Richard Cochran @ 2010-09-28  6:34 UTC (permalink / raw)
  To: M. Warner Losh
  Cc: peterz, johnstul, devicetree-discuss, linuxppc-dev, linux-kernel,
	netdev, tglx, linux-api, cl, giometti, davem, linux-arm-kernel,
	khc
In-Reply-To: <20100927.101423.702773873740300798.imp@bsdimp.com>

On Mon, Sep 27, 2010 at 10:14:23AM -0600, M. Warner Losh wrote:
> 
> This is a common error that I've seen repeated in this thread.  The
> only reason that it has historically been important is because when
> you are doing timestamping in software based on an interrupt, that
> stuff does matter.

Yes, thanks for your helpful explanation.

To further illustrate how small the effect of running the servo in
user space is, consider the following.

It is true that delays and jitter in the time to process the received
packet negatively affect the clock servo loop. However, the effect in
our case will be quite small.

John Eidson's book [1] presents a rigorous servo model that includes
an analysis of the delay from the time the samples (timestamps) are
taken until the corrective action is performed by the PTP software.

For PTP, the sample time is at the sender (the remote host, the master
clock). The master sends *two* packets, where the second one (the so
called follow-up packet) contains the hardware time stamp of the first
one. So, the computational delay includes the time spent by the sender
in its PTP stack preparing the second packet, the time the packet
spends in transit, and the time in the receiver's PTP stack and servo.

According to Eidson's analysis, a delay of up to 10 milliseconds would
be acceptable, even with a sample rate of 10 Hz. Therefore, saving a
few dozen microseconds by placing the servo (and PTP stack) into the
kernel is not worth the effort.

Richard


[1] title =     {Measurement, control, and communication using IEEE 1588},
    author =    {J. C. Eidson},
    year =      2006,
    publisher = {Springer-Verlag},

^ permalink raw reply

* [PATCH 2/3 RESEND] powerpc: remove cast from void*
From: matt mooney @ 2010-09-28  2:04 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: kernel-janitors, Paul Mackerras, linuxppc-dev
In-Reply-To: <cover.1285638395.git.mfm@muteddisk.com>

Unnecessary cast from void* in assignment.

Signed-off-by: matt mooney <mfm@muteddisk.com>
---
 arch/powerpc/platforms/pseries/hvCall_inst.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index e19ff02..f106662 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -55,7 +55,7 @@ static void hc_stop(struct seq_file *m, void *p)
 static int hc_show(struct seq_file *m, void *p)
 {
 	unsigned long h_num = (unsigned long)p;
-	struct hcall_stats *hs = (struct hcall_stats *)m->private;
+	struct hcall_stats *hs = m->private;
 
 	if (hs[h_num].num_calls) {
 		if (cpu_has_feature(CPU_FTR_PURR))
-- 
1.7.2.1

^ permalink raw reply related

* Re: Oops in trace_hardirqs_on (powerpc)
From: Steven Rostedt @ 2010-09-28  1:58 UTC (permalink / raw)
  To: Jörg Sommer
  Cc: Frederic Weisbecker, Ingo Molnar, linux-kernel, linuxppc-dev
In-Reply-To: <20100927125037.GA4497@alea.gnuu.de>

On Mon, 2010-09-27 at 14:50 +0200, Jörg Sommer wrote:
> Hello Steven,
> 
> Steven Rostedt hat am Wed 22. Sep, 15:44 (-0400) geschrieben:
> > Sorry for the late reply, but I was on vacation when you sent this, and
> > I missed it while going through email.
> > 
> > Do you still have this issue?
> 
> No. I've rebuild my kernel without TRACE_IRQFLAGS and the problem
> vanished, as expected. The problem is, that in some cases the stack is
> only two frames deep, which causes the macro CALLER_ADDR1 makes an
> invalid access. Someone told me, there a workaround for the problem on
> i386, too.
> 
> % sed -n 2p arch/x86/lib/thunk_32.S
>  * Trampoline to trace irqs off. (otherwise CALLER_ADDR1 might crash)

Yes, I remember that problem. When I get back from Tokyo, I'll tried to
remember to fix it.

Thanks!

-- Steve

^ 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