[PATCH] [RFC][ARM] pxa: rework pxa3xx-ulpi driver calls for ohci-pxa27x

Igor Grinberg grinberg at compulab.co.il
Mon Sep 20 10:48:30 EDT 2010


 ping

On 09/07/10 17:14, Igor Grinberg wrote:
> This patch reworks Marek's quick fix for pxa3xx-u2d crash when ULPI not
> used by:
> 1) Introducing the struct u2d_hc_ops for start/stop the U2DC Host mode.
> 2) Enabling the Host functionality only when ULPI is used.
>
> Signed-off-by: Igor Grinberg <grinberg at compulab.co.il>
> ---
>  arch/arm/mach-pxa/cm-x300.c                 |    1 +
>  arch/arm/mach-pxa/include/mach/ohci.h       |    2 +
>  arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h |   12 +++--
>  arch/arm/mach-pxa/pxa3xx-ulpi.c             |   66 +++++++++++++++++++--------
>  drivers/usb/host/ohci-pxa27x.c              |    8 ++--
>  5 files changed, 62 insertions(+), 27 deletions(-)
>
> diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
> index 8e0b562..952b475 100644
> --- a/arch/arm/mach-pxa/cm-x300.c
> +++ b/arch/arm/mach-pxa/cm-x300.c
> @@ -566,6 +566,7 @@ static struct pxaohci_platform_data cm_x300_ohci_platform_data = {
>  
>  static void __init cm_x300_init_ohci(void)
>  {
> +	cm_x300_ohci_platform_data.u2d_hc_ops = pxa3xx_get_u2d_hc_ops();
>  	pxa_set_ohci_info(&cm_x300_ohci_platform_data);
>  }
>  #else
> diff --git a/arch/arm/mach-pxa/include/mach/ohci.h b/arch/arm/mach-pxa/include/mach/ohci.h
> index 95b6e2a..0924e26 100644
> --- a/arch/arm/mach-pxa/include/mach/ohci.h
> +++ b/arch/arm/mach-pxa/include/mach/ohci.h
> @@ -29,6 +29,8 @@ struct pxaohci_platform_data {
>  #define PMM_PERPORT_MODE       3
>  
>  	int power_budget;
> +
> +	struct pxa3xx_u2d_hc_ops *u2d_hc_ops;
>  };
>  
>  extern void pxa_set_ohci_info(struct pxaohci_platform_data *info);
> diff --git a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
> index 9d82cb6..6f37f43 100644
> --- a/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
> +++ b/arch/arm/mach-pxa/include/mach/pxa3xx-u2d.h
> @@ -25,10 +25,14 @@ struct pxa3xx_u2d_platform_data {
>  };
>  
>  
> -/* Start PXA3xx U2D host */
> -int pxa3xx_u2d_start_hc(struct usb_bus *host);
> -/* Stop PXA3xx U2D host */
> -void pxa3xx_u2d_stop_hc(struct usb_bus *host);
> +struct pxa3xx_u2d_hc_ops {
> +	/* Start PXA3xx U2D host */
> +	int (*start_hc)(struct usb_bus *host);
> +	/* Stop PXA3xx U2D host */
> +	void (*stop_hc)(struct usb_bus *host);
> +};
> +
> +struct pxa3xx_u2d_hc_ops *pxa3xx_get_u2d_hc_ops(void);
>  
>  extern void pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info);
>  
> diff --git a/arch/arm/mach-pxa/pxa3xx-ulpi.c b/arch/arm/mach-pxa/pxa3xx-ulpi.c
> index ce7168b..7e76cbe 100644
> --- a/arch/arm/mach-pxa/pxa3xx-ulpi.c
> +++ b/arch/arm/mach-pxa/pxa3xx-ulpi.c
> @@ -234,27 +234,18 @@ static void pxa310_otg_exit(void)
>  {
>  	kfree(u2d->otg);
>  }
> -#else
> -static inline void pxa310_u2d_setup_otg_hc(void) {}
> -static inline int pxa310_start_otg_hc(struct usb_bus *host)
> -{
> -	return 0;
> -}
> -static inline void pxa310_stop_otg_hc(void) {}
> -static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
> -{
> -	return 0;
> -}
> -static inline void pxa310_otg_exit(void) {}
> -#endif /* CONFIG_PXA310_ULPI */
>  
> -int pxa3xx_u2d_start_hc(struct usb_bus *host)
> +static int pxa3xx_u2d_start_hc(struct usb_bus *host)
>  {
>  	int err = 0;
>  
> -	/* In case the PXA3xx ULPI isn't used, do nothing. */
> -	if (!u2d)
> +	if (!u2d) {
> +		pr_err("%s: Error: u2d struct is not initialized! "
> +		       "ULPI enabed, but pxa3xx-u2d device not registered?",
> +		       __func__);
> +
>  		return 0;
> +	}
>  
>  	clk_enable(u2d->clk);
>  
> @@ -266,11 +257,15 @@ int pxa3xx_u2d_start_hc(struct usb_bus *host)
>  	return err;
>  }
>  
> -void pxa3xx_u2d_stop_hc(struct usb_bus *host)
> +static void pxa3xx_u2d_stop_hc(struct usb_bus *host)
>  {
> -	/* In case the PXA3xx ULPI isn't used, do nothing. */
> -	if (!u2d)
> +	if (!u2d) {
> +		pr_err("%s: Error: u2d struct is not initialized! "
> +		       "ULPI enabed, but pxa3xx-u2d device not registered?",
> +		       __func__);
> +
>  		return;
> +	}
>  
>  	if (cpu_is_pxa310())
>  		pxa310_stop_otg_hc();
> @@ -278,6 +273,39 @@ void pxa3xx_u2d_stop_hc(struct usb_bus *host)
>  	clk_disable(u2d->clk);
>  }
>  
> +static struct pxa3xx_u2d_hc_ops u2d_hc_ops = {
> +	.start_hc	= pxa3xx_u2d_start_hc,
> +	.stop_hc	= pxa3xx_u2d_stop_hc,
> +};
> +
> +struct pxa3xx_u2d_hc_ops *pxa3xx_get_u2d_hc_ops(void)
> +{
> +	return &u2d_hc_ops;
> +}
> +#else
> +static inline void pxa310_u2d_setup_otg_hc(void) {}
> +static inline int pxa310_start_otg_hc(struct usb_bus *host)
> +{
> +	return 0;
> +}
> +static inline void pxa310_stop_otg_hc(void) {}
> +static inline int pxa310_otg_init(struct pxa3xx_u2d_platform_data *pdata)
> +{
> +	return 0;
> +}
> +static inline void pxa310_otg_exit(void) {}
> +static inline int pxa3xx_u2d_start_hc(struct usb_bus *host)
> +{
> +	return 0;
> +}
> +static inline void pxa3xx_u2d_stop_hc(struct usb_bus *host) {}
> +
> +struct pxa3xx_u2d_hc_ops *pxa3xx_get_u2d_hc_ops(void)
> +{
> +	return NULL;
> +}
> +#endif /* CONFIG_PXA310_ULPI */
> +
>  static int pxa3xx_u2d_probe(struct platform_device *pdev)
>  {
>  	struct pxa3xx_u2d_platform_data *pdata = pdev->dev.platform_data;
> diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
> index afef7b0..61ff775 100644
> --- a/drivers/usb/host/ohci-pxa27x.c
> +++ b/drivers/usb/host/ohci-pxa27x.c
> @@ -236,8 +236,8 @@ static int pxa27x_start_hc(struct pxa27x_ohci *ohci, struct device *dev)
>  	if (retval < 0)
>  		return retval;
>  
> -	if (cpu_is_pxa3xx())
> -		pxa3xx_u2d_start_hc(&ohci_to_hcd(&ohci->ohci)->self);
> +	if (cpu_is_pxa3xx() && inf->u2d_hc_ops)
> +		inf->u2d_hc_ops->start_hc(&ohci_to_hcd(&ohci->ohci)->self);
>  
>  	uhchr = __raw_readl(ohci->mmio_base + UHCHR) & ~UHCHR_SSE;
>  	__raw_writel(uhchr, ohci->mmio_base + UHCHR);
> @@ -255,8 +255,8 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev)
>  
>  	inf = dev->platform_data;
>  
> -	if (cpu_is_pxa3xx())
> -		pxa3xx_u2d_stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
> +	if (cpu_is_pxa3xx() && inf->u2d_hc_ops)
> +		inf->u2d_hc_ops->stop_hc(&ohci_to_hcd(&ohci->ohci)->self);
>  
>  	if (inf->exit)
>  		inf->exit(dev);

-- 
Regards,
Igor.




More information about the linux-arm-kernel mailing list