LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/3] USB: add of_platform glue driver for FSL USB DR controller
From: Anatolij Gustschin @ 2010-07-28 11:58 UTC (permalink / raw)
  To: Grant Likely
  Cc: Greg Kroah-Hartman, Wolfgang Denk, Detlev Zundel, linux-usb,
	linuxppc-dev, David Brownell
In-Reply-To: <AANLkTinSeFWM4bQK+o8nwStd6C-OcxMagC7TjwCBNn1v@mail.gmail.com>

Hi Grant,

On Wed, 28 Jul 2010 02:16:08 -0600
Grant Likely <grant.likely@secretlab.ca> wrote:

> On Thu, Jul 22, 2010 at 10:25 AM, Anatolij Gustschin <agust@denx.de> wrot=
e:
> > 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>
>=20
> Hi Anatolij,
>=20
> Looks pretty good, but some comments below.

Thanks for review and comments! Greg already merged this series and
therefore I'll submit an incremental cleanup patch to address
outstanding issues. My reply is below.

...
> > --- a/drivers/usb/host/Kconfig
> > +++ b/drivers/usb/host/Kconfig
> > @@ -112,10 +112,15 @@ config XPS_USB_HCD_XILINX
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0support both hig=
h speed and full speed devices, or high speed
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0devices only.
> >
> > +config USB_FSL_MPH_DR_OF
> > + =C2=A0 =C2=A0 =C2=A0 bool
> > + =C2=A0 =C2=A0 =C2=A0 depends on PPC_OF
>=20
> Drop the depends.  This is selected by USB_EHCI_FSL and
> USB_GADGET_FSL_USB2, which are already PPC only.

Okay, will remove it.

