1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <config.h> 8#include <types.h> 9#include <machine/io.h> 10#include <kernel/vspace.h> 11#include <arch/machine.h> 12#include <arch/kernel/vspace.h> 13#include <plat/machine.h> 14#include <linker.h> 15#include <plat/machine/hardware.h> 16 17#define L2_LINE_SIZE_BITS 5 18#define L2_LINE_SIZE BIT(L2_LINE_SIZE_BITS) 19 20#define L2_LINE_START(a) ROUND_DOWN(a, L2_LINE_SIZE_BITS) 21#define L2_LINE_INDEX(a) (L2_LINE_START(a)>>L2_LINE_SIZE_BITS) 22 23/* kernel devices */ 24struct imx31_l2cc_id { 25 uint32_t id; /* 000 */ 26 uint32_t type; /* 004 */ 27}; 28#define imx31_l2cc_id_regs \ 29 ((volatile struct imx31_l2cc_id *)L2CC_PPTR) 30 31struct imx31_l2cc_ctrl { 32 uint32_t control; /* 100 */ 33 uint32_t aux_control; /* 104 */ 34}; 35#define imx31_l2cc_ctrl_regs \ 36 ((volatile struct imx31_l2cc_ctrl *)(L2CC_PPTR + 0x100)) 37 38struct imx31_l2cc_flush { 39 uint32_t pad_0[12]; 40 uint32_t sync; /* 730 */ 41 uint32_t pad_1[15]; 42 uint32_t inv_by_pa; /* 770 */ 43 uint32_t pad_2[2]; 44 uint32_t inv_by_way; /* 77c */ 45 uint32_t pad_3[12]; 46 uint32_t clean_by_pa; /* 7b0 */ 47 uint32_t pad_4[1]; 48 uint32_t clean_by_ix; /* 7b8 */ 49 uint32_t clean_by_way; /* 7bc */ 50 uint32_t pad_5[12]; 51 uint32_t clinv_by_pa; /* 7f0 */ 52 uint32_t pad_6[1]; 53 uint32_t clinv_by_ix; /* 7f8 */ 54 uint32_t clinv_by_way; /* 7fc */ 55}; 56#define imx31_l2cc_flush_regs \ 57 ((volatile struct imx31_l2cc_flush *)(L2CC_PPTR + 0x700)) 58 59struct imx31_l2cc_lockdown { 60 uint32_t lock_way_D; /* 900 */ 61 uint32_t lock_way_I; /* 904 */ 62}; 63#define imx32_l2cc_lockdown_regs \ 64 ((volatile struct imx31_l2cc_lockdown *)(L2CC_PPTR + 0x900)) 65 66static void cleanL2(void) 67{ 68 /* clean all ways */ 69 imx31_l2cc_flush_regs->clean_by_way = 0xff; 70 /* Busy-wait for completion */ 71 while (imx31_l2cc_flush_regs->clean_by_way); 72} 73 74static void invalidateL2(void) 75{ 76 /* Invalidate all ways. */ 77 imx31_l2cc_flush_regs->inv_by_way = 0xff; 78 /* Busy-wait for completion. */ 79 while (imx31_l2cc_flush_regs->inv_by_way); 80} 81 82static void finaliseL2Op(void) 83{ 84 /* We sync the l2 cache, which drains the write and eviction 85 buffers, to ensure that everything is consistent with RAM. */ 86 imx31_l2cc_flush_regs->sync = 1; 87} 88 89void plat_cleanL2Range(paddr_t start, paddr_t end) 90{ 91 paddr_t line; 92 word_t index; 93 94 for (index = L2_LINE_INDEX(start); 95 index < L2_LINE_INDEX(end) + 1; 96 index++) { 97 line = index << L2_LINE_SIZE_BITS; 98 imx31_l2cc_flush_regs->clean_by_pa = line; 99 } 100 finaliseL2Op(); 101} 102 103void plat_invalidateL2Range(paddr_t start, paddr_t end) 104{ 105 paddr_t line; 106 word_t index; 107 108 for (index = L2_LINE_INDEX(start); 109 index < L2_LINE_INDEX(end) + 1; 110 index++) { 111 line = index << L2_LINE_SIZE_BITS; 112 imx31_l2cc_flush_regs->inv_by_pa = line; 113 } 114 115 finaliseL2Op(); 116} 117 118void plat_cleanInvalidateL2Range(paddr_t start, paddr_t end) 119{ 120 paddr_t line; 121 word_t index; 122 123 for (index = L2_LINE_INDEX(start); 124 index < L2_LINE_INDEX(end) + 1; 125 index++) { 126 line = index << L2_LINE_SIZE_BITS; 127 imx31_l2cc_flush_regs->clinv_by_pa = line; 128 } 129 finaliseL2Op(); 130} 131 132void plat_cleanInvalidateL2Cache(void) 133{ 134 cleanL2(); 135 invalidateL2(); 136} 137 138BOOT_CODE void initL2Cache(void) 139{ 140#ifndef CONFIG_DEBUG_DISABLE_L2_CACHE 141 /* Configure L2 cache */ 142 imx31_l2cc_ctrl_regs->aux_control = 0x0003001b; 143 144 /* Invalidate the L2 cache */ 145 invalidateL2(); 146 147 /* Enable the L2 cache */ 148 imx31_l2cc_ctrl_regs->control = 1; 149#endif 150} 151 152irq_t active_irq = irqInvalid; 153 154BOOT_CODE void initIRQController(void) 155{ 156 /* Do nothing */ 157} 158 159BOOT_CODE void cpu_initLocalIRQController(void) 160{ 161 /* Do nothing */ 162} 163