diff options
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r-- | arch/arm/mach-omap2/board-apollon.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.c | 146 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock.h | 20 | ||||
-rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 180 | ||||
-rw-r--r-- | arch/arm/mach-omap2/irq.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-omap2/mux.c | 14 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prcm.c | 10 |
7 files changed, 336 insertions, 53 deletions
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c index 7993b7bae2bd..2db6b732b084 100644 --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c | |||
@@ -166,8 +166,8 @@ static struct omap_uart_config apollon_uart_config __initdata = { | |||
166 | 166 | ||
167 | static struct omap_mmc_config apollon_mmc_config __initdata = { | 167 | static struct omap_mmc_config apollon_mmc_config __initdata = { |
168 | .mmc [0] = { | 168 | .mmc [0] = { |
169 | .enabled = 0, | 169 | .enabled = 1, |
170 | .wire4 = 0, | 170 | .wire4 = 1, |
171 | .wp_pin = -1, | 171 | .wp_pin = -1, |
172 | .power_pin = -1, | 172 | .power_pin = -1, |
173 | .switch_pin = -1, | 173 | .switch_pin = -1, |
@@ -257,6 +257,9 @@ static void __init omap_apollon_init(void) | |||
257 | /* REVISIT: where's the correct place */ | 257 | /* REVISIT: where's the correct place */ |
258 | omap_cfg_reg(W19_24XX_SYS_NIRQ); | 258 | omap_cfg_reg(W19_24XX_SYS_NIRQ); |
259 | 259 | ||
260 | /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */ | ||
261 | CONTROL_DEVCONF |= (1 << 24); | ||
262 | |||
260 | /* | 263 | /* |
261 | * Make sure the serial ports are muxed on at this point. | 264 | * Make sure the serial ports are muxed on at this point. |
262 | * You have to mux them off in device drivers later on | 265 | * You have to mux them off in device drivers later on |
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index d1b648a4efbf..0de201c3d50b 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c | |||
@@ -32,10 +32,14 @@ | |||
32 | #include "memory.h" | 32 | #include "memory.h" |
33 | #include "clock.h" | 33 | #include "clock.h" |
34 | 34 | ||
35 | #undef DEBUG | ||
36 | |||
35 | //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ | 37 | //#define DOWN_VARIABLE_DPLL 1 /* Experimental */ |
36 | 38 | ||
37 | static struct prcm_config *curr_prcm_set; | 39 | static struct prcm_config *curr_prcm_set; |
38 | static u32 curr_perf_level = PRCM_FULL_SPEED; | 40 | static u32 curr_perf_level = PRCM_FULL_SPEED; |
41 | static struct clk *vclk; | ||
42 | static struct clk *sclk; | ||
39 | 43 | ||
40 | /*------------------------------------------------------------------------- | 44 | /*------------------------------------------------------------------------- |
41 | * Omap2 specific clock functions | 45 | * Omap2 specific clock functions |
@@ -79,6 +83,14 @@ static void omap2_propagate_rate(struct clk * clk) | |||
79 | propagate_rate(clk); | 83 | propagate_rate(clk); |
80 | } | 84 | } |
81 | 85 | ||
86 | static void omap2_set_osc_ck(int enable) | ||
87 | { | ||
88 | if (enable) | ||
89 | PRCM_CLKSRC_CTRL &= ~(0x3 << 3); | ||
90 | else | ||
91 | PRCM_CLKSRC_CTRL |= 0x3 << 3; | ||
92 | } | ||
93 | |||
82 | /* Enable an APLL if off */ | 94 | /* Enable an APLL if off */ |
83 | static void omap2_clk_fixed_enable(struct clk *clk) | 95 | static void omap2_clk_fixed_enable(struct clk *clk) |
84 | { | 96 | { |
@@ -101,12 +113,54 @@ static void omap2_clk_fixed_enable(struct clk *clk) | |||
101 | else if (clk == &apll54_ck) | 113 | else if (clk == &apll54_ck) |
102 | cval = (1 << 6); | 114 | cval = (1 << 6); |
103 | 115 | ||
104 | while (!CM_IDLEST_CKGEN & cval) { /* Wait for lock */ | 116 | while (!(CM_IDLEST_CKGEN & cval)) { /* Wait for lock */ |
105 | ++i; | 117 | ++i; |
106 | udelay(1); | 118 | udelay(1); |
107 | if (i == 100000) | 119 | if (i == 100000) { |
120 | printk(KERN_ERR "Clock %s didn't lock\n", clk->name); | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void omap2_clk_wait_ready(struct clk *clk) | ||
127 | { | ||
128 | unsigned long reg, other_reg, st_reg; | ||
129 | u32 bit; | ||
130 | int i; | ||
131 | |||
132 | reg = (unsigned long) clk->enable_reg; | ||
133 | if (reg == (unsigned long) &CM_FCLKEN1_CORE || | ||
134 | reg == (unsigned long) &CM_FCLKEN2_CORE) | ||
135 | other_reg = (reg & ~0xf0) | 0x10; | ||
136 | else if (reg == (unsigned long) &CM_ICLKEN1_CORE || | ||
137 | reg == (unsigned long) &CM_ICLKEN2_CORE) | ||
138 | other_reg = (reg & ~0xf0) | 0x00; | ||
139 | else | ||
140 | return; | ||
141 | |||
142 | /* No check for DSS or cam clocks */ | ||
143 | if ((reg & 0x0f) == 0) { | ||
144 | if (clk->enable_bit <= 1 || clk->enable_bit == 31) | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | /* Check if both functional and interface clocks | ||
149 | * are running. */ | ||
150 | bit = 1 << clk->enable_bit; | ||
151 | if (!(__raw_readl(other_reg) & bit)) | ||
152 | return; | ||
153 | st_reg = (other_reg & ~0xf0) | 0x20; | ||
154 | i = 0; | ||
155 | while (!(__raw_readl(st_reg) & bit)) { | ||
156 | i++; | ||
157 | if (i == 100000) { | ||
158 | printk(KERN_ERR "Timeout enabling clock %s\n", clk->name); | ||
108 | break; | 159 | break; |
160 | } | ||
109 | } | 161 | } |
162 | if (i) | ||
163 | pr_debug("Clock %s stable after %d loops\n", clk->name, i); | ||
110 | } | 164 | } |
111 | 165 | ||
112 | /* Enables clock without considering parent dependencies or use count | 166 | /* Enables clock without considering parent dependencies or use count |
@@ -119,6 +173,11 @@ static int _omap2_clk_enable(struct clk * clk) | |||
119 | if (clk->flags & ALWAYS_ENABLED) | 173 | if (clk->flags & ALWAYS_ENABLED) |
120 | return 0; | 174 | return 0; |
121 | 175 | ||
176 | if (unlikely(clk == &osc_ck)) { | ||
177 | omap2_set_osc_ck(1); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
122 | if (unlikely(clk->enable_reg == 0)) { | 181 | if (unlikely(clk->enable_reg == 0)) { |
123 | printk(KERN_ERR "clock.c: Enable for %s without enable code\n", | 182 | printk(KERN_ERR "clock.c: Enable for %s without enable code\n", |
124 | clk->name); | 183 | clk->name); |
@@ -133,6 +192,9 @@ static int _omap2_clk_enable(struct clk * clk) | |||
133 | regval32 = __raw_readl(clk->enable_reg); | 192 | regval32 = __raw_readl(clk->enable_reg); |
134 | regval32 |= (1 << clk->enable_bit); | 193 | regval32 |= (1 << clk->enable_bit); |
135 | __raw_writel(regval32, clk->enable_reg); | 194 | __raw_writel(regval32, clk->enable_reg); |
195 | wmb(); | ||
196 | |||
197 | omap2_clk_wait_ready(clk); | ||
136 | 198 | ||
137 | return 0; | 199 | return 0; |
138 | } | 200 | } |
@@ -155,6 +217,11 @@ static void _omap2_clk_disable(struct clk *clk) | |||
155 | { | 217 | { |
156 | u32 regval32; | 218 | u32 regval32; |
157 | 219 | ||
220 | if (unlikely(clk == &osc_ck)) { | ||
221 | omap2_set_osc_ck(0); | ||
222 | return; | ||
223 | } | ||
224 | |||
158 | if (clk->enable_reg == 0) | 225 | if (clk->enable_reg == 0) |
159 | return; | 226 | return; |
160 | 227 | ||
@@ -166,6 +233,7 @@ static void _omap2_clk_disable(struct clk *clk) | |||
166 | regval32 = __raw_readl(clk->enable_reg); | 233 | regval32 = __raw_readl(clk->enable_reg); |
167 | regval32 &= ~(1 << clk->enable_bit); | 234 | regval32 &= ~(1 << clk->enable_bit); |
168 | __raw_writel(regval32, clk->enable_reg); | 235 | __raw_writel(regval32, clk->enable_reg); |
236 | wmb(); | ||
169 | } | 237 | } |
170 | 238 | ||
171 | static int omap2_clk_enable(struct clk *clk) | 239 | static int omap2_clk_enable(struct clk *clk) |
@@ -695,12 +763,14 @@ static int omap2_clk_set_rate(struct clk *clk, unsigned long rate) | |||
695 | reg_val = __raw_readl(reg); | 763 | reg_val = __raw_readl(reg); |
696 | reg_val &= ~(field_mask << div_off); | 764 | reg_val &= ~(field_mask << div_off); |
697 | reg_val |= (field_val << div_off); | 765 | reg_val |= (field_val << div_off); |
698 | |||
699 | __raw_writel(reg_val, reg); | 766 | __raw_writel(reg_val, reg); |
767 | wmb(); | ||
700 | clk->rate = clk->parent->rate / field_val; | 768 | clk->rate = clk->parent->rate / field_val; |
701 | 769 | ||
702 | if (clk->flags & DELAYED_APP) | 770 | if (clk->flags & DELAYED_APP) { |
703 | __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); | 771 | __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); |
772 | wmb(); | ||
773 | } | ||
704 | ret = 0; | 774 | ret = 0; |
705 | } else if (clk->set_rate != 0) | 775 | } else if (clk->set_rate != 0) |
706 | ret = clk->set_rate(clk, rate); | 776 | ret = clk->set_rate(clk, rate); |
@@ -836,10 +906,12 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) | |||
836 | reg_val = __raw_readl(reg) & ~(field_mask << src_off); | 906 | reg_val = __raw_readl(reg) & ~(field_mask << src_off); |
837 | reg_val |= (field_val << src_off); | 907 | reg_val |= (field_val << src_off); |
838 | __raw_writel(reg_val, reg); | 908 | __raw_writel(reg_val, reg); |
909 | wmb(); | ||
839 | 910 | ||
840 | if (clk->flags & DELAYED_APP) | 911 | if (clk->flags & DELAYED_APP) { |
841 | __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); | 912 | __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); |
842 | 913 | wmb(); | |
914 | } | ||
843 | if (clk->usecount > 0) | 915 | if (clk->usecount > 0) |
844 | _omap2_clk_enable(clk); | 916 | _omap2_clk_enable(clk); |
845 | 917 | ||
@@ -953,12 +1025,29 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate) | |||
953 | * Omap2 clock reset and init functions | 1025 | * Omap2 clock reset and init functions |
954 | *-------------------------------------------------------------------------*/ | 1026 | *-------------------------------------------------------------------------*/ |
955 | 1027 | ||
1028 | #ifdef CONFIG_OMAP_RESET_CLOCKS | ||
1029 | static void __init omap2_clk_disable_unused(struct clk *clk) | ||
1030 | { | ||
1031 | u32 regval32; | ||
1032 | |||
1033 | regval32 = __raw_readl(clk->enable_reg); | ||
1034 | if ((regval32 & (1 << clk->enable_bit)) == 0) | ||
1035 | return; | ||
1036 | |||
1037 | printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name); | ||
1038 | _omap2_clk_disable(clk); | ||
1039 | } | ||
1040 | #else | ||
1041 | #define omap2_clk_disable_unused NULL | ||
1042 | #endif | ||
1043 | |||
956 | static struct clk_functions omap2_clk_functions = { | 1044 | static struct clk_functions omap2_clk_functions = { |
957 | .clk_enable = omap2_clk_enable, | 1045 | .clk_enable = omap2_clk_enable, |
958 | .clk_disable = omap2_clk_disable, | 1046 | .clk_disable = omap2_clk_disable, |
959 | .clk_round_rate = omap2_clk_round_rate, | 1047 | .clk_round_rate = omap2_clk_round_rate, |
960 | .clk_set_rate = omap2_clk_set_rate, | 1048 | .clk_set_rate = omap2_clk_set_rate, |
961 | .clk_set_parent = omap2_clk_set_parent, | 1049 | .clk_set_parent = omap2_clk_set_parent, |
1050 | .clk_disable_unused = omap2_clk_disable_unused, | ||
962 | }; | 1051 | }; |
963 | 1052 | ||
964 | static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) | 1053 | static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) |
@@ -984,27 +1073,19 @@ static void __init omap2_get_crystal_rate(struct clk *osc, struct clk *sys) | |||
984 | sys->rate = sclk; | 1073 | sys->rate = sclk; |
985 | } | 1074 | } |
986 | 1075 | ||
987 | #ifdef CONFIG_OMAP_RESET_CLOCKS | 1076 | /* |
988 | static void __init omap2_disable_unused_clocks(void) | 1077 | * Set clocks for bypass mode for reboot to work. |
1078 | */ | ||
1079 | void omap2_clk_prepare_for_reboot(void) | ||
989 | { | 1080 | { |
990 | struct clk *ck; | 1081 | u32 rate; |
991 | u32 regval32; | ||
992 | 1082 | ||
993 | list_for_each_entry(ck, &clocks, node) { | 1083 | if (vclk == NULL || sclk == NULL) |
994 | if (ck->usecount > 0 || (ck->flags & ALWAYS_ENABLED) || | 1084 | return; |
995 | ck->enable_reg == 0) | ||
996 | continue; | ||
997 | |||
998 | regval32 = __raw_readl(ck->enable_reg); | ||
999 | if ((regval32 & (1 << ck->enable_bit)) == 0) | ||
1000 | continue; | ||
1001 | 1085 | ||
1002 | printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); | 1086 | rate = clk_get_rate(sclk); |
1003 | _omap2_clk_disable(ck); | 1087 | clk_set_rate(vclk, rate); |
1004 | } | ||
1005 | } | 1088 | } |
1006 | late_initcall(omap2_disable_unused_clocks); | ||
1007 | #endif | ||
1008 | 1089 | ||
1009 | /* | 1090 | /* |
1010 | * Switch the MPU rate if specified on cmdline. | 1091 | * Switch the MPU rate if specified on cmdline. |
@@ -1077,8 +1158,27 @@ int __init omap2_clk_init(void) | |||
1077 | */ | 1158 | */ |
1078 | clk_enable(&sync_32k_ick); | 1159 | clk_enable(&sync_32k_ick); |
1079 | clk_enable(&omapctrl_ick); | 1160 | clk_enable(&omapctrl_ick); |
1161 | |||
1162 | /* Force the APLLs active during bootup to avoid disabling and | ||
1163 | * enabling them unnecessarily. */ | ||
1164 | clk_enable(&apll96_ck); | ||
1165 | clk_enable(&apll54_ck); | ||
1166 | |||
1080 | if (cpu_is_omap2430()) | 1167 | if (cpu_is_omap2430()) |
1081 | clk_enable(&sdrc_ick); | 1168 | clk_enable(&sdrc_ick); |
1082 | 1169 | ||
1170 | /* Avoid sleeping sleeping during omap2_clk_prepare_for_reboot() */ | ||
1171 | vclk = clk_get(NULL, "virt_prcm_set"); | ||
1172 | sclk = clk_get(NULL, "sys_ck"); | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | static int __init omap2_disable_aplls(void) | ||
1178 | { | ||
1179 | clk_disable(&apll96_ck); | ||
1180 | clk_disable(&apll54_ck); | ||
1181 | |||
1083 | return 0; | 1182 | return 0; |
1084 | } | 1183 | } |
1184 | late_initcall(omap2_disable_aplls); | ||
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 2781dfbc5164..8816f5a33a28 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h | |||
@@ -560,7 +560,7 @@ static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */ | |||
560 | .name = "osc_ck", | 560 | .name = "osc_ck", |
561 | .rate = 26000000, /* fixed up in clock init */ | 561 | .rate = 26000000, /* fixed up in clock init */ |
562 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | | 562 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | |
563 | RATE_FIXED | ALWAYS_ENABLED | RATE_PROPAGATES, | 563 | RATE_FIXED | RATE_PROPAGATES, |
564 | }; | 564 | }; |
565 | 565 | ||
566 | /* With out modem likely 12MHz, with modem likely 13MHz */ | 566 | /* With out modem likely 12MHz, with modem likely 13MHz */ |
@@ -1368,7 +1368,8 @@ static struct clk mcbsp5_fck = { | |||
1368 | }; | 1368 | }; |
1369 | 1369 | ||
1370 | static struct clk mcspi1_ick = { | 1370 | static struct clk mcspi1_ick = { |
1371 | .name = "mcspi1_ick", | 1371 | .name = "mcspi_ick", |
1372 | .id = 1, | ||
1372 | .parent = &l4_ck, | 1373 | .parent = &l4_ck, |
1373 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1374 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1374 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | 1375 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, |
@@ -1377,7 +1378,8 @@ static struct clk mcspi1_ick = { | |||
1377 | }; | 1378 | }; |
1378 | 1379 | ||
1379 | static struct clk mcspi1_fck = { | 1380 | static struct clk mcspi1_fck = { |
1380 | .name = "mcspi1_fck", | 1381 | .name = "mcspi_fck", |
1382 | .id = 1, | ||
1381 | .parent = &func_48m_ck, | 1383 | .parent = &func_48m_ck, |
1382 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1384 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1383 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | 1385 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, |
@@ -1386,7 +1388,8 @@ static struct clk mcspi1_fck = { | |||
1386 | }; | 1388 | }; |
1387 | 1389 | ||
1388 | static struct clk mcspi2_ick = { | 1390 | static struct clk mcspi2_ick = { |
1389 | .name = "mcspi2_ick", | 1391 | .name = "mcspi_ick", |
1392 | .id = 2, | ||
1390 | .parent = &l4_ck, | 1393 | .parent = &l4_ck, |
1391 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1394 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1392 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, | 1395 | .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, |
@@ -1395,7 +1398,8 @@ static struct clk mcspi2_ick = { | |||
1395 | }; | 1398 | }; |
1396 | 1399 | ||
1397 | static struct clk mcspi2_fck = { | 1400 | static struct clk mcspi2_fck = { |
1398 | .name = "mcspi2_fck", | 1401 | .name = "mcspi_fck", |
1402 | .id = 2, | ||
1399 | .parent = &func_48m_ck, | 1403 | .parent = &func_48m_ck, |
1400 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, | 1404 | .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, |
1401 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, | 1405 | .enable_reg = (void __iomem *)&CM_FCLKEN1_CORE, |
@@ -1404,7 +1408,8 @@ static struct clk mcspi2_fck = { | |||
1404 | }; | 1408 | }; |
1405 | 1409 | ||
1406 | static struct clk mcspi3_ick = { | 1410 | static struct clk mcspi3_ick = { |
1407 | .name = "mcspi3_ick", | 1411 | .name = "mcspi_ick", |
1412 | .id = 3, | ||
1408 | .parent = &l4_ck, | 1413 | .parent = &l4_ck, |
1409 | .flags = CLOCK_IN_OMAP243X, | 1414 | .flags = CLOCK_IN_OMAP243X, |
1410 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, | 1415 | .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, |
@@ -1413,7 +1418,8 @@ static struct clk mcspi3_ick = { | |||
1413 | }; | 1418 | }; |
1414 | 1419 | ||
1415 | static struct clk mcspi3_fck = { | 1420 | static struct clk mcspi3_fck = { |
1416 | .name = "mcspi3_fck", | 1421 | .name = "mcspi_fck", |
1422 | .id = 3, | ||
1417 | .parent = &func_48m_ck, | 1423 | .parent = &func_48m_ck, |
1418 | .flags = CLOCK_IN_OMAP243X, | 1424 | .flags = CLOCK_IN_OMAP243X, |
1419 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, | 1425 | .enable_reg = (void __iomem *)&CM_FCLKEN2_CORE, |
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index c7a48f921fef..f4f04d87df32 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c | |||
@@ -13,6 +13,8 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/err.h> | 14 | #include <linux/err.h> |
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/ioport.h> | ||
17 | #include <linux/spinlock.h> | ||
16 | 18 | ||
17 | #include <asm/io.h> | 19 | #include <asm/io.h> |
18 | #include <asm/arch/gpmc.h> | 20 | #include <asm/arch/gpmc.h> |
@@ -41,6 +43,19 @@ | |||
41 | #define GPMC_CS0 0x60 | 43 | #define GPMC_CS0 0x60 |
42 | #define GPMC_CS_SIZE 0x30 | 44 | #define GPMC_CS_SIZE 0x30 |
43 | 45 | ||
46 | #define GPMC_CS_NUM 8 | ||
47 | #define GPMC_MEM_START 0x00000000 | ||
48 | #define GPMC_MEM_END 0x3FFFFFFF | ||
49 | #define BOOT_ROM_SPACE 0x100000 /* 1MB */ | ||
50 | |||
51 | #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ | ||
52 | #define GPMC_SECTION_SHIFT 28 /* 128 MB */ | ||
53 | |||
54 | static struct resource gpmc_mem_root; | ||
55 | static struct resource gpmc_cs_mem[GPMC_CS_NUM]; | ||
56 | static spinlock_t gpmc_mem_lock = SPIN_LOCK_UNLOCKED; | ||
57 | static unsigned gpmc_cs_map; | ||
58 | |||
44 | static void __iomem *gpmc_base = | 59 | static void __iomem *gpmc_base = |
45 | (void __iomem *) IO_ADDRESS(GPMC_BASE); | 60 | (void __iomem *) IO_ADDRESS(GPMC_BASE); |
46 | static void __iomem *gpmc_cs_base = | 61 | static void __iomem *gpmc_cs_base = |
@@ -187,9 +202,168 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) | |||
187 | return 0; | 202 | return 0; |
188 | } | 203 | } |
189 | 204 | ||
190 | unsigned long gpmc_cs_get_base_addr(int cs) | 205 | static void gpmc_cs_enable_mem(int cs, u32 base, u32 size) |
206 | { | ||
207 | u32 l; | ||
208 | u32 mask; | ||
209 | |||
210 | mask = (1 << GPMC_SECTION_SHIFT) - size; | ||
211 | l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); | ||
212 | l &= ~0x3f; | ||
213 | l = (base >> GPMC_CHUNK_SHIFT) & 0x3f; | ||
214 | l &= ~(0x0f << 8); | ||
215 | l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8; | ||
216 | l |= 1 << 6; /* CSVALID */ | ||
217 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); | ||
218 | } | ||
219 | |||
220 | static void gpmc_cs_disable_mem(int cs) | ||
221 | { | ||
222 | u32 l; | ||
223 | |||
224 | l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); | ||
225 | l &= ~(1 << 6); /* CSVALID */ | ||
226 | gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); | ||
227 | } | ||
228 | |||
229 | static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size) | ||
230 | { | ||
231 | u32 l; | ||
232 | u32 mask; | ||
233 | |||
234 | l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); | ||
235 | *base = (l & 0x3f) << GPMC_CHUNK_SHIFT; | ||
236 | mask = (l >> 8) & 0x0f; | ||
237 | *size = (1 << GPMC_SECTION_SHIFT) - (mask << GPMC_CHUNK_SHIFT); | ||
238 | } | ||
239 | |||
240 | static int gpmc_cs_mem_enabled(int cs) | ||
241 | { | ||
242 | u32 l; | ||
243 | |||
244 | l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); | ||
245 | return l & (1 << 6); | ||
246 | } | ||
247 | |||
248 | static void gpmc_cs_set_reserved(int cs, int reserved) | ||
191 | { | 249 | { |
192 | return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24; | 250 | gpmc_cs_map &= ~(1 << cs); |
251 | gpmc_cs_map |= (reserved ? 1 : 0) << cs; | ||
252 | } | ||
253 | |||
254 | static int gpmc_cs_reserved(int cs) | ||
255 | { | ||
256 | return gpmc_cs_map & (1 << cs); | ||
257 | } | ||
258 | |||
259 | static unsigned long gpmc_mem_align(unsigned long size) | ||
260 | { | ||
261 | int order; | ||
262 | |||
263 | size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1); | ||
264 | order = GPMC_CHUNK_SHIFT - 1; | ||
265 | do { | ||
266 | size >>= 1; | ||
267 | order++; | ||
268 | } while (size); | ||
269 | size = 1 << order; | ||
270 | return size; | ||
271 | } | ||
272 | |||
273 | static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size) | ||
274 | { | ||
275 | struct resource *res = &gpmc_cs_mem[cs]; | ||
276 | int r; | ||
277 | |||
278 | size = gpmc_mem_align(size); | ||
279 | spin_lock(&gpmc_mem_lock); | ||
280 | res->start = base; | ||
281 | res->end = base + size - 1; | ||
282 | r = request_resource(&gpmc_mem_root, res); | ||
283 | spin_unlock(&gpmc_mem_lock); | ||
284 | |||
285 | return r; | ||
286 | } | ||
287 | |||
288 | int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) | ||
289 | { | ||
290 | struct resource *res = &gpmc_cs_mem[cs]; | ||
291 | int r = -1; | ||
292 | |||
293 | if (cs > GPMC_CS_NUM) | ||
294 | return -ENODEV; | ||
295 | |||
296 | size = gpmc_mem_align(size); | ||
297 | if (size > (1 << GPMC_SECTION_SHIFT)) | ||
298 | return -ENOMEM; | ||
299 | |||
300 | spin_lock(&gpmc_mem_lock); | ||
301 | if (gpmc_cs_reserved(cs)) { | ||
302 | r = -EBUSY; | ||
303 | goto out; | ||
304 | } | ||
305 | if (gpmc_cs_mem_enabled(cs)) | ||
306 | r = adjust_resource(res, res->start & ~(size - 1), size); | ||
307 | if (r < 0) | ||
308 | r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0, | ||
309 | size, NULL, NULL); | ||
310 | if (r < 0) | ||
311 | goto out; | ||
312 | |||
313 | gpmc_cs_enable_mem(cs, res->start, res->end - res->start + 1); | ||
314 | *base = res->start; | ||
315 | gpmc_cs_set_reserved(cs, 1); | ||
316 | out: | ||
317 | spin_unlock(&gpmc_mem_lock); | ||
318 | return r; | ||
319 | } | ||
320 | |||
321 | void gpmc_cs_free(int cs) | ||
322 | { | ||
323 | spin_lock(&gpmc_mem_lock); | ||
324 | if (cs >= GPMC_CS_NUM || !gpmc_cs_reserved(cs)) { | ||
325 | printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs); | ||
326 | BUG(); | ||
327 | spin_unlock(&gpmc_mem_lock); | ||
328 | return; | ||
329 | } | ||
330 | gpmc_cs_disable_mem(cs); | ||
331 | release_resource(&gpmc_cs_mem[cs]); | ||
332 | gpmc_cs_set_reserved(cs, 0); | ||
333 | spin_unlock(&gpmc_mem_lock); | ||
334 | } | ||
335 | |||
336 | void __init gpmc_mem_init(void) | ||
337 | { | ||
338 | int cs; | ||
339 | unsigned long boot_rom_space = 0; | ||
340 | |||
341 | if (cpu_is_omap242x()) { | ||
342 | u32 l; | ||
343 | l = omap_readl(OMAP242X_CONTROL_STATUS); | ||
344 | /* In case of internal boot the 1st MB is redirected to the | ||
345 | * boot ROM memory space. | ||
346 | */ | ||
347 | if (l & (1 << 3)) | ||
348 | boot_rom_space = BOOT_ROM_SPACE; | ||
349 | } else | ||
350 | /* We assume internal boot if the mode can't be | ||
351 | * determined. | ||
352 | */ | ||
353 | boot_rom_space = BOOT_ROM_SPACE; | ||
354 | gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space; | ||
355 | gpmc_mem_root.end = GPMC_MEM_END; | ||
356 | |||
357 | /* Reserve all regions that has been set up by bootloader */ | ||
358 | for (cs = 0; cs < GPMC_CS_NUM; cs++) { | ||
359 | u32 base, size; | ||
360 | |||
361 | if (!gpmc_cs_mem_enabled(cs)) | ||
362 | continue; | ||
363 | gpmc_cs_get_memconf(cs, &base, &size); | ||
364 | if (gpmc_cs_insert_mem(cs, base, size) < 0) | ||
365 | BUG(); | ||
366 | } | ||
193 | } | 367 | } |
194 | 368 | ||
195 | void __init gpmc_init(void) | 369 | void __init gpmc_init(void) |
@@ -206,4 +380,6 @@ void __init gpmc_init(void) | |||
206 | l &= 0x03 << 3; | 380 | l &= 0x03 << 3; |
207 | l |= (0x02 << 3) | (1 << 0); | 381 | l |= (0x02 << 3) | (1 << 0); |
208 | gpmc_write_reg(GPMC_SYSCONFIG, l); | 382 | gpmc_write_reg(GPMC_SYSCONFIG, l); |
383 | |||
384 | gpmc_mem_init(); | ||
209 | } | 385 | } |
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index dfc3b35cc1ff..1ed2fff4691a 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c | |||
@@ -41,18 +41,6 @@ static struct omap_irq_bank { | |||
41 | .nr_irqs = 96, | 41 | .nr_irqs = 96, |
42 | }, { | 42 | }, { |
43 | /* XXX: DSP INTC */ | 43 | /* XXX: DSP INTC */ |
44 | |||
45 | #if 0 | ||
46 | /* | ||
47 | * Commented out for now until we fix the IVA clocking | ||
48 | */ | ||
49 | #ifdef CONFIG_ARCH_OMAP2420 | ||
50 | }, { | ||
51 | /* IVA INTC (2420 only) */ | ||
52 | .base_reg = OMAP24XX_IVA_INTC_BASE, | ||
53 | .nr_irqs = 16, /* Actually 32, but only 16 are used */ | ||
54 | #endif | ||
55 | #endif | ||
56 | } | 44 | } |
57 | }; | 45 | }; |
58 | 46 | ||
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 60ef084faffd..f538d0fdb13c 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c | |||
@@ -104,6 +104,20 @@ MUX_CFG_24XX("P20_24XX_TSC_IRQ", 0x108, 0, 0, 0, 1) | |||
104 | MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1) | 104 | MUX_CFG_24XX("K15_24XX_UART3_TX", 0x118, 0, 0, 0, 1) |
105 | MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1) | 105 | MUX_CFG_24XX("K14_24XX_UART3_RX", 0x119, 0, 0, 0, 1) |
106 | 106 | ||
107 | /* MMC/SDIO */ | ||
108 | MUX_CFG_24XX("G19_24XX_MMC_CLKO", 0x0f3, 0, 0, 0, 1) | ||
109 | MUX_CFG_24XX("H18_24XX_MMC_CMD", 0x0f4, 0, 0, 0, 1) | ||
110 | MUX_CFG_24XX("F20_24XX_MMC_DAT0", 0x0f5, 0, 0, 0, 1) | ||
111 | MUX_CFG_24XX("H14_24XX_MMC_DAT1", 0x0f6, 0, 0, 0, 1) | ||
112 | MUX_CFG_24XX("E19_24XX_MMC_DAT2", 0x0f7, 0, 0, 0, 1) | ||
113 | MUX_CFG_24XX("D19_24XX_MMC_DAT3", 0x0f8, 0, 0, 0, 1) | ||
114 | MUX_CFG_24XX("F19_24XX_MMC_DAT_DIR0", 0x0f9, 0, 0, 0, 1) | ||
115 | MUX_CFG_24XX("E20_24XX_MMC_DAT_DIR1", 0x0fa, 0, 0, 0, 1) | ||
116 | MUX_CFG_24XX("F18_24XX_MMC_DAT_DIR2", 0x0fb, 0, 0, 0, 1) | ||
117 | MUX_CFG_24XX("E18_24XX_MMC_DAT_DIR3", 0x0fc, 0, 0, 0, 1) | ||
118 | MUX_CFG_24XX("G18_24XX_MMC_CMD_DIR", 0x0fd, 0, 0, 0, 1) | ||
119 | MUX_CFG_24XX("H15_24XX_MMC_CLKI", 0x0fe, 0, 0, 0, 1) | ||
120 | |||
107 | /* Keypad GPIO*/ | 121 | /* Keypad GPIO*/ |
108 | MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1) | 122 | MUX_CFG_24XX("T19_24XX_KBR0", 0x106, 3, 1, 1, 1) |
109 | MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1) | 123 | MUX_CFG_24XX("R19_24XX_KBR1", 0x107, 3, 1, 1, 1) |
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c index c2bf57ef6825..90f530540c65 100644 --- a/arch/arm/mach-omap2/prcm.c +++ b/arch/arm/mach-omap2/prcm.c | |||
@@ -19,6 +19,8 @@ | |||
19 | 19 | ||
20 | #include "prcm-regs.h" | 20 | #include "prcm-regs.h" |
21 | 21 | ||
22 | extern void omap2_clk_prepare_for_reboot(void); | ||
23 | |||
22 | u32 omap_prcm_get_reset_sources(void) | 24 | u32 omap_prcm_get_reset_sources(void) |
23 | { | 25 | { |
24 | return RM_RSTST_WKUP & 0x7f; | 26 | return RM_RSTST_WKUP & 0x7f; |
@@ -28,12 +30,6 @@ EXPORT_SYMBOL(omap_prcm_get_reset_sources); | |||
28 | /* Resets clock rates and reboots the system. Only called from system.h */ | 30 | /* Resets clock rates and reboots the system. Only called from system.h */ |
29 | void omap_prcm_arch_reset(char mode) | 31 | void omap_prcm_arch_reset(char mode) |
30 | { | 32 | { |
31 | u32 rate; | 33 | omap2_clk_prepare_for_reboot(); |
32 | struct clk *vclk, *sclk; | ||
33 | |||
34 | vclk = clk_get(NULL, "virt_prcm_set"); | ||
35 | sclk = clk_get(NULL, "sys_ck"); | ||
36 | rate = clk_get_rate(sclk); | ||
37 | clk_set_rate(vclk, rate); /* go to bypass for OMAP limitation */ | ||
38 | RM_RSTCTRL_WKUP |= 2; | 34 | RM_RSTCTRL_WKUP |= 2; |
39 | } | 35 | } |