...
> > +struct fsl_usb2_dev_data dr_mode_data[] __devinitdata =3D {
> > + =C2=A0 =C2=A0 =C2=A0 {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "host",
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 { "fsl-ehci", NULL, =
NULL, },
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FSL_USB2_DR_HOST,
> > + =C2=A0 =C2=A0 =C2=A0 },
> > + =C2=A0 =C2=A0 =C2=A0 {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "otg",
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 { "fsl-ehci", "fsl-u=
sb2-udc", "fsl-usb2-otg", },
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FSL_USB2_DR_OTG,
> > + =C2=A0 =C2=A0 =C2=A0 },
> > + =C2=A0 =C2=A0 =C2=A0 {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 "periferal",
>=20
> spelling.  "peripheral"

Right, thanks for catching! Will fix it.

>=20
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 { "fsl-usb2-udc", NU=
LL, NULL, },
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FSL_USB2_DR_DEVICE,
> > + =C2=A0 =C2=A0 =C2=A0 },
> > +};
>=20
> Program defensively.  Use the following form:
> + =C2=A0 =C2=A0 =C2=A0 {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 .dr_mode =3D "host",
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 .drivers =3D { "fsl-eh=
ci", NULL, NULL, },
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 .op_mode =3D FSL_USB2_=
DR_HOST,
> + =C2=A0 =C2=A0 =C2=A0 },

I'll change it too as suggested.

...
> > +struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_no=
de *np)
> > +{
> > + =C2=A0 =C2=A0 =C2=A0 const unsigned char *prop;
> > + =C2=A0 =C2=A0 =C2=A0 int i;
> > +
> > + =C2=A0 =C2=A0 =C2=A0 prop =3D of_get_property(np, "dr_mode", NULL);
> > + =C2=A0 =C2=A0 =C2=A0 if (prop) {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 for (i =3D 0; i < AR=
RAY_SIZE(dr_mode_data); i++) {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 if (!strcmp(prop, dr_mode_data[i].dr_mode))
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return &dr_mode_data[i];
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
>=20
> Print a warning if you get through the loop, but don't match anything.
>  That means that dr_mode has a bad value.

I'll add a warning here.

...
> > +struct platform_device * __devinit
> > +fsl_usb2_device_register(struct of_device *ofdev,
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0struct fsl_usb2_platform_data *pdata,
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0const char *name, int id)
>=20
> In general, it is better to have the function name on the same line as
> the return arguements so that grep shows the relevant info.  Move the
> arguments to subsequent lines.

It will be fixed in a clean-up patch.

...
> > +static int __devinit fsl_usb2_mph_dr_of_probe(struct of_device *ofdev,
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0const struct of_device_id *match)
> > +{
> > + =C2=A0 =C2=A0 =C2=A0 struct device_node *np =3D ofdev->dev.of_node;
> > + =C2=A0 =C2=A0 =C2=A0 struct platform_device *usb_dev;
> > + =C2=A0 =C2=A0 =C2=A0 struct fsl_usb2_platform_data data, *pdata;
> > + =C2=A0 =C2=A0 =C2=A0 struct fsl_usb2_dev_data *dev_data;
> > + =C2=A0 =C2=A0 =C2=A0 const unsigned char *prop;
> > + =C2=A0 =C2=A0 =C2=A0 static unsigned int idx;
> > + =C2=A0 =C2=A0 =C2=A0 int i;
> > +
> > + =C2=A0 =C2=A0 =C2=A0 if (!of_device_is_available(np))
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return -ENODEV;
>=20
> What is this for?

Anton already answered this question better than I could do.

> > +
> > + =C2=A0 =C2=A0 =C2=A0 pdata =3D match->data;
> > + =C2=A0 =C2=A0 =C2=A0 if (!pdata) {
>=20
> The match table doesn't have any data, so this is a no-op.

The next patch [PATCH 3/3] of the series adds the data to the
match table.

...
> > + =C2=A0 =C2=A0 =C2=A0 if (of_device_is_compatible(np, "fsl-usb2-mph"))=
 {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 prop =3D of_get_prop=
erty(np, "port0", NULL);
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (prop)
>=20
> if (of_get_property())
>=20
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
 =C2=A0 pdata->port_enables |=3D FSL_USB2_PORT0_ENABLED;
> > +
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 prop =3D of_get_prop=
erty(np, "port1", NULL);
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (prop)
>=20
> Ditto

Okay, I'll clean this up.

...
> > +static struct of_platform_driver fsl_usb2_mph_dr_driver =3D {
> > + =C2=A0 =C2=A0 =C2=A0 .driver =3D {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 .name =3D "fsl-usb2-=
mph-dr",
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 .owner =3D THIS_MODU=
LE,
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 .of_match_table =3D =
fsl_usb2_mph_dr_of_match,
> > + =C2=A0 =C2=A0 =C2=A0 },
> > + =C2=A0 =C2=A0 =C2=A0 .probe =C2=A0=3D fsl_usb2_mph_dr_of_probe,
> > +};
>=20
> No remove hook?

Since the purpose of the driver is only creation of platform devices
according to the selected dual role controller mode described in
the device tree, I do not see much sense of making the driver a module
and provide a remove hook for destruction of created devices.

...
> > +static int __init fsl_usb2_mph_dr_init(void)
> > +{
> > + =C2=A0 =C2=A0 =C2=A0 return of_register_platform_driver(&fsl_usb2_mph=
_dr_driver);
> > +}
> > +fs_initcall(fsl_usb2_mph_dr_init);
>=20
> Why fs_initcall?  Is module_init() not sufficient?

No. Using module_init() here results in initializing the driver after
loading FLS USB OTG and EHCI-FSL drivers and reverted probing: probe()
in EHCI-FSL driver is called before probe() in OTG driver and doesn't
find OTG transceiver resource which is set and exported by probe() in
OTG driver. This breaks both USB host and device controller support
if dual role controller is configured to operate in OTG mode.

Thanks,
Anatolij

^ permalink raw reply

* [GIT/PATCH 0/4] Do not use IRQF_TIMER for non timer interrupts
From: Ian Campbell @ 2010-07-28 10:54 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Jeremy Fitzhardinge, xen-devel, devicetree-discuss,
	Dmitry Torokhov, linux-kernel, linuxppc-dev, Paul Mackerras,
	linux-input

Hi Thomas,

A small number of users of IRQF_TIMER are using it for the implied no
suspend behaviour on interrupts which are not timer interrupts.

Therefore the following series renames the IRQF_TIMER flag to
IRQF_NO_SUSPEND and updates the users which are not timer interrupts to
use the new name. IRQF_TIMER is retained as an alias for
IRQF_NO_SUSPEND.

The final patch in the series adds a new user the flag which disables
suspend of Xen IPI IRQs.

Ian.

The following changes since commit fc0f5ac8fe693d1b05f5a928cc48135d1c8b7f2e:
  Linus Torvalds (1):
        Merge branch 'for-linus' of git://git.kernel.org/.../ericvh/v9fs

are available in the git repository at:

  git://xenbits.xensource.com/people/ianc/linux-2.6.git for-irq/irqf-no-suspend

Ian Campbell (4):
      irq: rename IRQF_TIMER to IRQF_NO_SUSPEND
      ixp4xx-beeper: Use IRQF_NO_SUSPEND not IRQF_TIMER for non-timer interrupt
      powerpc: Use IRQF_NO_SUSPEND not IRQF_TIMER for non-timer interrupts
      xen: do not suspend IPI IRQs.

 arch/powerpc/platforms/powermac/low_i2c.c |    4 ++--
 drivers/input/misc/ixp4xx-beeper.c        |    2 +-
 drivers/macintosh/via-pmu.c               |    4 ++--
 drivers/xen/events.c                      |    1 +
 include/linux/interrupt.h                 |    8 ++++++--
 kernel/irq/manage.c                       |    2 +-
 6 files changed, 13 insertions(+), 8 deletions(-)

^ permalink raw reply

* [PATCH 1/4] irq: rename IRQF_TIMER to IRQF_NO_SUSPEND
From: Ian Campbell @ 2010-07-28 10:54 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jeremy Fitzhardinge, xen-devel, Ian Campbell, devicetree-discuss,
	Dmitry Torokhov, linuxppc-dev, Paul Mackerras, linux-input,
	Thomas Gleixner
In-Reply-To: <1280314445.24292.90.camel@zakaz.uk.xensource.com>

Continue to provide IRQF_TIMER as an alias to IRQF_NO_SUSPEND since I
think it is worth preserving the nice self-documenting name (where it
is used appropriately). It also avoid needing to patch all the many
users who are using the flag for an actual timer interrupt.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: xen-devel@lists.xensource.com
Cc: linux-input@vger.kernel.org
Cc: linuxppc-dev@ozlabs.org
Cc: devicetree-discuss@lists.ozlabs.org
---
 include/linux/interrupt.h |    8 ++++++--
 kernel/irq/manage.c       |    2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index c233113..b9bedd5 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -44,7 +44,7 @@
  * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
  * IRQF_SHARED - allow sharing the irq among several devices
  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
- * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
+ * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
  * IRQF_PERCPU - Interrupt is per cpu
  * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
  * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
@@ -53,17 +53,21 @@
  * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
  *                Used by threaded interrupts which need to keep the
  *                irq line disabled until the threaded handler has been run.
+ *
+ * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
  */
 #define IRQF_DISABLED		0x00000020
 #define IRQF_SAMPLE_RANDOM	0x00000040
 #define IRQF_SHARED		0x00000080
 #define IRQF_PROBE_SHARED	0x00000100
-#define IRQF_TIMER		0x00000200
+#define IRQF_NO_SUSPEND		0x00000200
 #define IRQF_PERCPU		0x00000400
 #define IRQF_NOBALANCING	0x00000800
 #define IRQF_IRQPOLL		0x00001000
 #define IRQF_ONESHOT		0x00002000
 
+#define IRQF_TIMER		(IRQF_NO_SUSPEND)
+
 /*
  * Bits used by threaded handlers:
  * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index e149748..c3003e9 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -216,7 +216,7 @@ static inline int setup_affinity(unsigned int irq, struct irq_desc *desc)
 void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
 {
 	if (suspend) {
-		if (!desc->action || (desc->action->flags & IRQF_TIMER))
+		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
 			return;
 		desc->status |= IRQ_SUSPENDED;
 	}
-- 
1.5.6.5

^ permalink raw reply related

* [PATCH 3/4] powerpc: Use IRQF_NO_SUSPEND not IRQF_TIMER for non-timer interrupts
From: Ian Campbell @ 2010-07-28 10:54 UTC (permalink / raw)
  To: linux-kernel
  Cc: Ian Campbell, devicetree-discuss, linuxppc-dev, Paul Mackerras,
	Thomas Gleixner
In-Reply-To: <1280314445.24292.90.camel@zakaz.uk.xensource.com>

kw_i2c_irq and via_pmu_interrupt are not timer interrupts and
therefore should not use IRQF_TIMER. Use the recently introduced
IRQF_NO_SUSPEND instead since that is the actual desired behaviour.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: linuxppc-dev@ozlabs.org
Cc: devicetree-discuss@lists.ozlabs.org
---
 arch/powerpc/platforms/powermac/low_i2c.c |    4 ++--
 drivers/macintosh/via-pmu.c               |    4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 06a137c..1554d29 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -542,11 +542,11 @@ static struct pmac_i2c_host_kw *__init kw_i2c_host_init(struct device_node *np)
 	/* Make sure IRQ is disabled */
 	kw_write_reg(reg_ier, 0);
 
-	/* Request chip interrupt. We set IRQF_TIMER because we don't
+	/* Request chip interrupt. We set IRQF_NO_SUSPEND because we don't
 	 * want that interrupt disabled between the 2 passes of driver
 	 * suspend or we'll have issues running the pfuncs
 	 */
-	if (request_irq(host->irq, kw_i2c_irq, IRQF_TIMER, "keywest i2c", host))
+	if (request_irq(host->irq, kw_i2c_irq, IRQF_NO_SUSPEND, "keywest i2c", host))
 		host->irq = NO_IRQ;
 
 	printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n",
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 3d4fc0f..5c6b5be 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -400,11 +400,11 @@ static int __init via_pmu_start(void)
 		printk(KERN_ERR "via-pmu: can't map interrupt\n");
 		return -ENODEV;
 	}
-	/* We set IRQF_TIMER because we don't want the interrupt to be disabled
+	/* We set IRQF_NO_SUSPEND because we don't want the interrupt to be disabled
 	 * between the 2 passes of driver suspend, we control our own disabling
 	 * for that one
 	 */
-	if (request_irq(irq, via_pmu_interrupt, IRQF_TIMER, "VIA-PMU", (void *)0)) {
+	if (request_irq(irq, via_pmu_interrupt, IRQF_NO_SUSPEND, "VIA-PMU", (void *)0)) {
 		printk(KERN_ERR "via-pmu: can't request irq %d\n", irq);
 		return -ENODEV;
 	}
-- 
1.5.6.5

^ permalink raw reply related

* RE: [PATCH 3/3] mmc: Add ESDHC weird register workaround
From: Zang Roy-R61911 @ 2010-07-28  9:43 UTC (permalink / raw)
  To: Anton Vorontsov; +Cc: linuxppc-dev, linux-mmc
In-Reply-To: <20100728080312.GA16994@oksana.dev.rtsoft.ru>

=20

> -----Original Message-----
> From: Anton Vorontsov [mailto:cbouatmailru@gmail.com]=20
> Sent: Wednesday, July 28, 2010 16:03 PM
> To: Zang Roy-R61911
> Cc: linux-mmc-approval@vger.kernel.org; linuxppc-dev@ozlabs.org
> Subject: Re: [PATCH 3/3] mmc: Add ESDHC weird register workaround
>=20
> On Wed, Jul 28, 2010 at 01:54:21PM +0800, Roy Zang wrote:
> > P4080 ESDHC controller induces weird register setting.
> > This patch adds the workaround to correct the weird=20
> register setting.
> >=20
> > Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> > ---
> >  drivers/mmc/host/sdhci-of-core.c |    5 +++++
> >  drivers/mmc/host/sdhci.c         |   13 +++++++++++++
> >  drivers/mmc/host/sdhci.h         |    2 ++
> >  3 files changed, 20 insertions(+), 0 deletions(-)
> >=20
> > diff --git a/drivers/mmc/host/sdhci-of-core.c=20
> b/drivers/mmc/host/sdhci-of-core.c
> > index 0c30242..1b6945a 100644
> > --- a/drivers/mmc/host/sdhci-of-core.c
> > +++ b/drivers/mmc/host/sdhci-of-core.c
> > @@ -164,6 +164,11 @@ static int __devinit=20
> sdhci_of_probe(struct of_device *ofdev,
> >  	if (sdhci_of_wp_inverted(np))
> >  		host->quirks |=3D SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
> > =20
> > +	if (of_device_is_compatible(np, "fsl,p4080-esdhc")) {
> > +		host->quirks |=3D SDHCI_QUIRK_QORIQ_REG_WEIRD;
> > +		host->quirks &=3D ~SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
>=20
> You do not mention this change in the patch description, why?
This is not needed any more. Will be removed.
>=20
> > +	}
> > +
> >  	clk =3D of_get_property(np, "clock-frequency", &size);
> >  	if (clk && size =3D=3D sizeof(*clk) && *clk)
> >  		of_host->clock =3D *clk;
> > diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> > index 1424d08..b5b3627 100644
> > --- a/drivers/mmc/host/sdhci.c
> > +++ b/drivers/mmc/host/sdhci.c
> > @@ -788,6 +788,15 @@ static void sdhci_prepare_data(struct=20
> sdhci_host *host, struct mmc_data *data)
> >  		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
> >  	}
> > =20
> > +	/* The default value of DMAS bits of Protocol Control=20
> Register is not
> > +	 * correct. clear these two bits to use simple DMA */
> > +#define  ESDHCI_CTRL_DMAS_MASK		0xFFFFFCFF
> > +	if (host->quirks & SDHCI_QUIRK_QORIQ_REG_WEIRD) {
> > +		ctrl =3D sdhci_readl(host, SDHCI_HOST_CONTROL);
> > +		ctrl =3D ctrl & ESDHCI_CTRL_DMAS_MASK;
> > +		sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
> > +	}
>=20
> You should implement register quirks via SDHCI IO accessors.
What does you mean "SDHCI IO accessors?
It makes more sense to define something like:
SDHCI_QUIRK_QORIQ_PROCTL_WEIRD.
Any comment?

>=20
> See esdhc_writew() for example.
>=20
> >  	if (!(host->flags & SDHCI_REQ_USE_DMA)) {
> >  		int flags;
> > =20
> > @@ -1699,6 +1708,10 @@ int sdhci_add_host(struct sdhci_host *host)
> > =20
> >  	caps =3D sdhci_readl(host, SDHCI_CAPABILITIES);
> > =20
> > +	 /* Workaround for P4080 host controller capabilities */
> > +	if (host->quirks & SDHCI_QUIRK_QORIQ_REG_WEIRD)
> > +		caps &=3D ~(SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_330);
>=20
> Ditto. Make a quirk for cap register. Or implement
> SDHCI_QUIRK_NO_VDD_180 and SDHCI_QUIRK_NO_VDD_300 quirks
> instead.
Second proposal more makes sense to me.
Thanks.
Roy

^ permalink raw reply

* Problems using UART on MPC5200
From: Sven Batzer @ 2010-07-28  9:26 UTC (permalink / raw)
  To: linuxppc-dev

Hello,

I am using a PowerPC MPC5200 from Freescale (with STK5200-Board), ELDK 4.2
from DENX and the Kernel 2.6.34-rc5.

My Kernel is running fine. The console output is coming over the device
ttyPSC0.

In future I want to login over telnet. So I deactivated the Kerneloption
to output the console over the UART device.

Now I want to read and write to the RS232 interface from a program.
But when I try to open the device ttyPSC* I get the following error:
"unable to read portsettings : Inappropriate ioctl for device"

What does this mean ? How can I send and receive Data from/to the UART ?

Thanks for your help.

Sven

^ permalink raw reply

* [PATCH] powerpc: Replace hardcoded offset by BREAK_INSTR_SIZE
From: Michal Simek @ 2010-07-28  9:18 UTC (permalink / raw)
  Cc: linuxppc-dev, Michal Simek, Jason Wessel

kgdb_handle_breakpoint checks the first arch_kgdb_breakpoint
which is not known by gdb that's why is necessary jump over
it. The jump lenght is equal to BREAK_INSTR_SIZE that's
why is cleaner to use defined macro instead of hardcoded
non-described offset.

Signed-off-by: Michal Simek <monstr@monstr.eu>
CC: Jason Wessel <jason.wessel@windriver.com>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: linuxppc-dev@ozlabs.org
---
 arch/powerpc/kernel/kgdb.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index 82a7b22..7f61a3a 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -129,7 +129,7 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs)
 		return 0;
 
 	if (*(u32 *) (regs->nip) == *(u32 *) (&arch_kgdb_ops.gdb_bpt_instr))
-		regs->nip += 4;
+		regs->nip += BREAK_INSTR_SIZE;
 
 	return 1;
 }
-- 
1.5.5.6

^ permalink raw reply related

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

On Wed, Jul 28, 2010 at 02:16:08AM -0600, Grant Likely wrote:
[...]
> > +static int __devinit fsl_usb2_mph_dr_of_probe(struct of_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;
> 
> What is this for?

USB pins/clocks might be muxed away to other peripherals, like
eSDHC. In such cases firmware marks USB as unavailable (status
= "disabled").

If you try to access USB while it is disabled the SOC will hang.

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

^ permalink raw reply

* Re: [PATCH 3/3] USB: add USB EHCI support for MPC5121 SoC
From: Grant Likely @ 2010-07-28  8:22 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: Greg Kroah-Hartman, Wolfgang Denk, Detlev Zundel, linux-usb,
	linuxppc-dev, David Brownell
In-Reply-To: <1279815922-27198-4-git-send-email-agust@denx.de>

On Thu, Jul 22, 2010 at 10:25 AM, Anatolij Gustschin <agust@denx.de> wrote:
> 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>

On brief review, looks pretty good to me.

g.

> ---
> =A0Documentation/powerpc/dts-bindings/fsl/usb.txt | =A0 22 +++++
> =A0drivers/usb/Kconfig =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0| =A0 =A01 +
> =A0drivers/usb/host/Kconfig =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 |=
 =A0 =A06 +-
> =A0drivers/usb/host/ehci-fsl.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0107 +++++++++++++++++------
> =A0drivers/usb/host/ehci-fsl.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 19 ++++-
> =A0drivers/usb/host/ehci-mem.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 =A02 +-
> =A0drivers/usb/host/fsl-mph-dr-of.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 | =A0 89 =
++++++++++++++++++++
> =A0include/linux/fsl_devices.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| =
=A0 15 ++++
> =A08 files changed, 229 insertions(+), 32 deletions(-)
>
> diff --git a/Documentation/powerpc/dts-bindings/fsl/usb.txt b/Documentati=
on/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 :
> =A0Required properties :
> =A0- compatible : Should be "fsl-usb2-mph" for multi port host USB
> =A0 =A0controllers, or "fsl-usb2-dr" for dual role USB controllers
> + =A0 or "fsl,mpc5121-usb2-dr" for dual role USB controllers of MPC5121
> =A0- phy_type : For multi port host USB controllers, should be one of
> =A0 =A0"ulpi", or "serial". For dual role USB controllers, should be
> =A0 =A0one of "ulpi", "utmi", "utmi_wide", or "serial".
> @@ -33,6 +34,12 @@ Recommended properties :
> =A0- interrupt-parent : the phandle for the interrupt controller that
> =A0 =A0services interrupts for this device.
>
> +Optional properties :
> + - fsl,invert-drvvbus : boolean; for MPC5121 USB0 only. Indicates the
> + =A0 port power polarity of internal PHY signal DRVVBUS is inverted.
> + - fsl,invert-pwr-fault : boolean; for MPC5121 USB0 only. Indicates
> + =A0 the PWR_FAULT signal polarity is inverted.
> +
> =A0Example multi port host USB controller device node :
> =A0 =A0 =A0 =A0usb@22000 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0compatible =3D "fsl-usb2-mph";
> @@ -57,3 +64,18 @@ Example dual role USB controller device node :
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0dr_mode =3D "otg";
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0phy =3D "ulpi";
> =A0 =A0 =A0 =A0};
> +
> +Example dual role USB controller device node for MPC5121ADS:
> +
> + =A0 =A0 =A0 usb@4000 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,mpc5121-usb2-dr";
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg =3D <0x4000 0x1000>;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 #address-cells =3D <1>;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 #size-cells =3D <0>;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupt-parent =3D < &ipic >;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 interrupts =3D <44 0x8>;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dr_mode =3D "otg";
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 phy_type =3D "utmi_wide";
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 fsl,invert-drvvbus;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 fsl,invert-pwr-fault;
> + =A0 =A0 =A0 };
> diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
> index 6a58cb1..6e547b5 100644
> --- a/drivers/usb/Kconfig
> +++ b/drivers/usb/Kconfig
> @@ -58,6 +58,7 @@ config USB_ARCH_HAS_OHCI
> =A0config USB_ARCH_HAS_EHCI
> =A0 =A0 =A0 =A0boolean
> =A0 =A0 =A0 =A0default y if PPC_83xx
> + =A0 =A0 =A0 default y if PPC_MPC512x
> =A0 =A0 =A0 =A0default y if SOC_AU1200
> =A0 =A0 =A0 =A0default y if ARCH_IXP4XX
> =A0 =A0 =A0 =A0default y if ARCH_W90X900
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 6687523..90e50f0 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -93,12 +93,14 @@ config USB_EHCI_TT_NEWSCHED
>
> =A0config USB_EHCI_BIG_ENDIAN_MMIO
> =A0 =A0 =A0 =A0bool
> - =A0 =A0 =A0 depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX=
 || ARCH_IXP4XX || XPS_USB_HCD_XILINX)
> + =A0 =A0 =A0 depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX=
 || ARCH_IXP4XX || \
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 XPS=
_USB_HCD_XILINX || PPC_MPC512x)
> =A0 =A0 =A0 =A0default y
>
> =A0config USB_EHCI_BIG_ENDIAN_DESC
> =A0 =A0 =A0 =A0bool
> - =A0 =A0 =A0 depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_US=
B_HCD_XILINX)
> + =A0 =A0 =A0 depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_US=
B_HCD_XILINX || \
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 PPC=
_MPC512x)
> =A0 =A0 =A0 =A0default y
>
> =A0config XPS_USB_HCD_XILINX
> diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
> index a416421..ff50f5c 100644
> --- a/drivers/usb/host/ehci-fsl.c
> +++ b/drivers/usb/host/ehci-fsl.c
> @@ -116,13 +116,39 @@ static int usb_hcd_fsl_probe(const struct hc_driver=
 *driver,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto err3;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 /* Enable USB controller */
> - =A0 =A0 =A0 temp =3D in_be32(hcd->regs + 0x500);
> - =A0 =A0 =A0 out_be32(hcd->regs + 0x500, temp | 0x4);
> + =A0 =A0 =A0 pdata->regs =3D hcd->regs;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* do platform specific init: check the clock, grab/confi=
g pins, etc.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->init && pdata->init(pdev)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 retval =3D -ENODEV;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto err3;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Check if it is MPC5121 SoC, otherwise set pdata->have_=
sysif_regs
> + =A0 =A0 =A0 =A0* flag for 83xx or 8536 system interface registers.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->big_endian_mmio)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D in_be32(hcd->regs + FSL_SOC_USB_ID=
);
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D in_le32(hcd->regs + FSL_SOC_USB_ID=
);
> +
> + =A0 =A0 =A0 if ((temp & ID_MSK) !=3D (~((temp & NID_MSK) >> 8) & ID_MSK=
))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->have_sysif_regs =3D 1;
> +
> + =A0 =A0 =A0 /* Enable USB controller, 83xx or 8536 */
> + =A0 =A0 =A0 if (pdata->have_sysif_regs)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4=
);
>
> =A0 =A0 =A0 =A0/* Set to Host mode */
> - =A0 =A0 =A0 temp =3D in_le32(hcd->regs + 0x1a8);
> - =A0 =A0 =A0 out_le32(hcd->regs + 0x1a8, temp | 0x3);
> + =A0 =A0 =A0 if (pdata->big_endian_mmio) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 setbits32(hcd->regs + FSL_SOC_USB_USBMODE, =
USBMODE_CM_HOST);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clrsetbits_le32(hcd->regs + FSL_SOC_USB_USB=
MODE,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 USBMODE_CM_=
MASK, USBMODE_CM_HOST);
> + =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0retval =3D usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHAR=
ED);
> =A0 =A0 =A0 =A0if (retval !=3D 0)
> @@ -137,6 +163,8 @@ static int usb_hcd_fsl_probe(const struct hc_driver *=
driver,
> =A0 =A0 =A0 =A0usb_put_hcd(hcd);
> =A0 =A0 =A0 err1:
> =A0 =A0 =A0 =A0dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->=
dev), retval);
> + =A0 =A0 =A0 if (pdata->exit)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->exit(pdev);
> =A0 =A0 =A0 =A0return retval;
> =A0}
>
> @@ -154,17 +182,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver=
 *driver,
