summaryrefslogtreecommitdiff
path: root/arch/arm/plat-stmp3xxx/core.c
blob: 2d358f58c238df59c9df0cc7214016f7a5f42067 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Freescale STMP37XX/STMP378X core routines
 *
 * Embedded Alley Solutions, Inc <source@embeddedalley.com>
 *
 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>

#include <mach/stmp3xxx.h>
#include <mach/platform.h>
#include <mach/dma.h>
#include <mach/regs-clkctrl.h>
#include <mach/regs-rtc.h>
#include <mach/system.h>

static int __stmp3xxx_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 stmp3xxx_reset_block(void __iomem *hwreg, int just_enable)
{
	int try = 10;
	int r;

	while (try--) {
		r = __stmp3xxx_reset_block(hwreg, just_enable);
		if (!r)
			break;
		pr_debug("%s: try %d failed\n", __func__, 10 - try);
	}
	return r;
}
EXPORT_SYMBOL(stmp3xxx_reset_block);

static void stmp3xxx_machine_restart(char mode, const char *cmd)
{
	arch_reset(mode, cmd);
	printk(KERN_ERR"stmp3xxx_machine_restart failed -- System halted\n");
	for (;;)
		continue;
}

void __init stmp3xxx_init(void)
{
	/* Re-route machine restart to our own handler */
	arm_pm_restart = stmp3xxx_machine_restart;

	stmp3xxx_dma_init();

	stmp3xxx_setl(BM_RTC_PERSISTENT0_XTAL32KHZ_PWRUP |
				BM_RTC_PERSISTENT0_XTAL24MHZ_PWRUP,
				REGS_RTC_BASE + HW_RTC_PERSISTENT0);
}