blob: cd062d28aef507fc7b25b0d88443ef3e0b3c528e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/*
* Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
* The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
* http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html
*/
/*!
* @file mxc_vl2cc.c
*
* @brief VL2CC initialization and flush operation implementation
*
* @ingroup VL2CC
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm/hardware.h>
#include <asm/io.h>
#define VL2CC_CTRL_OFFSET (0x100)
#define VL2CC_AUXCTRL_OFFSET (0x104)
#define VL2CC_INVWAY_OFFSET (0x77C)
#define VL2CC_CLEANWAY_OFFSET (0x7BC)
/*! VL2CC clock handle. */
static struct clk *vl2cc_clk;
static u32 *vl2cc_base;
/*!
* Initialization function of VL2CC. Remap the VL2CC base address.
*
* @return status 0 success.
*/
int vl2cc_init(u32 vl2cc_hw_base)
{
vl2cc_base = ioremap(vl2cc_hw_base, SZ_8K - 1);
if (vl2cc_base == NULL) {
printk(KERN_INFO "vl2cc: Unable to ioremap\n");
return -ENOMEM;
}
vl2cc_clk = clk_get(NULL, "vl2cc_clk");
if (IS_ERR(vl2cc_clk)) {
printk(KERN_INFO "vl2cc: Unable to get clock\n");
iounmap(vl2cc_base);
return -EIO;
}
printk(KERN_INFO "VL2CC initialized\n");
return 0;
}
/*!
* Enable VL2CC hardware
*/
void vl2cc_enable(void)
{
volatile u32 reg;
clk_enable(vl2cc_clk);
/* Disable VL2CC */
reg = __raw_readl(vl2cc_base + VL2CC_CTRL_OFFSET);
reg &= 0xFFFFFFFE;
__raw_writel(reg, vl2cc_base + VL2CC_CTRL_OFFSET);
/* Set the latency for data RAM reads, data RAM writes, tag RAM and
* dirty RAM to 1 cycle - write 0x0 to AUX CTRL [11:0] and also
* configure the number of ways to 8 - write 8 to AUX CTRL [16:13]
*/
reg = __raw_readl(vl2cc_base + VL2CC_AUXCTRL_OFFSET);
reg &= 0xFFFE1000; /* Clear [16:13] too */
reg |= (0x8 << 13); /* [16:13] = 8; */
__raw_writel(reg, vl2cc_base + VL2CC_AUXCTRL_OFFSET);
/* Invalidate the VL2CC ways - write 0xff to INV BY WAY and poll the
* register until its value is 0x0
*/
__raw_writel(0xff, vl2cc_base + VL2CC_INVWAY_OFFSET);
while (__raw_readl(vl2cc_base + VL2CC_INVWAY_OFFSET) != 0x0) ;
/* Enable VL2CC */
reg = __raw_readl(vl2cc_base + VL2CC_CTRL_OFFSET);
reg |= 0x1;
__raw_writel(reg, vl2cc_base + VL2CC_CTRL_OFFSET);
}
/*!
* Flush VL2CC
*/
void vl2cc_flush(void)
{
__raw_writel(0xff, vl2cc_base + VL2CC_CLEANWAY_OFFSET);
while (__raw_readl(vl2cc_base + VL2CC_CLEANWAY_OFFSET) != 0x0) ;
}
/*!
* Disable VL2CC
*/
void vl2cc_disable(void)
{
__raw_writel(0, vl2cc_base + VL2CC_CTRL_OFFSET);
clk_disable(vl2cc_clk);
}
/*!
* Cleanup VL2CC
*/
void vl2cc_cleanup(void)
{
clk_put(vl2cc_clk);
iounmap(vl2cc_base);
}
|