> =A0static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct platfo=
rm_device *pdev)
> =A0{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> =A0 =A0 =A0 =A0usb_remove_hcd(hcd);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* do platform specific un-initialization:
> + =A0 =A0 =A0 =A0* release iomux pins, disable clock, etc.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (pdata->exit)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->exit(pdev);
> =A0 =A0 =A0 =A0iounmap(hcd->regs);
> =A0 =A0 =A0 =A0release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
> =A0 =A0 =A0 =A0usb_put_hcd(hcd);
> =A0}
>
> -static void mpc83xx_setup_phy(struct ehci_hcd *ehci,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 enum fsl_usb2_p=
hy_modes phy_mode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 unsigned int po=
rt_offset)
> +static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0enum fsl_usb=
2_phy_modes phy_mode,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned int=
 port_offset)
> =A0{
> - =A0 =A0 =A0 u32 portsc =3D 0;
> + =A0 =A0 =A0 u32 portsc;
> +
> + =A0 =A0 =A0 portsc =3D ehci_readl(ehci, &ehci->regs->port_status[port_o=
ffset]);
> + =A0 =A0 =A0 portsc &=3D ~(PORT_PTS_MSK | PORT_PTS_PTW);
> +
> =A0 =A0 =A0 =A0switch (phy_mode) {
> =A0 =A0 =A0 =A0case FSL_USB2_PHY_ULPI:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0portsc |=3D PORT_PTS_ULPI;
> @@ -184,20 +225,21 @@ static void mpc83xx_setup_phy(struct ehci_hcd *ehci=
,
> =A0 =A0 =A0 =A0ehci_writel(ehci, portsc, &ehci->regs->port_status[port_of=
fset]);
> =A0}
>
> -static void mpc83xx_usb_setup(struct usb_hcd *hcd)
> +static void ehci_fsl_usb_setup(struct ehci_hcd *ehci)
> =A0{
> - =A0 =A0 =A0 struct ehci_hcd *ehci =3D hcd_to_ehci(hcd);
> + =A0 =A0 =A0 struct usb_hcd *hcd =3D ehci_to_hcd(ehci);
> =A0 =A0 =A0 =A0struct fsl_usb2_platform_data *pdata;
> =A0 =A0 =A0 =A0void __iomem *non_ehci =3D hcd->regs;
> =A0 =A0 =A0 =A0u32 temp;
>
> - =A0 =A0 =A0 pdata =3D
> - =A0 =A0 =A0 =A0 =A0 (struct fsl_usb2_platform_data *)hcd->self.controll=
er->
> - =A0 =A0 =A0 =A0 =A0 platform_data;
> + =A0 =A0 =A0 pdata =3D hcd->self.controller->platform_data;
> +
> =A0 =A0 =A0 =A0/* Enable PHY interface in the control reg. */
> - =A0 =A0 =A0 temp =3D in_be32(non_ehci + FSL_SOC_USB_CTRL);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b);
> + =A0 =A0 =A0 if (pdata->have_sysif_regs) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 temp =3D in_be32(non_ehci + FSL_SOC_USB_CTR=
L);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_CTRL, temp =
| 0x00000004);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0=
000001b);
> + =A0 =A0 =A0 }
>
> =A0#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
> =A0 =A0 =A0 =A0/*
> @@ -214,7 +256,7 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
>
> =A0 =A0 =A0 =A0if ((pdata->operating_mode =3D=3D FSL_USB2_DR_HOST) ||
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(pdata->operating_mode =3D=
=3D FSL_USB2_DR_OTG))
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pdata->phy_mode, 0)=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pdata->phy_mode, 0=
);
>
> =A0 =A0 =A0 =A0if (pdata->operating_mode =3D=3D FSL_USB2_MPH_HOST) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0unsigned int chip, rev, svr;
> @@ -228,27 +270,31 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ehci->has_fsl_port_bug =3D=
 1;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (pdata->port_enables & FSL_USB2_PORT0_E=
NABLED)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pda=
ta->phy_mode, 0);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pd=
ata->phy_mode, 0);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (pdata->port_enables & FSL_USB2_PORT1_E=
NABLED)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 mpc83xx_setup_phy(ehci, pda=
ta->phy_mode, 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ehci_fsl_setup_phy(ehci, pd=
ata->phy_mode, 1);
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0/* put controller in host mode. */
> - =A0 =A0 =A0 ehci_writel(ehci, 0x00000003, non_ehci + FSL_SOC_USB_USBMOD=
E);
> + =A0 =A0 =A0 temp =3D USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
> + =A0 =A0 =A0 ehci_writel(ehci, temp, non_ehci + FSL_SOC_USB_USBMODE);
> +
> + =A0 =A0 =A0 if (pdata->have_sysif_regs) {
> =A0#ifdef CONFIG_PPC_85xx
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x=
00000008);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH=
, 0x00000080);
> =A0#else
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c);
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x=
0000000c);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH=
, 0x00000040);
> =A0#endif
> - =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x0=
0000001);
> + =A0 =A0 =A0 }
> =A0}
>
> =A0/* called after powerup, by probe or system-pm "wakeup" */
> =A0static int ehci_fsl_reinit(struct ehci_hcd *ehci)
> =A0{
> - =A0 =A0 =A0 mpc83xx_usb_setup(ehci_to_hcd(ehci));
> + =A0 =A0 =A0 ehci_fsl_usb_setup(ehci);
> =A0 =A0 =A0 =A0ehci_port_power(ehci, 0);
>
> =A0 =A0 =A0 =A0return 0;
> @@ -259,6 +305,11 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
> =A0{
> =A0 =A0 =A0 =A0struct ehci_hcd *ehci =3D hcd_to_ehci(hcd);
> =A0 =A0 =A0 =A0int retval;
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata;
> +
> + =A0 =A0 =A0 pdata =3D hcd->self.controller->platform_data;
> + =A0 =A0 =A0 ehci->big_endian_desc =3D pdata->big_endian_desc;
> + =A0 =A0 =A0 ehci->big_endian_mmio =3D pdata->big_endian_mmio;
>
> =A0 =A0 =A0 =A0/* EHCI registers start at offset 0x100 */
> =A0 =A0 =A0 =A0ehci->caps =3D hcd->regs + 0x100;
> @@ -372,7 +423,7 @@ static const struct hc_driver ehci_fsl_hc_driver =3D =
{
> =A0 =A0 =A0 =A0 * generic hardware linkage
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0.irq =3D ehci_irq,
> - =A0 =A0 =A0 .flags =3D HCD_USB2,
> + =A0 =A0 =A0 .flags =3D HCD_USB2 | HCD_MEMORY,
>
> =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 * basic lifecycle operations
> diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
> index b5e59db..e56be7b 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.
> =A0* Copyright (c) 2005 MontaVista Software
> =A0*
> =A0* This program is free software; you can redistribute =A0it and/or mod=
ify it
> @@ -19,6 +19,11 @@
> =A0#define _EHCI_FSL_H
>
> =A0/* offsets for the non-ehci registers in the FSL SOC USB controller */
> +#define FSL_SOC_USB_ID =A0 =A0 =A0 =A0 0x0
> +#define ID_MSK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 0x3f
> +#define NID_MSK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00x3f00
> +#define FSL_SOC_USB_SBUSCFG =A0 =A00x90
> +#define FSL_SOC_USB_BURSTSIZE =A00x160
> =A0#define FSL_SOC_USB_ULPIVP =A0 =A0 0x170
> =A0#define FSL_SOC_USB_PORTSC1 =A0 =A00x184
> =A0#define PORT_PTS_MSK =A0 =A0 =A0 =A0 =A0 (3<<30)
> @@ -26,8 +31,20 @@
> =A0#define PORT_PTS_ULPI =A0 =A0 =A0 =A0 =A0(2<<30)
> =A0#define =A0 =A0 =A0 =A0PORT_PTS_SERIAL =A0 =A0 =A0 =A0 (3<<30)
> =A0#define PORT_PTS_PTW =A0 =A0 =A0 =A0 =A0 (1<<28)
> +#define PORT_PTS_PHCD =A0 =A0 =A0 =A0 =A0(1<<23)
> =A0#define FSL_SOC_USB_PORTSC2 =A0 =A00x188
> =A0#define FSL_SOC_USB_USBMODE =A0 =A00x1a8
> +#define USBMODE_CM_MASK =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(3 << 0) =A0 =A0 =
=A0 =A0/* controller mode mask */
> +#define USBMODE_CM_HOST =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(3 << 0) =A0 =A0 =
=A0 =A0/* controller mode: host */
> +#define USBMODE_ES =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/* (B=
ig) Endian Select */
> +
> +#define FSL_SOC_USB_USBGENCTRL 0x200
> +#define USBGENCTRL_PPP =A0 =A0 =A0 =A0 (1 << 3)
> +#define USBGENCTRL_PFP =A0 =A0 =A0 =A0 (1 << 2)
> +#define FSL_SOC_USB_ISIPHYCTRL 0x204
> +#define ISIPHYCTRL_PXE =A0 =A0 =A0 =A0 (1)
> +#define ISIPHYCTRL_PHYE =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(1 << 4)
> +
> =A0#define FSL_SOC_USB_SNOOP1 =A0 =A0 0x400 =A0 /* NOTE: big-endian */
> =A0#define FSL_SOC_USB_SNOOP2 =A0 =A0 0x404 =A0 /* NOTE: big-endian */
> =A0#define FSL_SOC_USB_AGECNTTHRSH =A0 =A0 =A0 =A00x408 =A0 /* 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,
> =A0{
> =A0 =A0 =A0 =A0memset (qtd, 0, sizeof *qtd);
> =A0 =A0 =A0 =A0qtd->qtd_dma =3D dma;
> - =A0 =A0 =A0 qtd->hw_token =3D cpu_to_le32 (QTD_STS_HALT);
> + =A0 =A0 =A0 qtd->hw_token =3D cpu_to_hc32(ehci, QTD_STS_HALT);
> =A0 =A0 =A0 =A0qtd->hw_next =3D EHCI_LIST_END(ehci);
> =A0 =A0 =A0 =A0qtd->hw_alt_next =3D EHCI_LIST_END(ehci);
> =A0 =A0 =A0 =A0INIT_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 020a939..0ced9fc 100644
> --- a/drivers/usb/host/fsl-mph-dr-of.c
> +++ b/drivers/usb/host/fsl-mph-dr-of.c
> @@ -14,6 +14,7 @@
> =A0#include <linux/fsl_devices.h>
> =A0#include <linux/io.h>
> =A0#include <linux/of_platform.h>
> +#include <linux/clk.h>
>
> =A0struct fsl_usb2_dev_data {
> =A0 =A0 =A0 =A0char *dr_mode; =A0 =A0 =A0 =A0 =A0/* controller mode */
> @@ -146,6 +147,12 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct=
 of_device *ofdev,
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pdata->operating_mode =3D FSL_USB2_MPH_HOS=
T;
> =A0 =A0 =A0 =A0} else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "fsl,invert-drvvbus=
", NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->invert_drvvbus =3D 1=
;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (of_get_property(np, "fsl,invert-pwr-fau=
lt", NULL))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->invert_pwr_fault =3D=
 1;
> +
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* setup mode selected in the device tree =
*/
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pdata->operating_mode =3D dev_data->op_mod=
e;
> =A0 =A0 =A0 =A0}
> @@ -167,9 +174,91 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct=
 of_device *ofdev,
> =A0 =A0 =A0 =A0return 0;
> =A0}
>
> +#ifdef CONFIG_PPC_MPC512x
> +
> +#define USBGENCTRL =A0 =A0 =A0 =A0 =A0 =A0 0x200 =A0 =A0 =A0 =A0 =A0 /* =
NOTE: big endian */
> +#define GC_WU_INT_CLR =A0 =A0 =A0 =A0 =A0(1 << 5) =A0 =A0 =A0 =A0/* Wake=
up int clear */
> +#define GC_ULPI_SEL =A0 =A0 =A0 =A0 =A0 =A0(1 << 4) =A0 =A0 =A0 =A0/* UL=
PI i/f select (usb0 only)*/
> +#define GC_PPP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 3) =A0 =A0 =A0 =A0/=
* Inv. Port Power Polarity */
> +#define GC_PFP =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/=
* Inv. Power Fault Polarity */
> +#define GC_WU_ULPI_EN =A0 =A0 =A0 =A0 =A0(1 << 1) =A0 =A0 =A0 =A0/* Wake=
up on ULPI event */
> +#define GC_WU_IE =A0 =A0 =A0 =A0 =A0 =A0 =A0 (1 << 1) =A0 =A0 =A0 =A0/* =
Wakeup interrupt enable */
> +
> +#define ISIPHYCTRL =A0 =A0 =A0 =A0 =A0 =A0 0x204 =A0 =A0 =A0 =A0 =A0 /* =
NOTE: big endian */
> +#define PHYCTRL_PHYE =A0 =A0 =A0 =A0 =A0 (1 << 4) =A0 =A0 =A0 =A0/* On-c=
hip UTMI PHY enable */
> +#define PHYCTRL_BSENH =A0 =A0 =A0 =A0 =A0(1 << 3) =A0 =A0 =A0 =A0/* Bit =
Stuff Enable High */
> +#define PHYCTRL_BSEN =A0 =A0 =A0 =A0 =A0 (1 << 2) =A0 =A0 =A0 =A0/* Bit =
Stuff Enable */
> +#define PHYCTRL_LSFE =A0 =A0 =A0 =A0 =A0 (1 << 1) =A0 =A0 =A0 =A0/* Line=
 State Filter Enable */
> +#define PHYCTRL_PXE =A0 =A0 =A0 =A0 =A0 =A0(1 << 0) =A0 =A0 =A0 =A0/* PH=
Y oscillator enable */
> +
> +int fsl_usb2_mpc5121_init(struct platform_device *pdev)
> +{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> + =A0 =A0 =A0 struct clk *clk;
> + =A0 =A0 =A0 char clk_name[10];
> + =A0 =A0 =A0 int base, clk_num;
> +
> + =A0 =A0 =A0 base =3D pdev->resource->start & 0xf000;
> + =A0 =A0 =A0 if (base =3D=3D 0x3000)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_num =3D 1;
> + =A0 =A0 =A0 else if (base =3D=3D 0x4000)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_num =3D 2;
> + =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
> +
> + =A0 =A0 =A0 snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num);
> + =A0 =A0 =A0 clk =3D clk_get(&pdev->dev, clk_name);
> + =A0 =A0 =A0 if (IS_ERR(clk)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev_err(&pdev->dev, "failed to get clk\n");
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return PTR_ERR(clk);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 clk_enable(clk);
> + =A0 =A0 =A0 pdata->clk =3D clk;
> +
> + =A0 =A0 =A0 if (pdata->phy_mode =3D=3D FSL_USB2_PHY_UTMI_WIDE) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 reg =3D 0;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (pdata->invert_drvvbus)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg |=3D GC_PPP;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (pdata->invert_pwr_fault)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 reg |=3D GC_PFP;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(pdata->regs + ISIPHYCTRL, PHYCTRL_=
PHYE | PHYCTRL_PXE);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(pdata->regs + USBGENCTRL, reg);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static void fsl_usb2_mpc5121_exit(struct platform_device *pdev)
> +{
> + =A0 =A0 =A0 struct fsl_usb2_platform_data *pdata =3D pdev->dev.platform=
_data;
> +
> + =A0 =A0 =A0 pdata->regs =3D NULL;
> +
> + =A0 =A0 =A0 if (pdata->clk) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_disable(pdata->clk);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 clk_put(pdata->clk);
> + =A0 =A0 =A0 }
> +}
> +
> +struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd =3D {
> + =A0 =A0 =A0 .big_endian_desc =3D 1,
> + =A0 =A0 =A0 .big_endian_mmio =3D 1,
> + =A0 =A0 =A0 .es =3D 1,
> + =A0 =A0 =A0 .le_setup_buf =3D 1,
> + =A0 =A0 =A0 .init =3D fsl_usb2_mpc5121_init,
> + =A0 =A0 =A0 .exit =3D fsl_usb2_mpc5121_exit,
> +};
> +#endif /* CONFIG_PPC_MPC512x */
> +
> =A0static const struct of_device_id fsl_usb2_mph_dr_of_match[] =3D {
> =A0 =A0 =A0 =A0{ .compatible =3D "fsl-usb2-mph", },
> =A0 =A0 =A0 =A0{ .compatible =3D "fsl-usb2-dr", },
> +#ifdef CONFIG_PPC_MPC512x
> + =A0 =A0 =A0 { .compatible =3D "fsl,mpc5121-usb2-dr", .data =3D &fsl_usb=
2_mpc5121_pd, },
> +#endif
> =A0 =A0 =A0 =A0{},
> =A0};
>
> 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 {
> =A0 =A0 =A0 =A0FSL_USB2_PHY_SERIAL,
> =A0};
>
> +struct clk;
> +struct platform_device;
> +
> =A0struct fsl_usb2_platform_data {
> =A0 =A0 =A0 =A0/* board specific information */
> =A0 =A0 =A0 =A0enum fsl_usb2_operating_modes =A0 operating_mode;
> =A0 =A0 =A0 =A0enum fsl_usb2_phy_modes =A0 =A0 =A0 =A0 phy_mode;
> =A0 =A0 =A0 =A0unsigned int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0port_e=
nables;
> +
> + =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 (*init)(struct platform_device =
*);
> + =A0 =A0 =A0 void =A0 =A0 =A0 =A0 =A0 =A0(*exit)(struct platform_device =
*);
> + =A0 =A0 =A0 void __iomem =A0 =A0*regs; =A0 =A0 =A0 =A0 =A0/* ioremap'd =
register base */
> + =A0 =A0 =A0 struct clk =A0 =A0 =A0*clk;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0big_endian_mmio:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0big_endian_desc:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0es:1; =A0 =A0 =A0 =A0 =A0 /* need U=
SBMODE:ES */
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0le_setup_buf:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0have_sysif_regs:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0invert_drvvbus:1;
> + =A0 =A0 =A0 unsigned =A0 =A0 =A0 =A0invert_pwr_fault:1;
> =A0};
>
> =A0/* Flags in fsl_usb2_mph_platform_data */
> --
> 1.7.0.4
>
>



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

^ permalink raw reply

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

On Thu, Jul 22, 2010 at 10:25 AM, 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>

Hi Anatolij,

Looks pretty good, but some comments below.

g.

> ---
> =A0drivers/usb/gadget/Kconfig =A0 =A0 =A0 | =A0 =A01 +
> =A0drivers/usb/host/Kconfig =A0 =A0 =A0 =A0 | =A0 =A05 +
> =A0drivers/usb/host/Makefile =A0 =A0 =A0 =A0| =A0 =A01 +
> =A0drivers/usb/host/fsl-mph-dr-of.c | =A0189 ++++++++++++++++++++++++++++=
++++++++++
> =A04 files changed, 196 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 cd27f9b..e15e314 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..6687523 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -112,10 +112,15 @@ 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 bool
> + =A0 =A0 =A0 depends on PPC_OF

Drop the depends.  This is selected by USB_EHCI_FSL and
USB_GADGET_FSL_USB2, which are already PPC only.

> +
> =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..020a939
> --- /dev/null
> +++ b/drivers/usb/host/fsl-mph-dr-of.c
> @@ -0,0 +1,189 @@
> +/*
> + * 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/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 "host",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 { "fsl-ehci", NULL, NULL, },
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 FSL_USB2_DR_HOST,
> + =A0 =A0 =A0 },
> + =A0 =A0 =A0 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 "otg",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 { "fsl-ehci", "fsl-usb2-udc", "fsl-usb2-otg=
", },
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 FSL_USB2_DR_OTG,
> + =A0 =A0 =A0 },
> + =A0 =A0 =A0 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 "periferal",

spelling.  "peripheral"

> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 { "fsl-usb2-udc", NULL, NULL, },
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 FSL_USB2_DR_DEVICE,
> + =A0 =A0 =A0 },
> +};

Program defensively.  Use the following form:
+ =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 },

> +
> +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 }

Print a warning if you get through the loop, but don't match anything.
 That means that dr_mode has a bad value.

> + =A0 =A0 =A0 }
> + =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(struct of_device *ofdev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct fsl_usb2_platform=
_data *pdata,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const char *name, int id=
)

In general, it is better to have the function name on the same line as
the return arguements so that grep shows the relevant info.  Move the
arguments to subsequent lines.

> +{
> + =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;

Good!  The sub-devices show up sanely in the device hierarchy by
setting the parent pointer.

> +
> + =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 of_device *ofdev,
> + =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)
> +{
> + =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;

What is this for?

> +
> + =A0 =A0 =A0 pdata =3D match->data;
> + =A0 =A0 =A0 if (!pdata) {

The match table doesn't have any data, so this is a no-op.

> + =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 }
> +
> + =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 prop =3D of_get_property(np, "port0", NULL)=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (prop)

if (of_get_property())

> + =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 prop =3D of_get_property(np, "port1", NULL)=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (prop)

Ditto

> + =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 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,
> +};

No remove hook?

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

Why fs_initcall?  Is module_init() not sufficient?

> --
> 1.7.0.4
>
>



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

^ permalink raw reply

* Re: [PATCH 3/3] mmc: Add ESDHC weird register workaround
From: Anton Vorontsov @ 2010-07-28  8:03 UTC (permalink / raw)
  To: Roy Zang; +Cc: linuxppc-dev, linux-mmc-approval
In-Reply-To: <1280296461-17077-1-git-send-email-tie-fei.zang@freescale.com>

On Wed, Jul 28, 2010 at 01:54:21PM +0800, Roy Zang wrote:
> P4080 ESDHC controller induces weird register setting.
> This patch adds the workaround to correct the weird register setting.
> 
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
> ---
>  drivers/mmc/host/sdhci-of-core.c |    5 +++++
>  drivers/mmc/host/sdhci.c         |   13 +++++++++++++
>  drivers/mmc/host/sdhci.h         |    2 ++
>  3 files changed, 20 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
> index 0c30242..1b6945a 100644
> --- a/drivers/mmc/host/sdhci-of-core.c
> +++ b/drivers/mmc/host/sdhci-of-core.c
> @@ -164,6 +164,11 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev,
>  	if (sdhci_of_wp_inverted(np))
>  		host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
>  
> +	if (of_device_is_compatible(np, "fsl,p4080-esdhc")) {
> +		host->quirks |= SDHCI_QUIRK_QORIQ_REG_WEIRD;
> +		host->quirks &= ~SDHCI_QUIRK_INVERTED_WRITE_PROTECT;

You do not mention this change in the patch description, why?

> +	}
> +
>  	clk = of_get_property(np, "clock-frequency", &size);
>  	if (clk && size == sizeof(*clk) && *clk)
>  		of_host->clock = *clk;
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index 1424d08..b5b3627 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -788,6 +788,15 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
>  		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
>  	}
>  
> +	/* The default value of DMAS bits of Protocol Control Register is not
> +	 * correct. clear these two bits to use simple DMA */
> +#define  ESDHCI_CTRL_DMAS_MASK		0xFFFFFCFF
> +	if (host->quirks & SDHCI_QUIRK_QORIQ_REG_WEIRD) {
> +		ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
> +		ctrl = ctrl & ESDHCI_CTRL_DMAS_MASK;
> +		sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
> +	}

You should implement register quirks via SDHCI IO accessors.

See esdhc_writew() for example.

>  	if (!(host->flags & SDHCI_REQ_USE_DMA)) {
>  		int flags;
>  
> @@ -1699,6 +1708,10 @@ int sdhci_add_host(struct sdhci_host *host)
>  
>  	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
>  
> +	 /* Workaround for P4080 host controller capabilities */
> +	if (host->quirks & SDHCI_QUIRK_QORIQ_REG_WEIRD)
> +		caps &= ~(SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_330);

Ditto. Make a quirk for cap register. Or implement
SDHCI_QUIRK_NO_VDD_180 and SDHCI_QUIRK_NO_VDD_300 quirks
instead.

Thanks,

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

^ permalink raw reply

* Re: [PATCH v4 1/5] fsl-diu-fb: fix issue with re-enabling DIU area descriptor
From: Anatolij Gustschin @ 2010-07-28  7:56 UTC (permalink / raw)
  To: Grant Likely
  Cc: linuxppc-dev, linux-fbdev, devicetree-discuss, Detlev Zundel,
	Wolfgang Denk
In-Reply-To: <AANLkTikkLVCxU4ZC_nmUhKTQogUNeQzxOX6KqgZcxiYr@mail.gmail.com>

On Wed, 28 Jul 2010 01:02:59 -0600
Grant Likely <grant.likely@secretlab.ca> wrote:
...
> > =C2=A0drivers/video/fsl-diu-fb.c | =C2=A0 38 +++++++++++++++++++++++---=
------------
> > =C2=A01 files changed, 23 insertions(+), 15 deletions(-)
> >
> > diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
> > index 27455ce..9b8c991 100644
> > --- a/drivers/video/fsl-diu-fb.c
> > +++ b/drivers/video/fsl-diu-fb.c
> > @@ -317,6 +317,17 @@ static void fsl_diu_free(void *virt, size_t size)
> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0free_pages_exact=
(virt, size);
> > =C2=A0}
> >
> > +/*
> > + * Workaround for failed writing desc register of planes.
> > + * Needed with MPC5121 DIU rev 2.0 silicon.
> > + */
> > +void wr_reg_wa(u32 *reg, u32 val)
> > +{
> > + =C2=A0 =C2=A0 =C2=A0 do {
> > + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 out_be32(reg, val);
> > + =C2=A0 =C2=A0 =C2=A0 } while (in_be32(reg) !=3D val);
> > +}
>=20
> I'll apply this one, but it looks like a potential problem.  What
> happens if the write never succeeds?  The kernel then gets stuck in a
> forever busy loop.  You should look at reworking it.

I'll submit an incremental patch that prevents looping forever in
the case if the write never succeeds. Thanks!

Anatolij

^ permalink raw reply

* Re: [PATCH] xilinxfb: update tft comp versions
From: Grant Likely @ 2010-07-28  7:52 UTC (permalink / raw)
  To: Adrian Alonso; +Cc: devicetree-discuss, linuxppc-dev
In-Reply-To: <1280265853-21245-1-git-send-email-aalonso00@gmail.com>

On Tue, Jul 27, 2010 at 3:24 PM, Adrian Alonso <aalonso00@gmail.com> wrote:
> * Add tft display module compatibility for new
> =A0hardware modules
>
> Signed-off-by: Adrian Alonso <aalonso00@gmail.com>
> ---
> =A0drivers/video/xilinxfb.c | =A0 =A02 ++
> =A01 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
> index 574dc54..29b5daa 100644
> --- a/drivers/video/xilinxfb.c
> +++ b/drivers/video/xilinxfb.c
> @@ -485,6 +485,8 @@ static int __devexit xilinxfb_of_remove(struct of_dev=
ice *op)
> =A0/* Match table for of_platform binding */
> =A0static struct of_device_id xilinxfb_of_match[] __devinitdata =3D {
> =A0 =A0 =A0 =A0{ .compatible =3D "xlnx,xps-tft-1.00.a", },
> + =A0 =A0 =A0 { .compatible =3D "xlnx,xps-tft-2.00.a", },
> + =A0 =A0 =A0 { .compatible =3D "xlnx,xps-tft-2.01.a", },
> =A0 =A0 =A0 =A0{ .compatible =3D "xlnx,plb-tft-cntlr-ref-1.00.a", },
> =A0 =A0 =A0 =A0{ .compatible =3D "xlnx,plb-dvi-cntlr-ref-1.00.c", },
> =A0 =A0 =A0 =A0{},

I'll merged this, but it isn't exactly the best fix (not your fault; a
deficiency in the xilinx device tree generator).  I still need to get
around to fixing the generator to claim compatibility with the .00.a
ip core versions by default for newer parts with the same major
revision number.  Once it is fixed, then only the -2.00.a compatible
value would need to be added to the table.

Thanks Adrian.

g.

^ permalink raw reply

* Re: [PATCH v4 1/5] fsl-diu-fb: fix issue with re-enabling DIU area descriptor
From: Grant Likely @ 2010-07-28  7:02 UTC (permalink / raw)
  To: Anatolij Gustschin
  Cc: linuxppc-dev, linux-fbdev, devicetree-discuss, Detlev Zundel,
	Wolfgang Denk
In-Reply-To: <1279893639-24333-2-git-send-email-agust@denx.de>

On Fri, Jul 23, 2010 at 8:00 AM, Anatolij Gustschin <agust@denx.de> wrote:
> On MPC5121e Rev 2.0 re-configuring the DIU area descriptor
> by writing new descriptor address doesn't always work.
> As a result, DIU continues to display using old area descriptor
> even if the new one has been written to the descriptor register of
> the plane.
>
> Add the code from Freescale MPC5121EADS BSP for writing descriptor
> addresses properly. This fixes the problem for Rev 2.0 silicon.
>
> Signed-off-by: Anatolij Gustschin <agust@denx.de>
> ---
> v4:
> =A0- use workaround code as suggested by FSL technical support.
>
> v3:
> =A0- no changes since v1
>
> =A0drivers/video/fsl-diu-fb.c | =A0 38 +++++++++++++++++++++++-----------=
----
> =A01 files changed, 23 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
> index 27455ce..9b8c991 100644
> --- a/drivers/video/fsl-diu-fb.c
> +++ b/drivers/video/fsl-diu-fb.c
> @@ -317,6 +317,17 @@ static void fsl_diu_free(void *virt, size_t size)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0free_pages_exact(virt, size);
> =A0}
>
> +/*
> + * Workaround for failed writing desc register of planes.
> + * Needed with MPC5121 DIU rev 2.0 silicon.
> + */
> +void wr_reg_wa(u32 *reg, u32 val)
> +{
> + =A0 =A0 =A0 do {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(reg, val);
> + =A0 =A0 =A0 } while (in_be32(reg) !=3D val);
> +}

I'll apply this one, but it looks like a potential problem.  What
happens if the write never succeeds?  The kernel then gets stuck in a
forever busy loop.  You should look at reworking it.

g.

> +
> =A0static int fsl_diu_enable_panel(struct fb_info *info)
> =A0{
> =A0 =A0 =A0 =A0struct mfb_info *pmfbi, *cmfbi, *mfbi =3D info->par;
> @@ -330,7 +341,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0switch (mfbi->index) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case 0: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (hw->desc[0] !=3D ad->p=
addr)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&h=
w->desc[0], ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&=
hw->desc[0], ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case 1: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 1 AOI 0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cmfbi =3D machine_data->fs=
l_diu_info[2]->par;
> @@ -340,7 +351,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0cpu_to_le32(cmfbi->ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0ad->next_ad =3D 0;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&h=
w->desc[1], ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&=
hw->desc[1], ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case 3: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 2 AOI 0 */
> @@ -351,14 +362,14 @@ static int fsl_diu_enable_panel(struct fb_info *inf=
o)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0cpu_to_le32(cmfbi->ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0ad->next_ad =3D 0;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&h=
w->desc[2], ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&=
hw->desc[2], ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0case 2: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 1 AOI 1 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pmfbi =3D machine_data->fs=
l_diu_info[1]->par;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ad->next_ad =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (hw->desc[1] =3D=3D mac=
hine_data->dummy_ad->paddr)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&h=
w->desc[1], ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&=
hw->desc[1], ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* AOI0 open */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pmfbi->ad-=
>next_ad =3D cpu_to_le32(ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> @@ -366,7 +377,7 @@ static int fsl_diu_enable_panel(struct fb_info *info)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pmfbi =3D machine_data->fs=
l_diu_info[3]->par;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ad->next_ad =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (hw->desc[2] =3D=3D mac=
hine_data->dummy_ad->paddr)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&h=
w->desc[2], ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&=
hw->desc[2], ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* AOI0 was open */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pmfbi->ad-=
>next_ad =3D cpu_to_le32(ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> @@ -390,27 +401,24 @@ static int fsl_diu_disable_panel(struct fb_info *in=
fo)
> =A0 =A0 =A0 =A0switch (mfbi->index) {
> =A0 =A0 =A0 =A0case 0: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (hw->desc[0] !=3D machine_data->dummy_a=
d->paddr)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&hw->desc[0],
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 machine_dat=
a->dummy_ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&hw->desc[0], mac=
hine_data->dummy_ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0case 1: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 1 AOI 0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cmfbi =3D machine_data->fsl_diu_info[2]->p=
ar;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (cmfbi->count > 0) =A0 /* AOI1 is open =
*/
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&hw->desc[1], cmfb=
i->ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&hw->desc[1], cmf=
bi->ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0/* move AOI1 to the first */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0/* AOI1 was closed */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&hw->desc[1],
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 machine_dat=
a->dummy_ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&hw->desc[1], mac=
hine_data->dummy_ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0/* close AOI 0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0case 3: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 2 AOI 0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cmfbi =3D machine_data->fsl_diu_info[4]->p=
ar;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (cmfbi->count > 0) =A0 /* AOI1 is open =
*/
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&hw->desc[2], cmfb=
i->ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&hw->desc[2], cmf=
bi->ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0/* move AOI1 to the first */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0/* AOI1 was closed */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&hw->desc[2],
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 machine_dat=
a->dummy_ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&hw->desc[2], mac=
hine_data->dummy_ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0/* close AOI 0 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0case 2: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 1 AOI 1 */
> @@ -421,7 +429,7 @@ static int fsl_diu_disable_panel(struct fb_info *info=
)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0/* AOI0 is open, must be the first */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pmfbi->ad-=
>next_ad =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
/* AOI1 is the first in the chain */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&hw->desc[1], mach=
ine_data->dummy_ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&hw->desc[1], mac=
hine_data->dummy_ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0/* close AOI 1 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0case 4: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 /* plane 2 AOI 1 */
> @@ -432,7 +440,7 @@ static int fsl_diu_disable_panel(struct fb_info *info=
)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* AOI0 is=
 open, must be the first */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pmfbi->ad-=
>next_ad =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} else =A0 =A0 =A0 =A0 =A0/* AOI1 is the f=
irst in the chain */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 out_be32(&hw->desc[2], mach=
ine_data->dummy_ad->paddr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 wr_reg_wa(&hw->desc[2], mac=
hine_data->dummy_ad->paddr);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* close A=
OI 1 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
> =A0 =A0 =A0 =A0default:
> --
> 1.7.0.4
>
>



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

^ permalink raw reply

* [PATCH 2/3] dts: Add sdhci-auto-cmd12 field for p4080 device tree
From: Roy Zang @ 2010-07-28  5:44 UTC (permalink / raw)
  To: linux-mmc-approval; +Cc: linuxppc-dev

Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
 arch/powerpc/boot/dts/p4080ds.dts |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 6b29eab..11c8884 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -280,6 +280,7 @@
 			reg = <0x114000 0x1000>;
 			interrupts = <48 2>;
 			interrupt-parent = <&mpic>;
+			fsl,sdhci-auto-cmd12;
 		};
 
 		i2c@118000 {
-- 
1.5.6.5

^ permalink raw reply related

* [PATCH 1/3] mmc: Auto CMD12 support for eSDHC driver
From: Roy Zang @ 2010-07-28  5:42 UTC (permalink / raw)
  To: linux-mmc-approval; +Cc: linuxppc-dev, Chang-Ming.Huang

From: Jerry Huang <Chang-Ming.Huang@freescale.com>

Add auto CMD12 command support for eSDHC driver.
This is needed by P4080 and P1022 for block read/write.
Manual asynchronous CMD12 abort operation causes protocol violations on
these silicons.

Signed-off-by: Jerry Huang <Chang-Ming.Huang@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
 drivers/mmc/host/sdhci-of-core.c |    4 ++++
 drivers/mmc/host/sdhci.c         |   14 ++++++++++++--
 drivers/mmc/host/sdhci.h         |    3 +++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
index a2e9820..0c30242 100644
--- a/drivers/mmc/host/sdhci-of-core.c
+++ b/drivers/mmc/host/sdhci-of-core.c
@@ -154,6 +154,10 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev,
 		host->ops = &sdhci_of_data->ops;
 	}
 
+	if (of_get_property(np, "fsl,sdhci-auto-cmd12", NULL))
+		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+
+
 	if (of_get_property(np, "sdhci,1-bit-only", NULL))
 		host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c6d1bd8..1424d08 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2,6 +2,7 @@
  *  linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
  *
  *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
+ * Copyright 2010 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -817,8 +818,12 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
 	WARN_ON(!host->data);
 
 	mode = SDHCI_TRNS_BLK_CNT_EN;
-	if (data->blocks > 1)
-		mode |= SDHCI_TRNS_MULTI;
+	if (data->blocks > 1) {
+		if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
+			mode |= SDHCI_TRNS_MULTI | SDHCI_TRNS_ACMD12;
+		else
+			mode |= SDHCI_TRNS_MULTI;
+	}
 	if (data->flags & MMC_DATA_READ)
 		mode |= SDHCI_TRNS_READ;
 	if (host->flags & SDHCI_REQ_USE_DMA)
@@ -1108,6 +1113,11 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 #ifndef SDHCI_USE_LEDS_CLASS
 	sdhci_activate_led(host);
 #endif
+	if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
+		if (mrq->stop) {
+			mrq->data->stop = NULL;
+			mrq->stop = NULL;
+		}
 
 	host->mrq = mrq;
 
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index c846813..aa112aa 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -2,6 +2,7 @@
  *  linux/drivers/mmc/host/sdhci.h - Secure Digital Host Controller Interface driver
  *
  *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
+ * Copyright 2010 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -240,6 +241,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN		(1<<25)
 /* Controller cannot support End Attribute in NOP ADMA descriptor */
 #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC		(1<<26)
+/* Controller uses Auto CMD12 command to stop the transfer */
+#define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12		(1<<27)
 
 	int			irq;		/* Device IRQ */
 	void __iomem *		ioaddr;		/* Mapped address */
-- 
1.5.6.5

^ permalink raw reply related

* [PATCH 3/3] mmc: Add ESDHC weird register workaround
From: Roy Zang @ 2010-07-28  5:54 UTC (permalink / raw)
  To: linux-mmc-approval; +Cc: linuxppc-dev

P4080 ESDHC controller induces weird register setting.
This patch adds the workaround to correct the weird register setting.

Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
 drivers/mmc/host/sdhci-of-core.c |    5 +++++
 drivers/mmc/host/sdhci.c         |   13 +++++++++++++
 drivers/mmc/host/sdhci.h         |    2 ++
 3 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
index 0c30242..1b6945a 100644
--- a/drivers/mmc/host/sdhci-of-core.c
+++ b/drivers/mmc/host/sdhci-of-core.c
@@ -164,6 +164,11 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev,
 	if (sdhci_of_wp_inverted(np))
 		host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
 
+	if (of_device_is_compatible(np, "fsl,p4080-esdhc")) {
+		host->quirks |= SDHCI_QUIRK_QORIQ_REG_WEIRD;
+		host->quirks &= ~SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
+	}
+
 	clk = of_get_property(np, "clock-frequency", &size);
 	if (clk && size == sizeof(*clk) && *clk)
 		of_host->clock = *clk;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 1424d08..b5b3627 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -788,6 +788,15 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 	}
 
+	/* The default value of DMAS bits of Protocol Control Register is not
+	 * correct. clear these two bits to use simple DMA */
+#define  ESDHCI_CTRL_DMAS_MASK		0xFFFFFCFF
+	if (host->quirks & SDHCI_QUIRK_QORIQ_REG_WEIRD) {
+		ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
+		ctrl = ctrl & ESDHCI_CTRL_DMAS_MASK;
+		sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
+	}
+
 	if (!(host->flags & SDHCI_REQ_USE_DMA)) {
 		int flags;
 
@@ -1699,6 +1708,10 @@ int sdhci_add_host(struct sdhci_host *host)
 
 	caps = sdhci_readl(host, SDHCI_CAPABILITIES);
 
+	 /* Workaround for P4080 host controller capabilities */
+	if (host->quirks & SDHCI_QUIRK_QORIQ_REG_WEIRD)
+		caps &= ~(SDHCI_CAN_VDD_180 | SDHCI_CAN_VDD_330);
+
 	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
 		host->flags |= SDHCI_USE_SDMA;
 	else if (!(caps & SDHCI_CAN_DO_SDMA))
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index aa112aa..33d5613 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -243,6 +243,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC		(1<<26)
 /* Controller uses Auto CMD12 command to stop the transfer */
 #define SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12		(1<<27)
+/* Controller has weird bit setting for some registers due to errata */
+#define SDHCI_QUIRK_QORIQ_REG_WEIRD			(1<<28)
 
 	int			irq;		/* Device IRQ */
 	void __iomem *		ioaddr;		/* Mapped address */
-- 
1.5.6.5

^ permalink raw reply related

* [PATCH 0/3] mmc: Add mmc support for P4080 chip
From: Roy Zang @ 2010-07-28  5:41 UTC (permalink / raw)
  To: linux-mmc-approval; +Cc: linuxppc-dev

This serial patch adds some workarounds to enable mmc card
support for P4080 chip.

^ permalink raw reply

* Re: Please pull my perf.git urgent branch
From: Paul Mackerras @ 2010-07-28  4:47 UTC (permalink / raw)
  To: Scott Wood
  Cc: Peter Zijlstra, Kumar Gala, linux-kernel, linuxppc-dev,
	Ingo Molnar
In-Reply-To: <20100727112854.7bf97d48@schlenkerla.am.freescale.net>

On Tue, Jul 27, 2010 at 11:28:54AM -0500, Scott Wood wrote:

> Doesn't the setting of .period need to be maintained (it is in the other
> powerpc perf_event implementation that this is derived from)?

Gah, yes it does.

> I don't see how this is a security fix -- the existing initializer above
> should zero-fill the fields that are not explicitly initialized.  In fact,
> it's taking other fields that were previously initialized to zero and is
> making them uninitialized, since perf_sample_data_init only sets addr and
> raw.

So I misunderstood how an initializer for an automatic struct works.
Brown paper bag time for me... :(

Regarding the other fields, I assume Peter et al. have checked that
they don't need to be cleared, so it's a microoptimization to not
clear them.

> CCing linuxppc-dev on the original patch would have been nice...

True, but at least I can blame Peter Z. for that. :)

Kumar and Ben, how do you want to proceed on this one?

Paul.

^ permalink raw reply

* Re: [PATCH] powerpc: print decimal values in prom_init.c
From: Michael Neuling @ 2010-07-28  4:26 UTC (permalink / raw)
  To: benh; +Cc: Olof Johansson, Paul Mackerras, linuxppc-dev, Jesse Larrew, anton
In-Reply-To: <3394.1280280241@neuling.org>

Currently we look pretty stupid when printing out a bunch of things in
prom_init.c.  eg.

  Max number of cores passed to firmware: 0x0000000000000080

So I've change this to print in decimal:

  Max number of cores passed to firmware: 128 (NR_CPUS = 256)

This required adding a prom_print_dec() function and changing some
prom_printk() calls from %x to %lu.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Bike shed colour status: Mauve.

Thanks to a suggestion from paulus, we are now 3 lines shorter.

 arch/powerpc/kernel/prom_init.c |   44 +++++++++++++++++++++++++++++++--------
 1 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 3b6f8ae..941ff4d 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -311,6 +311,24 @@ static void __init prom_print_hex(unsigned long val)
 	call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
 }
 
+/* max number of decimal digits in an unsigned long */
+#define UL_DIGITS 21
+static void __init prom_print_dec(unsigned long val)
+{
+	int i, size;
+	char buf[UL_DIGITS+1];
+	struct prom_t *_prom = &RELOC(prom);
+
+	for (i = UL_DIGITS-1; i >= 0;  i--) {
+		buf[i] = (val % 10) + '0';
+		val = val/10;
+		if (val == 0)
+			break;
+	}
+	/* shift stuff down */
+	size = UL_DIGITS - i;
+	call_prom("write", 3, 1, _prom->stdout, buf+i, size);
+}
 
 static void __init prom_printf(const char *format, ...)
 {
@@ -350,6 +368,14 @@ static void __init prom_printf(const char *format, ...)
 			v = va_arg(args, unsigned long);
 			prom_print_hex(v);
 			break;
+		case 'l':
+			++q;
+			if (*q == 'u') { /* '%lu' */
+				++q;
+				v = va_arg(args, unsigned long);
+				prom_print_dec(v);
+			}
+			break;
 		}
 	}
 }
@@ -835,11 +861,11 @@ static int __init prom_count_smt_threads(void)
 		if (plen == PROM_ERROR)
 			break;
 		plen >>= 2;
-		prom_debug("Found 0x%x smt threads per core\n", (unsigned long)plen);
+		prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
 
 		/* Sanity check */
 		if (plen < 1 || plen > 64) {
-			prom_printf("Threads per core 0x%x out of bounds, assuming 1\n",
+			prom_printf("Threads per core %lu out of bounds, assuming 1\n",
 				    (unsigned long)plen);
 			return 1;
 		}
@@ -869,12 +895,12 @@ static void __init prom_send_capabilities(void)
 		cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]);
 		if (*cores != NR_CPUS) {
 			prom_printf("WARNING ! "
-				    "ibm_architecture_vec structure inconsistent: 0x%x !\n",
+				    "ibm_architecture_vec structure inconsistent: %lu!\n",
 				    *cores);
 		} else {
 			*cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
-			prom_printf("Max number of cores passed to firmware: 0x%x\n",
-				    (unsigned long)*cores);
+			prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
+				    *cores, NR_CPUS);
 		}
 
 		/* try calling the ibm,client-architecture-support method */
@@ -1482,7 +1508,7 @@ static void __init prom_hold_cpus(void)
 		reg = -1;
 		prom_getprop(node, "reg", &reg, sizeof(reg));
 
-		prom_debug("cpu hw idx   = 0x%x\n", reg);
+		prom_debug("cpu hw idx   = %lu\n", reg);
 
 		/* Init the acknowledge var which will be reset by
 		 * the secondary cpu when it awakens from its OF
@@ -1492,7 +1518,7 @@ static void __init prom_hold_cpus(void)
 
 		if (reg != _prom->cpu) {
 			/* Primary Thread of non-boot cpu */
-			prom_printf("starting cpu hw idx %x... ", reg);
+			prom_printf("starting cpu hw idx %lu... ", reg);
 			call_prom("start-cpu", 3, 0, node,
 				  secondary_hold, reg);
 
@@ -1507,7 +1533,7 @@ static void __init prom_hold_cpus(void)
 		}
 #ifdef CONFIG_SMP
 		else
-			prom_printf("boot cpu hw idx %x\n", reg);
+			prom_printf("boot cpu hw idx %lu\n", reg);
 #endif /* CONFIG_SMP */
 	}
 
