Commit | Line | Data |
---|---|---|
7c6337e2 KH |
1 | /* |
2 | * TI DaVinci Power and Sleep Controller (PSC) | |
3 | * | |
4 | * Copyright (C) 2006 Texas Instruments. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 | * | |
20 | */ | |
21 | #include <linux/kernel.h> | |
22 | #include <linux/module.h> | |
23 | #include <linux/init.h> | |
24 | ||
25 | #include <asm/io.h> | |
a09e64fb RK |
26 | #include <mach/hardware.h> |
27 | #include <mach/psc.h> | |
28 | #include <mach/mux.h> | |
7c6337e2 | 29 | |
83f53220 VB |
30 | /* PSC register offsets */ |
31 | #define EPCPR 0x070 | |
32 | #define PTCMD 0x120 | |
33 | #define PTSTAT 0x128 | |
34 | #define PDSTAT 0x200 | |
35 | #define PDCTL1 0x304 | |
36 | #define MDSTAT 0x800 | |
37 | #define MDCTL 0xA00 | |
7c6337e2 | 38 | |
83f53220 VB |
39 | /* System control register offsets */ |
40 | #define VDD3P3V_PWDN 0x48 | |
7c6337e2 KH |
41 | |
42 | static void davinci_psc_mux(unsigned int id) | |
43 | { | |
44 | switch (id) { | |
45 | case DAVINCI_LPSC_ATA: | |
83f53220 VB |
46 | davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1); |
47 | davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1); | |
7c6337e2 KH |
48 | break; |
49 | case DAVINCI_LPSC_MMC_SD: | |
50 | /* VDD power manupulations are done in U-Boot for CPMAC | |
51 | * so applies to MMC as well | |
52 | */ | |
53 | /*Set up the pull regiter for MMC */ | |
83f53220 VB |
54 | davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN); |
55 | davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0); | |
7c6337e2 KH |
56 | break; |
57 | case DAVINCI_LPSC_I2C: | |
83f53220 | 58 | davinci_mux_peripheral(DAVINCI_MUX_I2C, 1); |
7c6337e2 KH |
59 | break; |
60 | case DAVINCI_LPSC_McBSP: | |
83f53220 | 61 | davinci_mux_peripheral(DAVINCI_MUX_ASP, 1); |
7c6337e2 KH |
62 | break; |
63 | default: | |
64 | break; | |
65 | } | |
66 | } | |
67 | ||
68 | /* Enable or disable a PSC domain */ | |
69 | void davinci_psc_config(unsigned int domain, unsigned int id, char enable) | |
70 | { | |
83f53220 | 71 | u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; |
7c6337e2 KH |
72 | |
73 | if (id < 0) | |
74 | return; | |
75 | ||
83f53220 | 76 | mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); |
7c6337e2 | 77 | if (enable) |
83f53220 | 78 | mdctl |= 0x00000003; /* Enable Module */ |
7c6337e2 | 79 | else |
83f53220 VB |
80 | mdctl &= 0xFFFFFFF2; /* Disable Module */ |
81 | davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); | |
82 | ||
83 | pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT); | |
84 | if ((pdstat & 0x00000001) == 0) { | |
85 | pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | |
86 | pdctl1 |= 0x1; | |
87 | davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | |
88 | ||
89 | ptcmd = 1 << domain; | |
90 | davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); | |
7c6337e2 | 91 | |
83f53220 VB |
92 | do { |
93 | epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | |
94 | EPCPR); | |
95 | } while ((((epcpr >> domain) & 1) == 0)); | |
7c6337e2 | 96 | |
83f53220 VB |
97 | pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); |
98 | pdctl1 |= 0x100; | |
99 | davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); | |
100 | ||
101 | do { | |
102 | ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | |
103 | PTSTAT); | |
104 | } while (!(((ptstat >> domain) & 1) == 0)); | |
7c6337e2 | 105 | } else { |
83f53220 VB |
106 | ptcmd = 1 << domain; |
107 | davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); | |
108 | ||
109 | do { | |
110 | ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | |
111 | PTSTAT); | |
112 | } while (!(((ptstat >> domain) & 1) == 0)); | |
7c6337e2 KH |
113 | } |
114 | ||
115 | if (enable) | |
83f53220 | 116 | mdstat_mask = 0x3; |
7c6337e2 | 117 | else |
83f53220 VB |
118 | mdstat_mask = 0x2; |
119 | ||
120 | do { | |
121 | mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + | |
122 | MDSTAT + 4 * id); | |
123 | } while (!((mdstat & 0x0000001F) == mdstat_mask)); | |
7c6337e2 KH |
124 | |
125 | if (enable) | |
126 | davinci_psc_mux(id); | |
127 | } | |
128 | ||
129 | void __init davinci_psc_init(void) | |
130 | { | |
131 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1); | |
132 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1); | |
133 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1); | |
134 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1); | |
135 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1); | |
136 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1); | |
137 | ||
138 | /* Turn on WatchDog timer LPSC. Needed for RESET to work */ | |
139 | davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1); | |
140 | } |