diff options
author | Robby Cai <R63905@freescale.com> | 2010-01-20 20:35:12 +0800 |
---|---|---|
committer | Alejandro Gonzalez <alex.gonzalez@digi.com> | 2010-05-25 11:09:56 +0200 |
commit | 460880faa9e2b08a336b35840664e2d7fdc019cb (patch) | |
tree | bc574dd84f1337850d525199f62ae411700b44e8 /arch/arm/plat-mxs/core.c | |
parent | ebeb7921233812989c7c779921b98a7742bb99a0 (diff) |
ENGR00117720-1 MX28: Add MSL codes to support MX28EVK
Add the MSL codes(New Framework) for MX28,
including clock, gpio, pinctrl, interrupt, timer, DMA, etc.
Signed-off-by: Fred Fan <r01011@freescale.com>
Signed-off-by: Robby Cai <R63905@freescale.com>
Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'arch/arm/plat-mxs/core.c')
-rw-r--r-- | arch/arm/plat-mxs/core.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/arch/arm/plat-mxs/core.c b/arch/arm/plat-mxs/core.c new file mode 100644 index 000000000000..7f91808e6c66 --- /dev/null +++ b/arch/arm/plat-mxs/core.c @@ -0,0 +1,126 @@ +/* + * 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 <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/err.h> + +#include <asm/proc-fns.h> + +static 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); +} + +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; +} |