@@ -2420,7 +2446,7 @@ static void __init prom_find_boot_cpu(void)
 	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
 	_prom->cpu = getprop_rval;
 
-	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
+	prom_debug("Booting CPU hw index = %lu\n", _prom->cpu);
 }
 
 static void __init prom_check_initrd(unsigned long r3, unsigned long r4)

^ permalink raw reply related

* Re: [PATCH 04/11] powerpc: Simplify update_vsyscall
From: john stultz @ 2010-07-28  1:33 UTC (permalink / raw)
  To: Paul Mackerras
  Cc: linuxppc-dev, Thomas Gleixner, Ingo Molnar, LKML, Anton Blanchard
In-Reply-To: <20100727234152.GC14947@brick.ozlabs.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 1792 bytes --]

On Wed, 2010-07-28 at 09:41 +1000, Paul Mackerras wrote:
> On Tue, Jul 13, 2010 at 05:56:21PM -0700, John Stultz wrote:
> 
> > Currently powerpc's update_vsyscall calls an inline update_gtod.
> > However, both are straightforward, and there are no other users,
> > so this patch merges update_gtod into update_vsyscall.
> > 
> > Compiles, but otherwise untested.
> 
> This and the following two patches will cause interesting conflicts
> with two commits in Ben Herrenschmidt's powerpc.git next branch,
> specifically 8fd63a9e ("powerpc: Rework VDSO gettimeofday to prevent
> time going backwards") and c1aa687d ("powerpc: Clean up obsolete code
> relating to decrementer and timebase") from me.  In fact the first of
> those two commits includes changes equivalent to those in your 5/11
> patch ("powerpc: Cleanup xtime usage"), as far as I can see.

Ahh.. Right.. I guess I should have remembered you were working on those
changes (even though I don't think I saw the final results sent to lkml
or anything).

Sorry about that.

> BTW, BenH's tree is at:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git

So I've cherry picked the two changes from the ppc tree, applied them
onto linus' git tree and then rebased my changes ontop of them.

The net of the change to the patch set:

Added to the head of the patch queue:
  powerpc: Rework VDSO gettimeofday to prevent time going backwards
  powerpc: Clean up obsolete code relating to decrementer and timebase

Modified to resolve collision:
  powerpc: Simplify update_vsyscall  

Dropped (as earlier patches already made equivalent changes):
  powerpc: Cleanup xtime usage

The full set is in the attached tarball.

Thomas, would you consider re-adding these? Hopefully that will avoid
any -next collisions.

thanks
-john

[-- Attachment #2: patches.tar.bz2 --]
[-- Type: application/x-bzip-compressed-tar, Size: 21405 bytes --]

^ permalink raw reply

* [PATCH] powerpc: print decimal values in prom_init.c
From: Michael Neuling @ 2010-07-28  1:24 UTC (permalink / raw)
  To: Jesse Larrew, benh, linuxppc-dev, Olof Johansson, anton
In-Reply-To: <10860.1279849480@neuling.org>

Currently we look pretty stupid when printing out a bunch of things in
prom_init.c.  eg.

  Max number of cores passed to firmware: 0x0000000000000080

So I've change this to print in decimal:

  Max number of cores passed to firmware: 128 (NR_CPUS = 256)

This required adding a prom_print_dec() function and changing some
prom_printk() calls from %x to %lu.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
This version changes more things over to decimal.

 arch/powerpc/kernel/prom_init.c |   47 +++++++++++++++++++++++++++++++-------
 1 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 3b6f8ae..7bc5ae8 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -311,6 +311,27 @@ static void __init prom_print_hex(unsigned long val)
 	call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
 }
 
+/* max number of decimal digits in an unsigned long */
+#define UL_DIGITS 21
+static void __init prom_print_dec(unsigned long val)
+{
+	int i, size;
+	char buf[UL_DIGITS+1];
+	struct prom_t *_prom = &RELOC(prom);
+
+	for (i = UL_DIGITS-1; i >= 0;  i--) {
+		buf[i] = (val % 10) + '0';
+		val = val/10;
+		if (val == 0)
+			break;
+	}
+	/* shift stuff down */
+	size = UL_DIGITS - i;
+	for (i = 0 ; i < size ; i++)
+		buf[i] = buf[i + UL_DIGITS - size];
+	buf[size+1] = '\0';
+	call_prom("write", 3, 1, _prom->stdout, buf, size);
+}
 
 static void __init prom_printf(const char *format, ...)
 {
@@ -350,6 +371,14 @@ static void __init prom_printf(const char *format, ...)
 			v = va_arg(args, unsigned long);
 			prom_print_hex(v);
 			break;
+		case 'l':
+			++q;
+			if (*q == 'u') { /* '%lu' */
+				++q;
+				v = va_arg(args, unsigned long);
+				prom_print_dec(v);
+			}
+			break;
 		}
 	}
 }
