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