* 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", ®, 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", ®, 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
* Re: [PATCH 04/11] powerpc: Simplify update_vsyscall
From: Paul Mackerras @ 2010-07-27 23:41 UTC (permalink / raw)
To: John Stultz
Cc: linuxppc-dev, Thomas Gleixner, Ingo Molnar, LKML, Anton Blanchard
In-Reply-To: <1279068988-21864-5-git-send-email-johnstul@us.ibm.com>
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.
BTW, BenH's tree is at:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
Paul.
^ permalink raw reply
* mpc512x_dma hangs when used from multiple threads
From: Ilya Yanok @ 2010-07-27 23:01 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Piotr Ziecik
Hello Piotr, everybody,
I've found that mpc512x_dma channels hang sometimes while accessed from
more than one thread simultaneously.
The easiest way to reproduce this error I've managed to found is using
dmatest module with rather high threads_per_chan value (20 should be
enough):
-bash-3.2# insmod dmatest.ko max_channels=1 iterations=1 threads_per_chan=20
[ 32.559568] dma0chan0-copy0: terminating after 1 tests, 0 failures
(status 0)
-bash-3.2# [ 35.553688] dma0chan0-copy1: #0: test timed out
[ 35.558207] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.565458] dma0chan0-copy1: #0: test timed out
[ 35.569968] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.577219] dma0chan0-copy1: #0: test timed out
[ 35.581735] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.588953] dma0chan0-copy2: #0: test timed out
[ 35.593502] dma0chan0-copy2: terminating after 1 tests, 1 failures
(status 0)
[ 35.600720] dma0chan0-copy3: #0: test timed out
[ 35.605284] dma0chan0-copy3: terminating after 1 tests, 1 failures
(status 0)
[ 35.612472] dma0chan0-copy4: #0: test timed out
[ 35.617052] dma0chan0-copy4: terminating after 1 tests, 1 failures
(status 0)
[ 35.624381] dma0chan0-copy5: #0: test timed out
[ 35.628895] dma0chan0-copy5: terminating after 1 tests, 1 failures
(status 0)
[ 35.636126] dma0chan0-copy6: #0: test timed out
[ 35.640657] dma0chan0-copy6: terminating after 1 tests, 1 failures
(status 0)
[ 35.647876] dma0chan0-copy7: #0: test timed out
[ 35.652425] dma0chan0-copy7: terminating after 1 tests, 1 failures
(status 0)
[ 35.659643] dma0chan0-copy8: #0: test timed out
[ 35.664209] dma0chan0-copy8: terminating after 1 tests, 1 failures
(status 0)
[ 35.671395] dma0chan0-copy9: #0: test timed out
[ 35.675976] dma0chan0-copy9: terminating after 1 tests, 1 failures
(status 0)
[ 35.683164] dma0chan0-copy1: #0: test timed out
[ 35.687743] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.694942] dma0chan0-copy1: #0: test timed out
[ 35.699495] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.706714] dma0chan0-copy1: #0: test timed out
[ 35.711264] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.719826] dma0chan0-copy1: #0: test timed out
[ 35.724404] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.731549] dma0chan0-copy1: #0: test timed out
[ 35.736131] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.744247] dma0chan0-copy1: #0: test timed out
[ 35.748778] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.756768] dma0chan0-copy1: #0: test timed out
[ 35.761301] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
[ 35.769306] dma0chan0-copy1: #0: test timed out
[ 35.773883] dma0chan0-copy1: terminating after 1 tests, 1 failures
(status 0)
Also, this can be reproduced using more than one channel at once (in
this case some of channels eventually hang). With max_channels=1 and
threads_per_chan=1 dmatest works fine so I think this should be a
synchronization issue.
After the hang, channel becomes unusable and cannot be even freed...
Is it a known problem? Maybe there exists some fix or workaround for it?
Regards, Ilya.
^ permalink raw reply
* [PATCH v4 2/2] powerpc/mpc5121: add initial support for PDM360NG board
From: Anatolij Gustschin @ 2010-07-27 21:26 UTC (permalink / raw)
To: linuxppc-dev
Cc: Detlev Zundel, Markus Fischer, devicetree-discuss, Michael Weiss,
Anatolij Gustschin, Wolfgang Grandegger
In-Reply-To: <1279892973-24110-1-git-send-email-agust@denx.de>
Adds IFM PDM360NG device tree and platform code.
Currently following is supported:
- Spansion S29GL512P 256 MB NOR flash
- ST Micro NAND 1 GiB flash
- DIU, please use "fbcon=map:5 video=fslfb:800x480-32@60"
at the kernel command line to enable PrimeView PM070WL3
Display support.
- FEC
- I2C
- RTC, EEPROM
- MSCAN
- PSC UART, please pass "console=tty0 console=ttyPSC5,115200"
on the kernel command line.
- SPI, ADS7845 Touchscreen
- USB0/1 Host
- USB0 OTG Host/Device
- VIU, Overlay/Capture support
Signed-off-by: Markus Fischer <markus.fischer.ec@ifm.com>
Signed-off-by: Wolfgang Grandegger <wg@denx.de>
Signed-off-by: Michael Weiss <michael.weiss@ifm.com>
Signed-off-by: Detlev Zundel <dzu@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: Grant Likely <grant.likely@secretlab.ca>
---
v4:
- set interrupt-parent in root node only, less verbose DT
- add compatible property to phy node
- update touch screen controller node (add reg and
spi-max-frequency properties)
- drop unnecessary (u32 *) casts
- change return statement in pdm360ng_get_pendown_state()
as suggested
- use correct error codes (-ENODEV) when returning on errors
- use of_iomap() to eliminate some code
- rework pdm360ng_touchscreen_init() to only use bus notifier
for addition of platform data for touch screen driver
- eliminate machine_device_initcall(), code moved to init
callback
v3:
- uncomment and correct .irq_flags field of touchscreen
platform data struct as proposed extension to this
data struct has been accepted and merged via input tree
a short while ago
v1 -> v2:
- fix interrupt-parent property in nfc node
- drop #address-cells in ipic node
- remove device_type from ethernet-phy sub-node
- remove device_type from ethernet node
- add aliases node for eth0, needed for MAC address
update by U-Boot
- removed spaces around &ipic
arch/powerpc/boot/dts/pdm360ng.dts | 410 ++++++++++++++++++++++++++++++++
arch/powerpc/platforms/512x/Kconfig | 7 +
arch/powerpc/platforms/512x/Makefile | 1 +
arch/powerpc/platforms/512x/pdm360ng.c | 129 ++++++++++
4 files changed, 547 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/boot/dts/pdm360ng.dts
create mode 100644 arch/powerpc/platforms/512x/pdm360ng.c
diff --git a/arch/powerpc/boot/dts/pdm360ng.dts b/arch/powerpc/boot/dts/pdm360ng.dts
new file mode 100644
index 0000000..94dfa5c
--- /dev/null
+++ b/arch/powerpc/boot/dts/pdm360ng.dts
@@ -0,0 +1,410 @@
+/*
+ * Device Tree Source for IFM PDM360NG.
+ *
+ * Copyright 2009 - 2010 DENX Software Engineering.
+ * Anatolij Gustschin <agust@denx.de>
+ *
+ * Based on MPC5121E ADS dts.
+ * Copyright 2008 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "pdm360ng";
+ compatible = "ifm,pdm360ng";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&ipic>;
+
+ aliases {
+ ethernet0 = ð0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,5121@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <0x20>; // 32 bytes
+ i-cache-line-size = <0x20>; // 32 bytes
+ d-cache-size = <0x8000>; // L1, 32K
+ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <49500000>;// 49.5 MHz (csb/4)
+ bus-frequency = <198000000>; // 198 MHz csb bus
+ clock-frequency = <396000000>; // 396 MHz ppc core
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x20000000>; // 512MB at 0
+ };
+
+ nfc@40000000 {
+ compatible = "fsl,mpc5121-nfc";
+ reg = <0x40000000 0x100000>;
+ interrupts = <0x6 0x8>;
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ bank-width = <0x1>;
+ chips = <0x1>;
+
+ partition@0 {
+ label = "nand0";
+ reg = <0x0 0x40000000>;
+ };
+ };
+
+ sram@50000000 {
+ compatible = "fsl,mpc5121-sram";
+ reg = <0x50000000 0x20000>; // 128K at 0x50000000
+ };
+
+ localbus@80000020 {
+ compatible = "fsl,mpc5121-localbus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ reg = <0x80000020 0x40>;
+
+ ranges = <0x0 0x0 0xf0000000 0x10000000 /* Flash */
+ 0x2 0x0 0x50040000 0x00020000>; /* CS2: MRAM */
+
+ flash@0,0 {
+ compatible = "amd,s29gl01gp", "cfi-flash";
+ reg = <0 0x00000000 0x08000000
+ 0 0x08000000 0x08000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ bank-width = <4>;
+ device-width = <2>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x00000000 0x00080000>;
+ read-only;
+ };
+ partition@80000 {
+ label = "environment";
+ reg = <0x00080000 0x00080000>;
+ read-only;
+ };
+ partition@100000 {
+ label = "splash-image";
+ reg = <0x00100000 0x00080000>;
+ read-only;
+ };
+ partition@180000 {
+ label = "device-tree";
+ reg = <0x00180000 0x00040000>;
+ };
+ partition@1c0000 {
+ label = "kernel";
+ reg = <0x001c0000 0x00500000>;
+ };
+ partition@6c0000 {
+ label = "filesystem";
+ reg = <0x006c0000 0x07940000>;
+ };
+ };
+
+ mram0@2,0 {
+ compatible = "mtd-ram";
+ reg = <2 0x00000 0x10000>;
+ bank-width = <2>;
+ };
+
+ mram1@2,10000 {
+ compatible = "mtd-ram";
+ reg = <2 0x010000 0x10000>;
+ bank-width = <2>;
+ };
+ };
+
+ soc@80000000 {
+ compatible = "fsl,mpc5121-immr";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <2>;
+ ranges = <0x0 0x80000000 0x400000>;
+ reg = <0x80000000 0x400000>;
+ bus-frequency = <66000000>; // 66 MHz ips bus
+
+ // IPIC
+ // interrupts cell = <intr #, sense>
+ // sense values match linux IORESOURCE_IRQ_* defines:
+ // sense == 8: Level, low assertion
+ // sense == 2: Edge, high-to-low change
+ //
+ ipic: interrupt-controller@c00 {
+ compatible = "fsl,mpc5121-ipic", "fsl,ipic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <2>;
+ reg = <0xc00 0x100>;
+ };
+
+ rtc@a00 { // Real time clock
+ compatible = "fsl,mpc5121-rtc";
+ reg = <0xa00 0x100>;
+ interrupts = <79 0x8 80 0x8>;
+ };
+
+ reset@e00 { // Reset module
+ compatible = "fsl,mpc5121-reset";
+ reg = <0xe00 0x100>;
+ };
+
+ clock@f00 { // Clock control
+ compatible = "fsl,mpc5121-clock";
+ reg = <0xf00 0x100>;
+ };
+
+ pmc@1000{ //Power Management Controller
+ compatible = "fsl,mpc5121-pmc";
+ reg = <0x1000 0x100>;
+ interrupts = <83 0x2>;
+ };
+
+ gpio@1100 {
+ compatible = "fsl,mpc5121-gpio";
+ reg = <0x1100 0x100>;
+ interrupts = <78 0x8>;
+ };
+
+ can@1300 {
+ compatible = "fsl,mpc5121-mscan";
+ interrupts = <12 0x8>;
+ reg = <0x1300 0x80>;
+ };
+
+ can@1380 {
+ compatible = "fsl,mpc5121-mscan";
+ interrupts = <13 0x8>;
+ reg = <0x1380 0x80>;
+ };
+
+ i2c@1700 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5121-i2c";
+ reg = <0x1700 0x20>;
+ interrupts = <0x9 0x8>;
+ fsl,preserve-clocking;
+
+ eeprom@50 {
+ compatible = "at,24c01";
+ reg = <0x50>;
+ };
+
+ rtc@68 {
+ compatible = "stm,m41t00";
+ reg = <0x68>;
+ };
+ };
+
+ i2c@1740 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5121-i2c";
+ reg = <0x1740 0x20>;
+ interrupts = <0xb 0x8>;
+ fsl,preserve-clocking;
+ };
+
+ i2ccontrol@1760 {
+ compatible = "fsl,mpc5121-i2c-ctrl";
+ reg = <0x1760 0x8>;
+ };
+
+ axe@2000 {
+ compatible = "fsl,mpc5121-axe";
+ reg = <0x2000 0x100>;
+ interrupts = <42 0x8>;
+ };
+
+ display@2100 {
+ compatible = "fsl,mpc5121-diu";
+ reg = <0x2100 0x100>;
+ interrupts = <64 0x8>;
+ };
+
+ can@2300 {
+ compatible = "fsl,mpc5121-mscan";
+ interrupts = <90 0x8>;
+ reg = <0x2300 0x80>;
+ };
+
+ can@2380 {
+ compatible = "fsl,mpc5121-mscan";
+ interrupts = <91 0x8>;
+ reg = <0x2380 0x80>;
+ };
+
+ viu@2400 {
+ compatible = "fsl,mpc5121-viu";
+ reg = <0x2400 0x400>;
+ interrupts = <67 0x8>;
+ };
+
+ mdio@2800 {
+ compatible = "fsl,mpc5121-fec-mdio";
+ reg = <0x2800 0x200>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ phy: ethernet-phy@0 {
+ compatible = "smsc,lan8700";
+ reg = <0x1f>;
+ };
+ };
+
+ eth0: ethernet@2800 {
+ compatible = "fsl,mpc5121-fec";
+ reg = <0x2800 0x200>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <4 0x8>;
+ phy-handle = < &phy >;
+ };
+
+ // USB1 using external ULPI PHY
+ usb@3000 {
+ compatible = "fsl,mpc5121-usb2-dr";
+ reg = <0x3000 0x600>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <43 0x8>;
+ dr_mode = "host";
+ phy_type = "ulpi";
+ };
+
+ // USB0 using internal UTMI PHY
+ usb@4000 {
+ compatible = "fsl,mpc5121-usb2-dr";
+ reg = <0x4000 0x600>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <44 0x8>;
+ dr_mode = "otg";
+ phy_type = "utmi_wide";
+ fsl,invert-pwr-fault;
+ };
+
+ // IO control
+ ioctl@a000 {
+ compatible = "fsl,mpc5121-ioctl";
+ reg = <0xA000 0x1000>;
+ };
+
+ // 512x PSCs are not 52xx PSCs compatible
+ serial@11000 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <0>;
+ reg = <0x11000 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ serial@11100 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <1>;
+ reg = <0x11100 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ serial@11200 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <2>;
+ reg = <0x11200 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ serial@11300 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <3>;
+ reg = <0x11300 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ serial@11400 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <4>;
+ reg = <0x11400 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ serial@11600 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <6>;
+ reg = <0x11600 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ serial@11800 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <8>;
+ reg = <0x11800 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ serial@11B00 {
+ compatible = "fsl,mpc5121-psc-uart", "fsl,mpc5121-psc";
+ cell-index = <11>;
+ reg = <0x11B00 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+ };
+
+ pscfifo@11f00 {
+ compatible = "fsl,mpc5121-psc-fifo";
+ reg = <0x11f00 0x100>;
+ interrupts = <40 0x8>;
+ };
+
+ spi@11900 {
+ compatible = "fsl,mpc5121-psc-spi", "fsl,mpc5121-psc";
+ cell-index = <9>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x11900 0x100>;
+ interrupts = <40 0x8>;
+ fsl,rx-fifo-size = <16>;
+ fsl,tx-fifo-size = <16>;
+
+ // 7845 touch screen controller
+ ts@0 {
+ compatible = "ti,ads7846";
+ reg = <0x0>;
+ spi-max-frequency = <3000000>;
+ // pen irq is GPIO25
+ interrupts = <78 0x8>;
+ };
+ };
+
+ dma@14000 {
+ compatible = "fsl,mpc5121-dma";
+ reg = <0x14000 0x1800>;
+ interrupts = <65 0x8>;
+ };
+ };
+};
diff --git a/arch/powerpc/platforms/512x/Kconfig b/arch/powerpc/platforms/512x/Kconfig
index e9dca28..27b0651 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -25,3 +25,10 @@ config MPC5121_GENERIC
Compatible boards include: Protonic LVT base boards (ZANMCU
and VICVT2).
+
+config PDM360NG
+ bool "ifm PDM360NG board"
+ depends on PPC_MPC512x
+ select DEFAULT_UIMAGE
+ help
+ This option enables support for the PDM360NG board.
diff --git a/arch/powerpc/platforms/512x/Makefile b/arch/powerpc/platforms/512x/Makefile
index 90be2f5..4efc1c4 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -4,3 +4,4 @@
obj-y += clock.o mpc512x_shared.o
obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o
obj-$(CONFIG_MPC5121_GENERIC) += mpc5121_generic.o
+obj-$(CONFIG_PDM360NG) += pdm360ng.o
diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c
new file mode 100644
index 0000000..1eb8b0f
--- /dev/null
+++ b/arch/powerpc/platforms/512x/pdm360ng.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 DENX Software Engineering
+ *
+ * Anatolij Gustschin, <agust@denx.de>
+ *
+ * PDM360NG board setup
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+
+#include "mpc512x.h"
+
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
+ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+#include <linux/interrupt.h>
+#include <linux/spi/ads7846.h>
+#include <linux/spi/spi.h>
+#include <linux/notifier.h>
+
+static void *pdm360ng_gpio_base;
+
+static int pdm360ng_get_pendown_state(void)
+{
+ u32 reg;
+
+ reg = in_be32(pdm360ng_gpio_base + 0xc);
+ if (reg & 0x40)
+ setbits32(pdm360ng_gpio_base + 0xc, 0x40);
+
+ reg = in_be32(pdm360ng_gpio_base + 0x8);
+
+ /* return 1 if pen is down */
+ return (reg & 0x40) == 0;
+}
+
+static struct ads7846_platform_data pdm360ng_ads7846_pdata = {
+ .model = 7845,
+ .get_pendown_state = pdm360ng_get_pendown_state,
+ .irq_flags = IRQF_TRIGGER_LOW,
+};
+
+static int __init pdm360ng_penirq_init(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-gpio");
+ if (!np) {
+ pr_err("%s: Can't find 'mpc5121-gpio' node\n", __func__);
+ return -ENODEV;
+ }
+
+ pdm360ng_gpio_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!pdm360ng_gpio_base) {
+ pr_err("%s: Can't map gpio regs.\n", __func__);
+ return -ENODEV;
+ }
+ out_be32(pdm360ng_gpio_base + 0xc, 0xffffffff);
+ setbits32(pdm360ng_gpio_base + 0x18, 0x2000);
+ setbits32(pdm360ng_gpio_base + 0x10, 0x40);
+
+ return 0;
+}
+
+static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *__dev)
+{
+ struct device *dev = __dev;
+
+ if ((event == BUS_NOTIFY_ADD_DEVICE) &&
+ of_device_is_compatible(dev->of_node, "ti,ads7846")) {
+ dev->platform_data = &pdm360ng_ads7846_pdata;
+ return NOTIFY_OK;
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block pdm360ng_touchscreen_nb = {
+ .notifier_call = pdm360ng_touchscreen_notifier_call,
+};
+
+static void __init pdm360ng_touchscreen_init(void)
+{
+ if (pdm360ng_penirq_init())
+ return;
+
+ bus_register_notifier(&spi_bus_type, &pdm360ng_touchscreen_nb);
+}
+#else
+static inline void __init pdm360ng_touchscreen_init(void)
+{
+}
+#endif /* CONFIG_TOUCHSCREEN_ADS7846 */
+
+void __init pdm360ng_init(void)
+{
+ mpc512x_init();
+ pdm360ng_touchscreen_init();
+}
+
+static int __init pdm360ng_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ return of_flat_dt_is_compatible(root, "ifm,pdm360ng");
+}
+
+define_machine(pdm360ng) {
+ .name = "PDM360NG",
+ .probe = pdm360ng_probe,
+ .setup_arch = mpc512x_setup_diu,
+ .init = pdm360ng_init,
+ .init_early = mpc512x_init_diu,
+ .init_IRQ = mpc512x_init_IRQ,
+ .get_irq = ipic_get_irq,
+ .calibrate_decr = generic_calibrate_decr,
+ .restart = mpc512x_restart,
+};
--
1.7.0.4
^ permalink raw reply related
* [PATCH] xilinxfb: update tft comp versions
From: Adrian Alonso @ 2010-07-27 21:24 UTC (permalink / raw)
To: linuxppc-dev; +Cc: devicetree-discuss, Adrian Alonso
* Add tft display module compatibility for new
hardware modules
Signed-off-by: Adrian Alonso <aalonso00@gmail.com>
---
drivers/video/xilinxfb.c | 2 ++
1 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_device *op)
/* Match table for of_platform binding */
static struct of_device_id xilinxfb_of_match[] __devinitdata = {
{ .compatible = "xlnx,xps-tft-1.00.a", },
+ { .compatible = "xlnx,xps-tft-2.00.a", },
+ { .compatible = "xlnx,xps-tft-2.01.a", },
{ .compatible = "xlnx,plb-tft-cntlr-ref-1.00.a", },
{ .compatible = "xlnx,plb-dvi-cntlr-ref-1.00.c", },
{},
--
1.7.2
^ permalink raw reply related
* Re: [Patch v2] kexec: increase max of kexec segments and use dynamic allocation
From: Eric W. Biederman @ 2010-07-27 18:24 UTC (permalink / raw)
To: Milton Miller
Cc: Neil Horman, WANG Cong, Neil Horman, huang ying, linux-kernel,
kexec, linuxppc-dev
In-Reply-To: <kexec-nrseg-reply1@mdm.bga.com>
Milton Miller <miltonm@bga.com> writes:
> [ Added kexec at lists.infradead.org and linuxppc-dev@lists.ozlabs.org ]
>
>>
>> Currently KEXEC_SEGMENT_MAX is only 16 which is too small for machine with
>> many memory ranges. When hibernate on a machine with disjoint memory we do
>> need one segment for each memory region. Increase this hard limit to 16K
>> which is reasonably large.
>>
>> And change ->segment from a static array to a dynamically allocated memory.
>>
>> Cc: Neil Horman <nhorman@redhat.com>
>> Cc: huang ying <huang.ying.caritas@gmail.com>
>> Cc: Eric W. Biederman <ebiederm@xmission.com>
>> Signed-off-by: WANG Cong <amwang@redhat.com>
>>
>> ---
>> diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
>> index ed31a29..f115585 100644
>> --- a/arch/powerpc/kernel/machine_kexec_64.c
>> +++ b/arch/powerpc/kernel/machine_kexec_64.c
>> @@ -131,10 +131,7 @@ static void copy_segments(unsigned long ind)
>> void kexec_copy_flush(struct kimage *image)
>> {
>> long i, nr_segments = image->nr_segments;
>> - struct kexec_segment ranges[KEXEC_SEGMENT_MAX];
>> -
>> - /* save the ranges on the stack to efficiently flush the icache */
>> - memcpy(ranges, image->segment, sizeof(ranges));
>> + struct kexec_segment range;
>
> I'm glad you found our copy on the stack and removed the stack overflow
> that comes with this bump, but ...
>
>>
>> /*
>> * After this call we may not use anything allocated in dynamic
>> @@ -148,9 +145,11 @@ void kexec_copy_flush(struct kimage *image)
>> * we need to clear the icache for all dest pages sometime,
>> * including ones that were in place on the original copy
>> */
>> - for (i = 0; i < nr_segments; i++)
>> - flush_icache_range((unsigned long)__va(ranges[i].mem),
>> - (unsigned long)__va(ranges[i].mem + ranges[i].memsz));
>> + for (i = 0; i < nr_segments; i++) {
>> + memcpy(&range, &image->segment[i], sizeof(range));
>> + flush_icache_range((unsigned long)__va(range.mem),
>> + (unsigned long)__va(range.mem + range.memsz));
>> + }
>> }
>
> This is executed after the copy, so as it says,
> "we may not use anything allocated in dynamic memory".
>
> We could allocate control pages to copy the segment list into.
> Actually ppc64 doesn't use the existing control page, but that
> is only 4kB today.
>
> We need the list to icache flush all the pages in all the segments.
> The as the indirect list doesn't have pages that were allocated at
> their destination.
An interesting point.
> Or maybe the icache flush should be done in the generic code
> like it does for crash load segments?
Please. I don't quite understand the icache flush requirement.
But we really should not be looking at the segments in the
architecture specific code.
Ideally we would only keep the segment information around for
the duration of the kexec_load syscall and not have it when
it comes time to start the second kernel.
I am puzzled. We should be completely replacing the page tables so
can't we just do a global flush? Perhaps I am being naive about what
is required for a ppc flush.
Eric
^ permalink raw reply
* Re: [PATCH 3/6] of/spi: add support to parse the SPI flash's partitions
From: Grant Likely @ 2010-07-27 19:24 UTC (permalink / raw)
To: Hu Mingkai-B21284; +Cc: linuxppc-dev, spi-devel-general, Zang Roy-R61911
In-Reply-To: <73839B4A0818E747864426270AC332C305400687@zmy16exm20.fsl.freescale.net>
[cc'ing spi-devel-general]
On Mon, Jul 26, 2010 at 2:20 AM, Hu Mingkai-B21284 <B21284@freescale.com> w=
rote:
>
>
>> -----Original Message-----
>> From: glikely@secretlab.ca [mailto:glikely@secretlab.ca] On
>> Behalf Of Grant Likely
>> Sent: Monday, July 26, 2010 3:53 PM
>> To: Hu Mingkai-B21284
>> Cc: linuxppc-dev@ozlabs.org; galak@kernel.crashing.org; Zang
>> Roy-R61911
>> Subject: Re: [PATCH 3/6] of/spi: add support to parse the SPI
>> flash's partitions
>>
>> On Mon, Jul 26, 2010 at 1:25 AM, Hu Mingkai-B21284
>> <B21284@freescale.com> wrote:
>> >
>> >
>> >> -----Original Message-----
>> >> From: Grant Likely [mailto:glikely@secretlab.ca] On Behalf
>> Of Grant
>> >> Likely
>> >> Sent: Monday, July 26, 2010 8:28 AM
>> >> To: Hu Mingkai-B21284
>> >> Cc: linuxppc-dev@ozlabs.org; galak@kernel.crashing.org; Zang
>> >> Roy-R61911
>> >> Subject: Re: [PATCH 3/6] of/spi: add support to parse the
>> SPI flash's
>> >> partitions
>> >>
>> >> On Tue, Jul 20, 2010 at 10:08:22AM +0800, Mingkai Hu wrote:
>> >> > Signed-off-by: Mingkai Hu <Mingkai.hu@freescale.com>
>> >> > ---
>> >> > =A0drivers/of/of_spi.c =A0 =A0 =A0 | =A0 11 +++++++++++
>> >> > =A0drivers/spi/spi_mpc8xxx.c | =A0 =A01 +
>> >> > =A02 files changed, 12 insertions(+), 0 deletions(-)
>> >> >
>> >> > diff --git a/drivers/of/of_spi.c b/drivers/of/of_spi.c index
>> >> > 5fed7e3..284ca0e 100644
>> >> > --- a/drivers/of/of_spi.c
>> >> > +++ b/drivers/of/of_spi.c
>> >> > @@ -10,6 +10,8 @@
>> >> > =A0#include <linux/device.h>
>> >> > =A0#include <linux/spi/spi.h>
>> >> > =A0#include <linux/of_spi.h>
>> >> > +#include <linux/spi/flash.h>
>> >> > +#include <linux/mtd/partitions.h>
>> >> >
>> >> > =A0/**
>> >> > =A0 * of_register_spi_devices - Register child devices onto
>> >> the SPI bus
>> >> > @@ -26,6 +28,7 @@ void of_register_spi_devices(struct
>> >> spi_master *master, struct device_node *np)
>> >> > =A0 =A0 const __be32 *prop;
>> >> > =A0 =A0 int rc;
>> >> > =A0 =A0 int len;
>> >> > + =A0 struct flash_platform_data *pdata;
>> >> >
>> >> > =A0 =A0 for_each_child_of_node(np, nc) {
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 /* Alloc an spi_device */ @@ -81,6 +84,14 @=
@ void
>> >> > of_register_spi_devices(struct
>> >> spi_master *master, struct device_node *np)
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 of_node_get(nc);
>> >> > =A0 =A0 =A0 =A0 =A0 =A0 spi->dev.of_node =3D nc;
>> >> >
>> >> > + =A0 =A0 =A0 =A0 =A0 /* Parse the mtd partitions */
>> >> > + =A0 =A0 =A0 =A0 =A0 pdata =3D kzalloc(sizeof(*pdata), GFP_KERNEL)=
;
>> >> > + =A0 =A0 =A0 =A0 =A0 if (!pdata)
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
>> >> > + =A0 =A0 =A0 =A0 =A0 pdata->nr_parts =3D
>> of_mtd_parse_partitions(&master->dev,
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 nc, &pdata->p=
arts);
>> >> > + =A0 =A0 =A0 =A0 =A0 spi->dev.platform_data =3D pdata;
>> >> > +
>> >>
>> >> Nack. =A0Not all spi devices are mtd devices. =A0In fact, most are no=
t.
>> >>
>> >> The spi driver itself should call the
>> of_mtd_parse_partitions code to
>> >> get the partition map. =A0Do not use pdata in this case.
>> >>
>> >
>> > Yes, we can call of_mtd_parse_partitions to get the
>> partiton map, but
>> > how can we pass this map to spi device to register to MTD layer?
>> >
>> > The spi device is created and registered when call
>> > of_register_spi_device in the spi controller probe
>> function, then the
>> > spi device will traverse the spi device driver list to find
>> the proper
>> > driver, if matched, then call the spi device driver probe
>> code where
>> > the mtd partition info is registered to the mtd layer.
>> >
>> > so where is the proper place to put the
>> of_mtd_parse_partitions code?
>>
>> In the device driver probe code.
>>
>
> This is the way that I did at first, thus we need to add the same code
> in all the spi flash driver to get partition map info.
>
> or we add the get partition map code to of_spi.c?
No, it really does not belong in of_spi.c because the spi code has no
knowledge about MTD devices.
I only see two valid options, to either:
a) add it to each MTD driver, or
b) add a hook to the core MTD code so that if an of_node pointer is
provided, and no partition data is provided, then it will parse the
partitions when the MTD device is registered. You'd also need to code
it in a way that becomes a no-op when CONFIG_OF is not set.
>
> +/*
> + * of_parse_flash_partition - Parse the flash partition on the SPI bus
> + * @spi: =A0 =A0 =A0 Pointer to spi_device device
> + */
> +void of_parse_flash_partition(struct spi_device *spi)
> +{
> + =A0 =A0 =A0 struct mtd_partition *parts;
> + =A0 =A0 =A0 struct flash_platform_data *spi_pdata;
> + =A0 =A0 =A0 int nr_parts =3D 0;
> + =A0 =A0 =A0 static int num_flash;
> + =A0 =A0 =A0 struct device_node *np =3D spi->dev.archdata.of_node;
> +
> + =A0 =A0 =A0 nr_parts =3D of_mtd_parse_partitions(&spi->dev, np, &parts)=
;
> + =A0 =A0 =A0 if (!nr_parts)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto end;
> +
> + =A0 =A0 =A0 spi_pdata =3D kzalloc(sizeof(*spi_pdata), GFP_KERNEL);
> + =A0 =A0 =A0 if (!spi_pdata)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto end;
> + =A0 =A0 =A0 spi_pdata->name =3D kzalloc(10, GFP_KERNEL);
> + =A0 =A0 =A0 if (!spi_pdata->name)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto free_flash;
> + =A0 =A0 =A0 snprintf(spi_pdata->name, 10, "SPIFLASH%d", num_flash++);
> +
> + =A0 =A0 =A0 spi_pdata->parts =3D parts;
> + =A0 =A0 =A0 spi_pdata->nr_parts =3D nr_parts;
> +
> + =A0 =A0 =A0 spi->dev.platform_data =3D spi_pdata;
> +
> + =A0 =A0 =A0 return;
> +
> +free_flash:
> + =A0 =A0 =A0 kfree(spi_pdata);
> +end:
> + =A0 =A0 =A0 return;
> +}
>
>
>> >> > diff --git a/drivers/spi/spi_mpc8xxx.c
>> b/drivers/spi/spi_mpc8xxx.c
>> >> > index efed70e..0fadaeb 100644
>> >> > --- a/drivers/spi/spi_mpc8xxx.c
>> >> > +++ b/drivers/spi/spi_mpc8xxx.c
>> >> > @@ -137,6 +137,7 @@ int mpc8xxx_spi_transfer(struct spi_device
>> >> > *spi,
>> >> >
>> >> > =A0void mpc8xxx_spi_cleanup(struct spi_device *spi) =A0{
>> >> > + =A0 kfree(spi->dev.platform_data);
>> >>
>> >> Irrelevant given the above comment, but how does this even work?
>> >> What if a driver was detached and reattached to an
>> spi_device? =A0The
>> >> platform_data would be freed. =A0Not to mention that the
>> pointer isn't
>> >> cleared, so the driver would have no idea that it has a freed
>> >> pointer.
>> >>
>> >
>> > It works. If the driver detached, the spi device
>> platform_data will be
>> > released, when reattached, the of_register_spi_devices will
>> be called
>> > again, the platform_data will be allocated.
>>
>> Ah right, I wasn't looking in the right place. =A0On that note
>> however, the cleanup of spi_device allocated by the OF code
>> should also have a reciprocal helper that frees them too. =A0It
>> shouldn't be done in the individual drivers.
>>
>
> We can define a helper to free the platform_data, but where it should be =
called?
> Maybe spidev_release is a better place to call, after all the platfrom_da=
ta is allocated
> when the spi device is created, so it should be freed when released.
It would be called from the spi core code. However, with two options
I gave above, platform_data shouldn't be needed at all.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [PATCH v3 2/2] powerpc/mpc5121: add initial support for PDM360NG board
From: Grant Likely @ 2010-07-27 17:43 UTC (permalink / raw)
To: Anatolij Gustschin
Cc: Detlev Zundel, Markus Fischer, devicetree-discuss, Michael Weiss,
linuxppc-dev, Wolfgang Grandegger
In-Reply-To: <20100727192856.63edc8e0@wker>
On Tue, Jul 27, 2010 at 11:28 AM, Anatolij Gustschin <agust@denx.de> wrote:
> On Tue, 27 Jul 2010 10:58:33 -0600
> Grant Likely <grant.likely@secretlab.ca> wrote:
> ...
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spi@11900 {
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,m=
pc5121-psc-spi", "fsl,mpc5121-psc";
>> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cell-index =3D <9>;
>> >>
>> >> Try to drop the cell-index properties. =A0They are almost always misu=
sed.
>> >
>> > Removing cell-index would require changing the spi driver's probe.
>> > Currently cell-index is used to set spi bus number. What could be used
>> > for bus enumeration instead? Is it okay to use part of the spi node
>> > address? e.g. obtaining the offset 0x11900, masking out the unrelated
>> > bits and shifting by 8 would deliver unique index 9 for PSC9 in SPI
>> > mode. This would work for all 12 PSC SPI controllers of mpc5121.
>>
>> Does the spi bus number really matter? =A0The device tree context gives
>> you a firm association between spi masters and devices which doesn't
>> require assigning a specific bus number. =A0The core spi code can
>> dynamically assign a bus number for the bus by setting bus_num to -1.
>
> The bus number is used in the mpc5121 psc spi driver to obtain correct
> clock for PSC in question (0 to 11) and to enable the PSC clock at probe
> time. Therefore using dynamically assigned bus number would require anoth=
er
> change to the spi driver.
That's unrelated to the bus number. Use cell-index value directly for
obtaining the clock if you need to; but limit its exposure. Once
Jeremy gets his common clock architecture merged, then we could
probably migrate to that for obtaining the correct clock without
cell-index.
g.
^ permalink raw reply
* Re: [PATCH v3 2/2] powerpc/mpc5121: add initial support for PDM360NG board
From: Anatolij Gustschin @ 2010-07-27 17:28 UTC (permalink / raw)
To: Grant Likely
Cc: Detlev Zundel, Markus Fischer, devicetree-discuss, Michael Weiss,
linuxppc-dev, Wolfgang Grandegger
In-Reply-To: <AANLkTika=KeKcaY_FF8tN5Fy-H+cozjZsGObXoQhKiVh@mail.gmail.com>
On Tue, 27 Jul 2010 10:58:33 -0600
Grant Likely <grant.likely@secretlab.ca> wrote:
...
> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spi@11900 {
> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,mp=
c5121-psc-spi", "fsl,mpc5121-psc";
> >> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cell-index =3D <9>;
> >>
> >> Try to drop the cell-index properties. =A0They are almost always misus=
ed.
> >
> > Removing cell-index would require changing the spi driver's probe.
> > Currently cell-index is used to set spi bus number. What could be used
> > for bus enumeration instead? Is it okay to use part of the spi node
> > address? e.g. obtaining the offset 0x11900, masking out the unrelated
> > bits and shifting by 8 would deliver unique index 9 for PSC9 in SPI
> > mode. This would work for all 12 PSC SPI controllers of mpc5121.
>=20
> Does the spi bus number really matter? The device tree context gives
> you a firm association between spi masters and devices which doesn't
> require assigning a specific bus number. The core spi code can
> dynamically assign a bus number for the bus by setting bus_num to -1.
The bus number is used in the mpc5121 psc spi driver to obtain correct
clock for PSC in question (0 to 11) and to enable the PSC clock at probe
time. Therefore using dynamically assigned bus number would require another
change to the spi driver.
...
> > This requires fixing the mpc5121 psc spi driver to create spi child
> > nodes of the spi master node. I have already send the appropriate
> > patch to spi-devel list, but it is not the right approach to call
> > of_register_spi_devices() in each driver.
>=20
> It's not wrong; but it isn't ideal either.
>=20
> > Do you plan to fix it in
> > core spi code in v2.6.36?
>=20
> Apparently I no longer have to because you've gone ahead and done it
> for me anyway. :-) I'll take a look at that patch and send you my
> comments.
Okay, thanks,
Anatolij
^ permalink raw reply
* Re: [PATCH v3 2/2] powerpc/mpc5121: add initial support for PDM360NG board
From: Grant Likely @ 2010-07-27 16:58 UTC (permalink / raw)
To: Anatolij Gustschin
Cc: Detlev Zundel, Markus Fischer, devicetree-discuss, Michael Weiss,
linuxppc-dev, Wolfgang Grandegger
In-Reply-To: <20100727123647.0a3b8832@wker>
On Tue, Jul 27, 2010 at 4:36 AM, Anatolij Gustschin <agust@denx.de> wrote:
> Hi Grant,
>
> On Sun, 25 Jul 2010 01:42:23 -0600
> Grant Likely <grant.likely@secretlab.ca> wrote:
> ...
>> Hi Anatolij,
>>
>> Finally got some time tonight to properly dig into this patch. =A0Commen=
ts below.
>
> Thanks for review and comments! My reply below.
Thanks Anatolij, replies below.
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 spi@11900 {
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 compatible =3D "fsl,mpc5=
121-psc-spi", "fsl,mpc5121-psc";
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cell-index =3D <9>;
>>
>> Try to drop the cell-index properties. =A0They are almost always misused=
.
>
> Removing cell-index would require changing the spi driver's probe.
> Currently cell-index is used to set spi bus number. What could be used
> for bus enumeration instead? Is it okay to use part of the spi node
> address? e.g. obtaining the offset 0x11900, masking out the unrelated
> bits and shifting by 8 would deliver unique index 9 for PSC9 in SPI
> mode. This would work for all 12 PSC SPI controllers of mpc5121.
Does the spi bus number really matter? The device tree context gives
you a firm association between spi masters and devices which doesn't
require assigning a specific bus number. The core spi code can
dynamically assign a bus number for the bus by setting bus_num to -1.
>> > +
>> > + =A0 =A0 =A0 if (bus_num < 0 || bus_num > 11)
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
>> > +
>> > + =A0 =A0 =A0 info.bus_num =3D bus_num;
>> > +
>> > + =A0 =A0 =A0 of_dev =3D of_find_device_by_node(np);
>> > + =A0 =A0 =A0 of_node_put(np);
>> > + =A0 =A0 =A0 if (of_dev) {
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct fsl_spi_platform_data *pdata;
>> > +
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata =3D kzalloc(sizeof(*pdata), GFP_KE=
RNEL);
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (pdata) {
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->bus_num =3D bus_n=
um;
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 pdata->max_chipselect =
=3D 1;
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 of_dev->dev.platform_dat=
a =3D pdata;
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> > + =A0 =A0 =A0 }
>> > +
>> > + =A0 =A0 =A0 if (pdm360ng_penirq_init())
>> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENODEV;
>> > +
>> > + =A0 =A0 =A0 return spi_register_board_info(&info, 1);
>>
>> This ends up being a lot of code simply to attach a pdata structure to
>> an spi device. =A0I've been thinking about this problem, and I think
>> there is a better way. =A0Instead, use a bus notifier attached to the
>> SPI bus to wait for the spi_device to get registered, but before it
>> gets bound to a driver. =A0Then you can attach the pdata structure very
>> simply. =A0Something like this I think (completely untested, or even
>> compiled. =A0Details are left as an exercise to the developer):
>>
>> static int pdm360ng_touchscreen_notifier_call(struct notifier_block *nb,
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 unsigned long event, void *__dev)
>> {
>> =A0 =A0 =A0 struct device *dev =3D __dev;
>>
>> =A0 =A0 =A0 if ((event =3D=3D BUS_NOTIFIY_ADD_DEVICE) && (dev->of_node =
=3D=3D [FOO]))
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 dev->platform_data =3D [BAR];
>> }
>>
>> static struct notifier_block pdm360ng_touchscreen_nb =3D {
>> =A0 =A0 =A0 notifier_call =3D pdm360ng_touchscreen_notifier_call;
>> };
>>
>> static int __init pdm360ng_touchscreen_init(void)
>> {
>> =A0 =A0 =A0 bus_register_notifier(&spi_bus_type, pdm360ng_touchscreen_nb=
);
>> }
>
> Thanks! Bus notifier is now used for setting platform data in v4.
Cool!
> This requires fixing the mpc5121 psc spi driver to create spi child
> nodes of the spi master node. I have already send the appropriate
> patch to spi-devel list, but it is not the right approach to call
> of_register_spi_devices() in each driver.
It's not wrong; but it isn't ideal either.
> Do you plan to fix it in
> core spi code in v2.6.36?
Apparently I no longer have to because you've gone ahead and done it
for me anyway. :-) I'll take a look at that patch and send you my
comments.
Cheers,
g.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox