/* * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include void (*machine_arch_reset) (char mode, const char *cmd); void arch_idle(void) { cpu_do_idle(); } void arch_reset(char mode, const char *cmd) { if (machine_arch_reset) machine_arch_reset(mode, cmd); else { void *base = IO_ADDRESS(RTC_PHYS_ADDR); __raw_writel(1, base + HW_RTC_WATCHDOG); __raw_writel(0x80000000, base + HW_RTC_PERSISTENT1_SET); __raw_writel(BM_RTC_CTRL_WATCHDOGEN, base + HW_RTC_CTRL_SET); } cpu_reset(0); } static int __mxs_reset_block(void __iomem *hwreg, int just_enable) { u32 c; int timeout; /* the process of software reset of IP block is done in several steps: - clear SFTRST and wait for block is enabled; - clear clock gating (CLKGATE bit); - set the SFTRST again and wait for block is in reset; - clear SFTRST and wait for reset completion. */ c = __raw_readl(hwreg); c &= ~(1 << 31); /* clear SFTRST */ __raw_writel(c, hwreg); for (timeout = 1000000; timeout > 0; timeout--) /* still in SFTRST state ? */ if ((__raw_readl(hwreg) & (1 << 31)) == 0) break; if (timeout <= 0) { printk(KERN_ERR "%s(%p): timeout when enabling\n", __func__, hwreg); return -ETIME; } c = __raw_readl(hwreg); c &= ~(1 << 30); /* clear CLKGATE */ __raw_writel(c, hwreg); if (!just_enable) { c = __raw_readl(hwreg); c |= (1 << 31); /* now again set SFTRST */ __raw_writel(c, hwreg); for (timeout = 1000000; timeout > 0; timeout--) /* poll until CLKGATE set */ if (__raw_readl(hwreg) & (1 << 30)) break; if (timeout <= 0) { printk(KERN_ERR "%s(%p): timeout when resetting\n", __func__, hwreg); return -ETIME; } c = __raw_readl(hwreg); c &= ~(1 << 31); /* clear SFTRST */ __raw_writel(c, hwreg); for (timeout = 1000000; timeout > 0; timeout--) /* still in SFTRST state ? */ if ((__raw_readl(hwreg) & (1 << 31)) == 0) break; if (timeout <= 0) { printk(KERN_ERR "%s(%p): timeout when enabling " "after reset\n", __func__, hwreg); return -ETIME; } c = __raw_readl(hwreg); c &= ~(1 << 30); /* clear CLKGATE */ __raw_writel(c, hwreg); } for (timeout = 1000000; timeout > 0; timeout--) /* still in SFTRST state ? */ if ((__raw_readl(hwreg) & (1 << 30)) == 0) break; if (timeout <= 0) { printk(KERN_ERR "%s(%p): timeout when unclockgating\n", __func__, hwreg); return -ETIME; } return 0; } int mxs_reset_block(void __iomem *hwreg, int just_enable) { int try = 10; int r; while (try--) { r = __mxs_reset_block(hwreg, just_enable); if (!r) break; pr_debug("%s: try %d failed\n", __func__, 10 - try); } return r; }