@@ -835,11 +864,11 @@ static int __init prom_count_smt_threads(void)
 		if (plen == PROM_ERROR)
 			break;
 		plen >>= 2;
-		prom_debug("Found 0x%x smt threads per core\n", (unsigned long)plen);
+		prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
 
 		/* Sanity check */
 		if (plen < 1 || plen > 64) {
-			prom_printf("Threads per core 0x%x out of bounds, assuming 1\n",
+			prom_printf("Threads per core %lu out of bounds, assuming 1\n",
 				    (unsigned long)plen);
 			return 1;
 		}
@@ -869,12 +898,12 @@ static void __init prom_send_capabilities(void)
 		cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]);
 		if (*cores != NR_CPUS) {
 			prom_printf("WARNING ! "
-				    "ibm_architecture_vec structure inconsistent: 0x%x !\n",
+				    "ibm_architecture_vec structure inconsistent: %lu!\n",
 				    *cores);
 		} else {
 			*cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
-			prom_printf("Max number of cores passed to firmware: 0x%x\n",
-				    (unsigned long)*cores);
+			prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
+				    *cores, NR_CPUS);
 		}
 
 		/* try calling the ibm,client-architecture-support method */
@@ -1482,7 +1511,7 @@ static void __init prom_hold_cpus(void)
 		reg = -1;
 		prom_getprop(node, "reg", &reg, sizeof(reg));
 
