diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/85xx/p1022_ds.c | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 5ca2823ab7f2..3c732acf331d 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c | |||
@@ -208,6 +208,7 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) | |||
208 | u8 __iomem *lbc_lcs0_ba = NULL; | 208 | u8 __iomem *lbc_lcs0_ba = NULL; |
209 | u8 __iomem *lbc_lcs1_ba = NULL; | 209 | u8 __iomem *lbc_lcs1_ba = NULL; |
210 | phys_addr_t cs0_addr, cs1_addr; | 210 | phys_addr_t cs0_addr, cs1_addr; |
211 | u32 br0, or0, br1, or1; | ||
211 | const __be32 *iprop; | 212 | const __be32 *iprop; |
212 | unsigned int num_laws; | 213 | unsigned int num_laws; |
213 | u8 b; | 214 | u8 b; |
@@ -256,11 +257,70 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) | |||
256 | } | 257 | } |
257 | num_laws = be32_to_cpup(iprop); | 258 | num_laws = be32_to_cpup(iprop); |
258 | 259 | ||
259 | cs0_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[0].br)); | 260 | /* |
260 | cs1_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[1].br)); | 261 | * Indirect mode requires both BR0 and BR1 to be set to "GPCM", |
262 | * otherwise writes to these addresses won't actually appear on the | ||
263 | * local bus, and so the PIXIS won't see them. | ||
264 | * | ||
265 | * In FCM mode, writes go to the NAND controller, which does not pass | ||
266 | * them to the localbus directly. So we force BR0 and BR1 into GPCM | ||
267 | * mode, since we don't care about what's behind the localbus any | ||
268 | * more. | ||
269 | */ | ||
270 | br0 = in_be32(&lbc->bank[0].br); | ||
271 | br1 = in_be32(&lbc->bank[1].br); | ||
272 | or0 = in_be32(&lbc->bank[0].or); | ||
273 | or1 = in_be32(&lbc->bank[1].or); | ||
274 | |||
275 | /* Make sure CS0 and CS1 are programmed */ | ||
276 | if (!(br0 & BR_V) || !(br1 & BR_V)) { | ||
277 | pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); | ||
278 | goto exit; | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * Use the existing BRx/ORx values if it's already GPCM. Otherwise, | ||
283 | * force the values to simple 32KB GPCM windows with the most | ||
284 | * conservative timing. | ||
285 | */ | ||
286 | if ((br0 & BR_MSEL) != BR_MS_GPCM) { | ||
287 | br0 = (br0 & BR_BA) | BR_V; | ||
288 | or0 = 0xFFFF8000 | 0xFF7; | ||
289 | out_be32(&lbc->bank[0].br, br0); | ||
290 | out_be32(&lbc->bank[0].or, or0); | ||
291 | } | ||
292 | if ((br1 & BR_MSEL) != BR_MS_GPCM) { | ||
293 | br1 = (br1 & BR_BA) | BR_V; | ||
294 | or1 = 0xFFFF8000 | 0xFF7; | ||
295 | out_be32(&lbc->bank[1].br, br1); | ||
296 | out_be32(&lbc->bank[1].or, or1); | ||
297 | } | ||
298 | |||
299 | cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); | ||
300 | if (!cs0_addr) { | ||
301 | pr_err("p1022ds: could not determine physical address for CS0" | ||
302 | " (BR0=%08x)\n", br0); | ||
303 | goto exit; | ||
304 | } | ||
305 | cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); | ||
306 | if (!cs0_addr) { | ||
307 | pr_err("p1022ds: could not determine physical address for CS1" | ||
308 | " (BR1=%08x)\n", br1); | ||
309 | goto exit; | ||
310 | } | ||
261 | 311 | ||
262 | lbc_lcs0_ba = ioremap(cs0_addr, 1); | 312 | lbc_lcs0_ba = ioremap(cs0_addr, 1); |
313 | if (!lbc_lcs0_ba) { | ||
314 | pr_err("p1022ds: could not ioremap CS0 address %llx\n", | ||
315 | (unsigned long long)cs0_addr); | ||
316 | goto exit; | ||
317 | } | ||
263 | lbc_lcs1_ba = ioremap(cs1_addr, 1); | 318 | lbc_lcs1_ba = ioremap(cs1_addr, 1); |
319 | if (!lbc_lcs1_ba) { | ||
320 | pr_err("p1022ds: could not ioremap CS1 address %llx\n", | ||
321 | (unsigned long long)cs1_addr); | ||
322 | goto exit; | ||
323 | } | ||
264 | 324 | ||
265 | /* Make sure we're in indirect mode first. */ | 325 | /* Make sure we're in indirect mode first. */ |
266 | if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != | 326 | if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != |