On 10/30/2013 04:06 AM, Peter Chen wrote: > According to Freescale imx28 Errata, "ENGR119653 USB: ARM to USB > register error issue", All USB register write operations must > use the ARM SWP instruction. So, we implement special hw_write > and hw_test_and_clear for imx28. > > Discussion for it at below: > http://marc.info/?l=linux-usb&m=137996395529294&w=2 > > Signed-off-by: Peter Chen <[email protected]> > --- > Changes for v4: > - introducing __hw_write to encapsulate low level write, > it can reduce the duplicated code. > > drivers/usb/chipidea/ci.h | 26 ++++++++++++++++++++++++-- > drivers/usb/chipidea/core.c | 2 ++ > drivers/usb/chipidea/host.c | 1 + > include/linux/usb/chipidea.h | 1 + > 4 files changed, 28 insertions(+), 2 deletions(-) > > diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h > index 1c94fc5..f9b1914 100644 > --- a/drivers/usb/chipidea/ci.h > +++ b/drivers/usb/chipidea/ci.h > @@ -173,6 +173,8 @@ struct ci_hdrc { > struct dentry *debugfs; > bool id_event; > bool b_sess_valid_event; > + /* imx28 needs swp instruction for writing */ > + bool imx28_write_fix; > }; > > static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) > @@ -253,6 +255,26 @@ static inline u32 hw_read(struct ci_hdrc *ci, enum > ci_hw_regs reg, u32 mask) > return ioread32(ci->hw_bank.regmap[reg]) & mask; > } > > +#ifdef CONFIG_SOC_IMX28 > +static inline void imx28_ci_writel(u32 val32, volatile u32 *addr)
same applies here:
static inline void imx28_ci_writel(u32 val32, void __iomem *addr)
Marc
> +{
> + __asm__ ("swp %0, %0, [%1]" : : "r"(val32), "r"(addr));
> +}
> +#endif
> +
> +static inline void __hw_write(struct ci_hdrc *ci, u32 val,
> + void __iomem *addr)
> +{
> +#ifdef CONFIG_SOC_IMX28
> + if (ci->imx28_write_fix)
> + imx28_ci_writel(val, addr);
> + else
> + iowrite32(val, addr);
> +#else
> + iowrite32(val, addr);
> +#endif
> +}
> +
> /**
> * hw_write: writes to a hw register
> * @reg: register index
> @@ -266,7 +288,7 @@ static inline void hw_write(struct ci_hdrc *ci, enum
> ci_hw_regs reg,
> data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask)
> | (data & mask);
>
> - iowrite32(data, ci->hw_bank.regmap[reg]);
> + __hw_write(ci, data, ci->hw_bank.regmap[reg]);
> }
>
> /**
> @@ -281,7 +303,7 @@ static inline u32 hw_test_and_clear(struct ci_hdrc *ci,
> enum ci_hw_regs reg,
> {
> u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask;
>
> - iowrite32(val, ci->hw_bank.regmap[reg]);
> + __hw_write(ci, val, ci->hw_bank.regmap[reg]);
> return val;
> }
>
> diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> index 06204b7..357a059 100644
> --- a/drivers/usb/chipidea/core.c
> +++ b/drivers/usb/chipidea/core.c
> @@ -551,6 +551,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
>
> ci->dev = dev;
> ci->platdata = dev->platform_data;
> + ci->imx28_write_fix = !!(ci->platdata->flags &
> + CI_HDRC_IMX28_WRITE_FIX);
>
> ret = hw_device_init(ci, base);
> if (ret < 0) {
> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> index 59e6020..06fd042 100644
> --- a/drivers/usb/chipidea/host.c
> +++ b/drivers/usb/chipidea/host.c
> @@ -65,6 +65,7 @@ static int host_start(struct ci_hdrc *ci)
> ehci->caps = ci->hw_bank.cap;
> ehci->has_hostpc = ci->hw_bank.lpm;
> ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
> + ehci->imx28_write_fix = ci->imx28_write_fix;
>
> if (ci->platdata->reg_vbus) {
> ret = regulator_enable(ci->platdata->reg_vbus);
> diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
> index 7d39967..708bd11 100644
> --- a/include/linux/usb/chipidea.h
> +++ b/include/linux/usb/chipidea.h
> @@ -24,6 +24,7 @@ struct ci_hdrc_platform_data {
> * but otg is not supported (no register otgsc).
> */
> #define CI_HDRC_DUAL_ROLE_NOT_OTG BIT(4)
> +#define CI_HDRC_IMX28_WRITE_FIX BIT(5)
> enum usb_dr_mode dr_mode;
> #define CI_HDRC_CONTROLLER_RESET_EVENT 0
> #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
>
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
signature.asc
Description: OpenPGP digital signature