-		prom_debug("cpu hw idx   = 0x%x\n", reg);
+		prom_debug("cpu hw idx   = %lu\n", reg);
 
 		/* Init the acknowledge var which will be reset by
 		 * the secondary cpu when it awakens from its OF
@@ -1492,7 +1521,7 @@ static void __init prom_hold_cpus(void)
 
 		if (reg != _prom->cpu) {
 			/* Primary Thread of non-boot cpu */
-			prom_printf("starting cpu hw idx %x... ", reg);
+			prom_printf("starting cpu hw idx %lu... ", reg);
 			call_prom("start-cpu", 3, 0, node,
 				  secondary_hold, reg);
 
@@ -1507,7 +1536,7 @@ static void __init prom_hold_cpus(void)
 		}
 #ifdef CONFIG_SMP
 		else
-			prom_printf("boot cpu hw idx %x\n", reg);
+			prom_printf("boot cpu hw idx %lu\n", reg);
 #endif /* CONFIG_SMP */
 	}
 
@@ -2420,7 +2449,7 @@ static void __init prom_find_boot_cpu(void)
 	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
 	_prom->cpu = getprop_rval;
 
-	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
+	prom_debug("Booting CPU hw index = %lu\n", _prom->cpu);
 }
 
 static void __init prom_check_initrd(unsigned long r3, unsigned long r4)

