[PATCH v2 03/15] ARM: mxs: Add reset routines

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Thu Dec 2 02:27:50 EST 2010


Hi Shawn,

On Thu, Dec 02, 2010 at 02:02:39PM +0800, Shawn Guo wrote:
> Hi Uwe,
> 
> 2010/11/30 Uwe Kleine-König <u.kleine-koenig at pengutronix.de>:
> > Hello,
> >
> [...]
> >
> >> +     /* Poll CLKGATE set */
> >> +     timeout = 0x400;
> >> +     while ((!(__raw_readl(reset_addr) & MXS_MODULE_CLKGATE)) && --timeout)
> >> +             /* nothing */;
> >> +     if (!timeout)
> >> +             goto error;
> >> +
> >> +     /* Clear SFTRST */
> >> +     val = __raw_readl(reset_addr);
> >> +     val &= ~MXS_MODULE_SFTRST;
> >> +     __raw_writel(val, reset_addr);
> >> +     /* Wait 1us */
> >> +     udelay(1);
> >> +     /* Poll SFTRST cleared */
> >> +     timeout = 0x400;
> >> +     while ((__raw_readl(reset_addr) & MXS_MODULE_SFTRST) && --timeout)
> >> +             /* nothing */;
> >> +     if (!timeout)
> >> +             goto error;
> >> +
> >> +     /* Clear CLKGATE */
> >> +     val = __raw_readl(reset_addr);
> >> +     val &= ~MXS_MODULE_CLKGATE;
> >> +     __raw_writel(val, reset_addr);
> >> +     /* Wait 1us */
> >> +     udelay(1);
> >> +     /* Poll CLKGATE cleared */
> >> +     timeout = 0x400;
> >> +     while ((__raw_readl(reset_addr) & MXS_MODULE_CLKGATE) && --timeout)
> >> +             /* nothing */;
> >> +     if (!timeout)
> >> +             goto error;
> >
> > There are quite some repetitions in this function.  If you could get it
> > down to something that looks like
> >
> >        clear SFTRST
> >        udelay
> >        poll SFTRST cleared
> >
> >        clear CLKGATE
> >        set SFTRST
> >        udelay
> >        poll CLKGATE set
> >
> >        clear SFTRST
> >        udelay
> >        poll SFTRST cleared
> >
> >        clear CLKGATE
> >        udelay
> >        poll CLKGATE cleared
> >
> > it's IMHO better than the comment above.  If "clear CLKGATE" and "set
> > SFTRST" can be done in a single step this might be done like that:
> >
> >        /* comment describing setmask_poll */
> >        static int setmask_poll(void __iomem *addr, u32 set, u32 mask,
> >                u32 pollval, u32 pollmask, u32 *curval)
> >        {
> >                int timeout = 0x400;
> >
> >                *curval &= ~mask;
> >                *curval |= set;
> >                __raw_writel(*curval, addr)
> >
> >                /*
> >                 * some nice comment about 1us being a good idea
> >                 */
> >                udelay(1);
> >
> >                do {
> >                        *curval = __raw_readl(addr);
> >                        if ((*curval & pollmask) == pollval)
> >                                return 0;
> >
> >                } while(--timeout);
> >
> >                return 1;
> >        }
> >
> >        int mxs_reset_block(void __iomem *reset_addr)
> >        {
> >                u32 val = __raw_readl(reset_addr);
> >                int ret;
> >
> >                /* clear SFTRST and poll SFTRST becoming clear */
> >                ret = setmask_poll(reset_addr,
> >                        0, MXS_MODULE_SFTRST,
> >                        0, MXS_MODULE_SFTRST, &val);
> >                if (ret)
> >                        goto error;
> >
> >                /* clear CLKGATE, set SFTRST and poll CLKGATE becoming set */
> >                ret = setmask_poll(reset_addr,
> >                        MXS_MODULE_SFTRST, MXS_MODULE_SFTRST | MXS_MODULE_CLKGATE,
> >                        0, MXS_MODULE_CLKGATE, &val);
> >                if (ret)
> >                        goto error;
> >
> >                ...
> >        }
> >
> > Well, not very nice, but IMHO better that your code.  Maybe
> > mxs_reset_block fits in a Terminal that way without decreasing the font
> > size :-)
> >
> I checked designer about doing "clear CLKGATE" and "set SFTRST" in a
> single step, and got the following feedback.
> 
> "Per HW design, it is not safe to get those two done by write once
> time. By two step write, one instruction period interval can be
> ensured at least for clock  enabling before sync. Soft reset.  Your
> code is only once time write in fact, so it shall not be equal to two
> write operation."
> 
> In this case, how do the following changes look to you?
> 
> /*
>  * Clear the bit and poll it cleared, the bit has to be
>  * SFTRST(bit 31) or CLKGATE (bit 30) of block control register.
for the function it doesn't have to be one of these bits.  Maybe:

	Clear the bit and poll it cleared.  This is usually called with
	a reset address and mask being either SFTRST(bit 31) or CLKGATE
	(bit 30).

>  */
> static int clear_poll_bit(void __iomem *addr, u32 mask)
> {
>         int timeout = 0x400;
> 
>         /* clear the bit */
>         __raw_writel(mask, addr + MXS_CLR_ADDR);
ah, so there is a clr register, that's nice.

> 
>         /*
>          * SFTRST needs 3 GPMI clocks to settle, the reference manual
>          * recommends to wait 1us.
>          */
>         udelay(1);
> 
>         /* poll the bit becoming clear */
>         while ((__raw_readl(addr) & mask) && --timeout)
>                 /* nothing */;
> 
>         if (unlikely(!timeout))
>                 return 1;
> 
>         return 0;
return !timeout; ?

> }
> 
> int mxs_reset_block(void __iomem *reset_addr)
> {
>         int ret;
>         int timeout = 0x400;
> 
>         /* clear and poll SFTRST */
>         ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
>         if (ret)
>                 goto error;
> 
>         /* clear CLKGATE */
>         __raw_writel(MXS_MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
>         /* set SFTRST to reset the block */
>         __raw_writel(MXS_MODULE_SFTRST, reset_addr + MXS_SET_ADDR);
>         udelay(1);
>         /* poll CLKGATE becoming set */
>         while ((!(__raw_readl(reset_addr) & MXS_MODULE_CLKGATE)) && --timeout)
>                 /* nothing */;
>         if (unlikely(!timeout))
>                 goto error;
> 
>         /* clear and poll SFTRST */
>         ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
>         if (ret)
>                 goto error;
> 
>         /* clear and poll CLKGATE */
>         ret = clear_poll_bit(reset_addr, MXS_MODULE_CLKGATE);
>         if (ret)
>                 goto error;
> 
	return 0;

> error:
>         pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
>         return -ETIMEDOUT;
> }
Other than that it looks much better IMHO.

Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |



More information about the linux-arm-kernel mailing list