/* * The current mxs_reset_block() will do two things: * [1] enable the module. * [2] reset the module. * * In most of the cases, it's ok. * But in MX23, there is a hardware bug in the BCH block (see erratum #2847). * If you try to soft reset the BCH block, it becomes unusable until * the next hard reset. This case occurs in the NAND boot mode. When the board * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. * So If the driver tries to reset the BCH again, the BCH will not work anymore. * You will see a DMA timeout in this case. The bug has been fixed * in the following chips, such as MX28. * * To avoid this bug, just add a new parameter `just_enable` for * the mxs_reset_block(), and rewrite it here. */ static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) { int ret; int timeout = 0x400; /* clear and poll SFTRST */ ret = clear_poll_bit(reset_addr, MODULE_SFTRST); if (unlikely(ret)) goto error; /* clear CLKGATE */ writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR); if (!just_enable) { /* set SFTRST to reset the block */ writel(MODULE_SFTRST, reset_addr + MXS_SET_ADDR); udelay(1); /* poll CLKGATE becoming set */ while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout) /* nothing */; if (unlikely(!timeout)) goto error; } /* clear and poll SFTRST */ ret = clear_poll_bit(reset_addr, MODULE_SFTRST); if (unlikely(ret)) goto error; /* clear and poll CLKGATE */ ret = clear_poll_bit(reset_addr, MODULE_CLKGATE); if (unlikely(ret)) goto error; return 0; error: pr_err("%s(%p): module reset timeout\n", __func__, reset_addr); return -ETIMEDOUT; }
static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) { int ret; int timeout = 0x400; ret = clear_poll_bit(reset_addr, MODULE_SFTRST); if (unlikely(ret)) goto error; __mxs_clrl(MODULE_CLKGATE, reset_addr); if (!just_enable) { __mxs_setl(MODULE_SFTRST, reset_addr); udelay(1); while ((!(readl(reset_addr) & MODULE_CLKGATE)) && --timeout) ; if (unlikely(!timeout)) goto error; } ret = clear_poll_bit(reset_addr, MODULE_SFTRST); if (unlikely(ret)) goto error; ret = clear_poll_bit(reset_addr, MODULE_CLKGATE); if (unlikely(ret)) goto error; return 0; error: pr_err("%s(%p): module reset timeout\n", __func__, reset_addr); return -ETIMEDOUT; }
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 (unlikely(ret)) goto error; /* clear CLKGATE */ __mxs_clrl(MXS_MODULE_CLKGATE, reset_addr); /* set SFTRST to reset the block */ __mxs_setl(MXS_MODULE_SFTRST, reset_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 (unlikely(ret)) goto error; /* clear and poll CLKGATE */ ret = clear_poll_bit(reset_addr, MXS_MODULE_CLKGATE); if (unlikely(ret)) goto error; return 0; error: pr_err("%s(%p): module reset timeout\n", __func__, reset_addr); return -ETIMEDOUT; }