^ permalink raw reply related

* Patch "genirq: Deal with desc->set_type() changing desc->chip" has been added to the 2.6.32-stable tree
From: gregkh @ 2010-07-28  0:33 UTC (permalink / raw)
  To: tglx, benh, eha, gregkh, linuxppc-dev; +Cc: stable, stable-commits


This is a note to let you know that I've just added the patch titled

    genirq: Deal with desc->set_type() changing desc->chip

to the 2.6.32-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
    genirq-deal-with-desc-set_type-changing-desc-chip.patch
and it can be found in the queue-2.6.32 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@kernel.org> know about it.


>From 4673247562e39a17e09440fa1400819522ccd446 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Mon, 7 Jun 2010 17:53:51 +0200
Subject: genirq: Deal with desc->set_type() changing desc->chip

From: Thomas Gleixner <tglx@linutronix.de>

commit 4673247562e39a17e09440fa1400819522ccd446 upstream.

The set_type() function can change the chip implementation when the
trigger mode changes. That might result in using an non-initialized
irq chip when called from __setup_irq() or when called via
set_irq_type() on an already enabled irq.

The set_irq_type() function should not be called on an enabled irq,
but because we forgot to put a check into it, we have a bunch of users
which grew the habit of doing that and it never blew up as the
function is serialized via desc->lock against all users of desc->chip
and they never hit the non-initialized irq chip issue.

