aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/cache-l2x0.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm/cache-l2x0.c')
-rw-r--r--arch/arm/mm/cache-l2x0.c129
1 files changed, 119 insertions, 10 deletions
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 0d85d221d7b0..3f9b9980478e 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -33,6 +33,14 @@ static DEFINE_SPINLOCK(l2x0_lock);
33static uint32_t l2x0_way_mask; /* Bitmask of active ways */ 33static uint32_t l2x0_way_mask; /* Bitmask of active ways */
34static uint32_t l2x0_size; 34static uint32_t l2x0_size;
35 35
36struct l2x0_regs l2x0_saved_regs;
37
38struct l2x0_of_data {
39 void (*setup)(const struct device_node *, __u32 *, __u32 *);
40 void (*save)(void);
41 void (*resume)(void);
42};
43
36static inline void cache_wait_way(void __iomem *reg, unsigned long mask) 44static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
37{ 45{
38 /* wait for cache operation by line or way to complete */ 46 /* wait for cache operation by line or way to complete */
@@ -280,7 +288,7 @@ static void l2x0_disable(void)
280 spin_unlock_irqrestore(&l2x0_lock, flags); 288 spin_unlock_irqrestore(&l2x0_lock, flags);
281} 289}
282 290
283static void __init l2x0_unlock(__u32 cache_id) 291static void l2x0_unlock(__u32 cache_id)
284{ 292{
285 int lockregs; 293 int lockregs;
286 int i; 294 int i;
@@ -356,6 +364,8 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
356 /* l2x0 controller is disabled */ 364 /* l2x0 controller is disabled */
357 writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL); 365 writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
358 366
367 l2x0_saved_regs.aux_ctrl = aux;
368
359 l2x0_inv_all(); 369 l2x0_inv_all();
360 370
361 /* enable L2X0 */ 371 /* enable L2X0 */
@@ -445,33 +455,132 @@ static void __init pl310_of_setup(const struct device_node *np,
445 } 455 }
446} 456}
447 457
458static void __init pl310_save(void)
459{
460 u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
461 L2X0_CACHE_ID_RTL_MASK;
462
463 l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
464 L2X0_TAG_LATENCY_CTRL);
465 l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
466 L2X0_DATA_LATENCY_CTRL);
467 l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
468 L2X0_ADDR_FILTER_END);
469 l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
470 L2X0_ADDR_FILTER_START);
471
472 if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
473 /*
474 * From r2p0, there is Prefetch offset/control register
475 */
476 l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
477 L2X0_PREFETCH_CTRL);
478 /*
479 * From r3p0, there is Power control register
480 */
481 if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
482 l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
483 L2X0_POWER_CTRL);
484 }
485}
486
487static void l2x0_resume(void)
488{
489 if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
490 /* restore aux ctrl and enable l2 */
491 l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
492
493 writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
494 L2X0_AUX_CTRL);
495
496 l2x0_inv_all();
497
498 writel_relaxed(1, l2x0_base + L2X0_CTRL);
499 }
500}
501
502static void pl310_resume(void)
503{
504 u32 l2x0_revision;
505
506 if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
507 /* restore pl310 setup */
508 writel_relaxed(l2x0_saved_regs.tag_latency,
509 l2x0_base + L2X0_TAG_LATENCY_CTRL);
510 writel_relaxed(l2x0_saved_regs.data_latency,
511 l2x0_base + L2X0_DATA_LATENCY_CTRL);
512 writel_relaxed(l2x0_saved_regs.filter_end,
513 l2x0_base + L2X0_ADDR_FILTER_END);
514 writel_relaxed(l2x0_saved_regs.filter_start,
515 l2x0_base + L2X0_ADDR_FILTER_START);
516
517 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
518 L2X0_CACHE_ID_RTL_MASK;
519
520 if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
521 writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
522 l2x0_base + L2X0_PREFETCH_CTRL);
523 if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
524 writel_relaxed(l2x0_saved_regs.pwr_ctrl,
525 l2x0_base + L2X0_POWER_CTRL);
526 }
527 }
528
529 l2x0_resume();
530}
531
532static const struct l2x0_of_data pl310_data = {
533 pl310_of_setup,
534 pl310_save,
535 pl310_resume,
536};
537
538static const struct l2x0_of_data l2x0_data = {
539 l2x0_of_setup,
540 NULL,
541 l2x0_resume,
542};
543
448static const struct of_device_id l2x0_ids[] __initconst = { 544static const struct of_device_id l2x0_ids[] __initconst = {
449 { .compatible = "arm,pl310-cache", .data = pl310_of_setup }, 545 { .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
450 { .compatible = "arm,l220-cache", .data = l2x0_of_setup }, 546 { .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
451 { .compatible = "arm,l210-cache", .data = l2x0_of_setup }, 547 { .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
452 {} 548 {}
453}; 549};
454 550
455int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask) 551int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
456{ 552{
457 struct device_node *np; 553 struct device_node *np;
458 void (*l2_setup)(const struct device_node *np, 554 struct l2x0_of_data *data;
459 __u32 *aux_val, __u32 *aux_mask); 555 struct resource res;
460 556
461 np = of_find_matching_node(NULL, l2x0_ids); 557 np = of_find_matching_node(NULL, l2x0_ids);
462 if (!np) 558 if (!np)
463 return -ENODEV; 559 return -ENODEV;
464 l2x0_base = of_iomap(np, 0); 560
561 if (of_address_to_resource(np, 0, &res))
562 return -ENODEV;
563
564 l2x0_base = ioremap(res.start, resource_size(&res));
465 if (!l2x0_base) 565 if (!l2x0_base)
466 return -ENOMEM; 566 return -ENOMEM;
467 567
568 l2x0_saved_regs.phy_base = res.start;
569
570 data = of_match_node(l2x0_ids, np)->data;
571
468 /* L2 configuration can only be changed if the cache is disabled */ 572 /* L2 configuration can only be changed if the cache is disabled */
469 if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) { 573 if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
470 l2_setup = of_match_node(l2x0_ids, np)->data; 574 if (data->setup)
471 if (l2_setup) 575 data->setup(np, &aux_val, &aux_mask);
472 l2_setup(np, &aux_val, &aux_mask);
473 } 576 }
577
578 if (data->save)
579 data->save();
580
474 l2x0_init(l2x0_base, aux_val, aux_mask); 581 l2x0_init(l2x0_base, aux_val, aux_mask);
582
583 outer_cache.resume = data->resume;
475 return 0; 584 return 0;
476} 585}
477#endif 586#endif