xref: /rk3399_ARM-atf/drivers/marvell/cache_llc.c (revision 152b0e4717553bbfa30ba2e978b596499e946bc9)
1*152b0e47SKonstantin Porotchkin /*
2*152b0e47SKonstantin Porotchkin  * Copyright (C) 2018 Marvell International Ltd.
3*152b0e47SKonstantin Porotchkin  *
4*152b0e47SKonstantin Porotchkin  * SPDX-License-Identifier:     BSD-3-Clause
5*152b0e47SKonstantin Porotchkin  * https://spdx.org/licenses
6*152b0e47SKonstantin Porotchkin  */
7*152b0e47SKonstantin Porotchkin 
8*152b0e47SKonstantin Porotchkin /* LLC driver is the Last Level Cache (L3C) driver
9*152b0e47SKonstantin Porotchkin  * for Marvell SoCs in AP806, AP807, and AP810
10*152b0e47SKonstantin Porotchkin  */
11*152b0e47SKonstantin Porotchkin 
12*152b0e47SKonstantin Porotchkin #include <arch_helpers.h>
13*152b0e47SKonstantin Porotchkin #include <assert.h>
14*152b0e47SKonstantin Porotchkin #include <cache_llc.h>
15*152b0e47SKonstantin Porotchkin #include <ccu.h>
16*152b0e47SKonstantin Porotchkin #include <mmio.h>
17*152b0e47SKonstantin Porotchkin #include <mvebu_def.h>
18*152b0e47SKonstantin Porotchkin 
19*152b0e47SKonstantin Porotchkin #define CCU_HTC_CR(ap_index)		(MVEBU_CCU_BASE(ap_index) + 0x200)
20*152b0e47SKonstantin Porotchkin #define CCU_SET_POC_OFFSET		5
21*152b0e47SKonstantin Porotchkin 
22*152b0e47SKonstantin Porotchkin extern void ca72_l2_enable_unique_clean(void);
23*152b0e47SKonstantin Porotchkin 
24*152b0e47SKonstantin Porotchkin void llc_cache_sync(int ap_index)
25*152b0e47SKonstantin Porotchkin {
26*152b0e47SKonstantin Porotchkin 	mmio_write_32(LLC_SYNC(ap_index), 0);
27*152b0e47SKonstantin Porotchkin 	/* Atomic write, no need to wait */
28*152b0e47SKonstantin Porotchkin }
29*152b0e47SKonstantin Porotchkin 
30*152b0e47SKonstantin Porotchkin void llc_flush_all(int ap_index)
31*152b0e47SKonstantin Porotchkin {
32*152b0e47SKonstantin Porotchkin 	mmio_write_32(L2X0_CLEAN_INV_WAY(ap_index), LLC_WAY_MASK);
33*152b0e47SKonstantin Porotchkin 	llc_cache_sync(ap_index);
34*152b0e47SKonstantin Porotchkin }
35*152b0e47SKonstantin Porotchkin 
36*152b0e47SKonstantin Porotchkin void llc_clean_all(int ap_index)
37*152b0e47SKonstantin Porotchkin {
38*152b0e47SKonstantin Porotchkin 	mmio_write_32(L2X0_CLEAN_WAY(ap_index), LLC_WAY_MASK);
39*152b0e47SKonstantin Porotchkin 	llc_cache_sync(ap_index);
40*152b0e47SKonstantin Porotchkin }
41*152b0e47SKonstantin Porotchkin 
42*152b0e47SKonstantin Porotchkin void llc_inv_all(int ap_index)
43*152b0e47SKonstantin Porotchkin {
44*152b0e47SKonstantin Porotchkin 	mmio_write_32(L2X0_INV_WAY(ap_index), LLC_WAY_MASK);
45*152b0e47SKonstantin Porotchkin 	llc_cache_sync(ap_index);
46*152b0e47SKonstantin Porotchkin }
47*152b0e47SKonstantin Porotchkin 
48*152b0e47SKonstantin Porotchkin void llc_disable(int ap_index)
49*152b0e47SKonstantin Porotchkin {
50*152b0e47SKonstantin Porotchkin 	llc_flush_all(ap_index);
51*152b0e47SKonstantin Porotchkin 	mmio_write_32(LLC_CTRL(ap_index), 0);
52*152b0e47SKonstantin Porotchkin 	dsbishst();
53*152b0e47SKonstantin Porotchkin }
54*152b0e47SKonstantin Porotchkin 
55*152b0e47SKonstantin Porotchkin void llc_enable(int ap_index, int excl_mode)
56*152b0e47SKonstantin Porotchkin {
57*152b0e47SKonstantin Porotchkin 	uint32_t val;
58*152b0e47SKonstantin Porotchkin 
59*152b0e47SKonstantin Porotchkin 	dsbsy();
60*152b0e47SKonstantin Porotchkin 	llc_inv_all(ap_index);
61*152b0e47SKonstantin Porotchkin 	dsbsy();
62*152b0e47SKonstantin Porotchkin 
63*152b0e47SKonstantin Porotchkin 	val = LLC_CTRL_EN;
64*152b0e47SKonstantin Porotchkin 	if (excl_mode)
65*152b0e47SKonstantin Porotchkin 		val |= LLC_EXCLUSIVE_EN;
66*152b0e47SKonstantin Porotchkin 
67*152b0e47SKonstantin Porotchkin 	mmio_write_32(LLC_CTRL(ap_index), val);
68*152b0e47SKonstantin Porotchkin 	dsbsy();
69*152b0e47SKonstantin Porotchkin }
70*152b0e47SKonstantin Porotchkin 
71*152b0e47SKonstantin Porotchkin int llc_is_exclusive(int ap_index)
72*152b0e47SKonstantin Porotchkin {
73*152b0e47SKonstantin Porotchkin 	uint32_t reg;
74*152b0e47SKonstantin Porotchkin 
75*152b0e47SKonstantin Porotchkin 	reg = mmio_read_32(LLC_CTRL(ap_index));
76*152b0e47SKonstantin Porotchkin 
77*152b0e47SKonstantin Porotchkin 	if ((reg & (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) ==
78*152b0e47SKonstantin Porotchkin 		   (LLC_CTRL_EN | LLC_EXCLUSIVE_EN))
79*152b0e47SKonstantin Porotchkin 		return 1;
80*152b0e47SKonstantin Porotchkin 
81*152b0e47SKonstantin Porotchkin 	return 0;
82*152b0e47SKonstantin Porotchkin }
83*152b0e47SKonstantin Porotchkin 
84*152b0e47SKonstantin Porotchkin void llc_runtime_enable(int ap_index)
85*152b0e47SKonstantin Porotchkin {
86*152b0e47SKonstantin Porotchkin 	uint32_t reg;
87*152b0e47SKonstantin Porotchkin 
88*152b0e47SKonstantin Porotchkin 	reg = mmio_read_32(LLC_CTRL(ap_index));
89*152b0e47SKonstantin Porotchkin 	if (reg & LLC_CTRL_EN)
90*152b0e47SKonstantin Porotchkin 		return;
91*152b0e47SKonstantin Porotchkin 
92*152b0e47SKonstantin Porotchkin 	INFO("Enabling LLC\n");
93*152b0e47SKonstantin Porotchkin 
94*152b0e47SKonstantin Porotchkin 	/*
95*152b0e47SKonstantin Porotchkin 	 * Enable L2 UniqueClean evictions with data
96*152b0e47SKonstantin Porotchkin 	 *  Note: this configuration assumes that LLC is configured
97*152b0e47SKonstantin Porotchkin 	 *	  in exclusive mode.
98*152b0e47SKonstantin Porotchkin 	 *	  Later on in the code this assumption will be validated
99*152b0e47SKonstantin Porotchkin 	 */
100*152b0e47SKonstantin Porotchkin 	ca72_l2_enable_unique_clean();
101*152b0e47SKonstantin Porotchkin 	llc_enable(ap_index, 1);
102*152b0e47SKonstantin Porotchkin 
103*152b0e47SKonstantin Porotchkin 	/* Set point of coherency to DDR.
104*152b0e47SKonstantin Porotchkin 	 * This is required by units which have SW cache coherency
105*152b0e47SKonstantin Porotchkin 	 */
106*152b0e47SKonstantin Porotchkin 	reg = mmio_read_32(CCU_HTC_CR(ap_index));
107*152b0e47SKonstantin Porotchkin 	reg |= (0x1 << CCU_SET_POC_OFFSET);
108*152b0e47SKonstantin Porotchkin 	mmio_write_32(CCU_HTC_CR(ap_index), reg);
109*152b0e47SKonstantin Porotchkin }
110