The easy fix for the __setup_irq() issue would be to move the
irq_chip_set_defaults(desc->chip) call after the trigger setting to
make sure that a chip change is covered.

But as we have already users, which do the type setting after
request_irq(), the safe fix for now is to call irq_chip_set_defaults()
from __irq_set_trigger() when desc->set_type() changed the irq chip.

It needs a deeper analysis whether we should refuse to change the chip
on an already enabled irq, but that'd be a large scale change to fix
all the existing users. So that's neither stable nor 2.6.35 material.

Reported-by: Esben Haabendal <eha@doredevelopment.dk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: linuxppc-dev <linuxppc-dev@ozlabs.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 kernel/irq/manage.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -436,6 +436,9 @@ int __irq_set_trigger(struct irq_desc *d
 		/* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
 		desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
 		desc->status |= flags;
+
+		if (chip != desc->chip)
+			irq_chip_set_defaults(desc->chip);
 	}
 
 	return ret;


Patches currently in stable-queue which might be from tglx@linutronix.de are

queue-2.6.32/genirq-deal-with-desc-set_type-changing-desc-chip.patch

^ permalink raw reply

* Patch "genirq: Deal with desc->set_type() changing desc->chip" has been added to the 2.6.33-stable tree
From: gregkh @ 2010-07-28  0:26 UTC (permalink / raw)
  To: tglx, benh, eha, gregkh, linuxppc-dev; +Cc: stable, stable-commits


This is a note to let you know that I've just added the patch titled

    genirq: Deal with desc->set_type() changing desc->chip

to the 2.6.33-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
    genirq-deal-with-desc-set_type-changing-desc-chip.patch
and it can be found in the queue-2.6.33 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@kernel.org> know about it.


>From 4673247562e39a17e09440fa1400819522ccd446 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Mon, 7 Jun 2010 17:53:51 +0200
Subject: genirq: Deal with desc->set_type() changing desc->chip

From: Thomas Gleixner <tglx@linutronix.de>

commit 4673247562e39a17e09440fa1400819522ccd446 upstream.

The set_type() function can change the chip implementation when the
trigger mode changes. That might result in using an non-initialized
irq chip when called from __setup_irq() or when called via
set_irq_type() on an already enabled irq.

The set_irq_type() function should not be called on an enabled irq,
but because we forgot to put a check into it, we have a bunch of users
which grew the habit of doing that and it never blew up as the
function is serialized via desc->lock against all users of desc->chip
and they never hit the non-initialized irq chip issue.

The easy fix for the __setup_irq() issue would be to move the
irq_chip_set_defaults(desc->chip) call after the trigger setting to
make sure that a chip change is covered.

But as we have already users, which do the type setting after
request_irq(), the safe fix for now is to call irq_chip_set_defaults()
from __irq_set_trigger() when desc->set_type() changed the irq chip.

It needs a deeper analysis whether we should refuse to change the chip
on an already enabled irq, but that'd be a large scale change to fix
all the existing users. So that's neither stable nor 2.6.35 material.

Reported-by: Esben Haabendal <eha@doredevelopment.dk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: linuxppc-dev <linuxppc-dev@ozlabs.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 kernel/irq/manage.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -436,6 +436,9 @@ int __irq_set_trigger(struct irq_desc *d
 		/* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
 		desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
 		desc->status |= flags;
+
+		if (chip != desc->chip)
+			irq_chip_set_defaults(desc->chip);
 	}
 
 	return ret;


Patches currently in stable-queue which might be from tglx@linutronix.de are

queue-2.6.33/genirq-deal-with-desc-set_type-changing-desc-chip.patch
queue-2.6.33/x86-send-a-sigtrap-for-user-icebp-traps.patch

^ permalink raw reply

* Patch "genirq: Deal with desc->set_type() changing desc->chip" has been added to the 2.6.34-stable tree
From: gregkh @ 2010-07-28  0:24 UTC (permalink / raw)
  To: tglx, benh, eha, gregkh, linuxppc-dev; +Cc: stable, stable-commits


This is a note to let you know that I've just added the patch titled

    genirq: Deal with desc->set_type() changing desc->chip

to the 2.6.34-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
    genirq-deal-with-desc-set_type-changing-desc-chip.patch
and it can be found in the queue-2.6.34 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@kernel.org> know about it.


>From 4673247562e39a17e09440fa1400819522ccd446 Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Mon, 7 Jun 2010 17:53:51 +0200
Subject: genirq: Deal with desc->set_type() changing desc->chip

From: Thomas Gleixner <tglx@linutronix.de>

commit 4673247562e39a17e09440fa1400819522ccd446 upstream.

The set_type() function can change the chip implementation when the
trigger mode changes. That might result in using an non-initialized
irq chip when called from __setup_irq() or when called via
set_irq_type() on an already enabled irq.

The set_irq_type() function should not be called on an enabled irq,
but because we forgot to put a check into it, we have a bunch of users
which grew the habit of doing that and it never blew up as the
function is serialized via desc->lock against all users of desc->chip
and they never hit the non-initialized irq chip issue.

The easy fix for the __setup_irq() issue would be to move the
irq_chip_set_defaults(desc->chip) call after the trigger setting to
make sure that a chip change is covered.

But as we have already users, which do the type setting after
request_irq(), the safe fix for now is to call irq_chip_set_defaults()
from __irq_set_trigger() when desc->set_type() changed the irq chip.

It needs a deeper analysis whether we should refuse to change the chip
on an already enabled irq, but that'd be a large scale change to fix
all the existing users. So that's neither stable nor 2.6.35 material.

Reported-by: Esben Haabendal <eha@doredevelopment.dk>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: linuxppc-dev <linuxppc-dev@ozlabs.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
 kernel/irq/manage.c |    3 +++
 1 file changed, 3 insertions(+)

--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -440,6 +440,9 @@ int __irq_set_trigger(struct irq_desc *d
 		/* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
 		desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
 		desc->status |= flags;
+
+		if (chip != desc->chip)
+			irq_chip_set_defaults(desc->chip);
 	}
 
 	return ret;


Patches currently in stable-queue which might be from tglx@linutronix.de are

queue-2.6.34/genirq-deal-with-desc-set_type-changing-desc-chip.patch
queue-2.6.34/x86-send-a-sigtrap-for-user-icebp-traps.patch

^ 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