1 #include <linux/module.h>
2 #include <linux/interrupt.h>
5 #include "mach/mt_reg_base.h"
6 #include "mach/sync_write.h"
7 #include "asm/cacheflush.h"
9 /* config L2 to its size */
10 extern int config_L2(int size
);
11 extern void __inner_flush_dcache_all(void);
12 extern void __inner_flush_dcache_L1(void);
13 extern void __inner_flush_dcache_L2(void);
14 extern void __disable_cache(void);
15 extern void __enable_cache(void);
16 void inner_dcache_flush_all(void);
17 void inner_dcache_flush_L1(void);
18 void inner_dcache_flush_L2(void);
19 #define L2C_SIZE_CFG_OFF 5
20 #define L2C_DCM_CFG_OFF 8
21 #define INFRA_DCM_CFG_OFF 9
23 static DEFINE_SPINLOCK(cache_cfg_lock
);
24 static DEFINE_SPINLOCK(cache_cfg1_lock
);
25 /* config L2 cache and sram to its size */
26 int config_L2_size(int size
)
28 volatile unsigned int cache_cfg
, ret
= 1;
29 /* set L2C size to 128KB */
30 spin_lock(&cache_cfg_lock
);
31 cache_cfg
= readl(IOMEM(MCUSYS_CFGREG_BASE
));
32 if (size
== SZ_256K
) {
33 cache_cfg
&= (~0x7) << L2C_SIZE_CFG_OFF
;
34 cache_cfg
|= 0x1 << L2C_SIZE_CFG_OFF
;
35 mt65xx_reg_sync_writel(cache_cfg
, MCUSYS_CFGREG_BASE
);
36 } else if (size
== SZ_512K
) {
37 cache_cfg
&= (~0x7) << L2C_SIZE_CFG_OFF
;
38 cache_cfg
|= 0x3 << L2C_SIZE_CFG_OFF
;
39 mt65xx_reg_sync_writel(cache_cfg
, MCUSYS_CFGREG_BASE
);
43 spin_unlock(&cache_cfg_lock
);
47 int get_l2c_size(void)
49 volatile unsigned int cache_cfg
;
51 cache_cfg
= readl(IOMEM(MCUSYS_CFGREG_BASE
));
52 cache_cfg
= cache_cfg
>> L2C_SIZE_CFG_OFF
;
53 cache_cfg
= cache_cfg
& 0x7;
56 else if (cache_cfg
== 1)
58 else if (cache_cfg
== 3)
60 else if (cache_cfg
== 7)
67 atomic_t L1_flush_done
= ATOMIC_INIT(0);
68 extern int __is_dcache_enable(void);
69 extern int cr_alignment
;
71 void atomic_flush(void)
74 inner_dcache_flush_L1();
76 atomic_inc(&L1_flush_done
);
77 //update cr_alignment for other kernel function usage
78 cr_alignment
= cr_alignment
& ~(0x4); //C1_CBIT
81 int config_L2(int size
)
83 int cur_size
= get_l2c_size();
84 if (size
!= SZ_256K
&& size
!= SZ_512K
) {
85 printk("inlvalid input size %x\n", size
);
89 printk(KERN_ERR
"Cannot use %s in interrupt/softirq context\n",
93 if (size
== cur_size
) {
94 printk("Config L2 size %x is equal to current L2 size %x\n",
99 atomic_set(&L1_flush_done
, 0);
101 //printk("[Config L2] Config L2 start, on line cpu = %d\n",num_online_cpus());
103 /* disable cache and flush L1 */
104 on_each_cpu((smp_call_func_t
)atomic_flush
, NULL
, true);
105 //while(atomic_read(&L1_flush_done) != num_online_cpus());
106 //printk("[Config L2] L1 flush done\n");
109 inner_dcache_flush_L2();
110 //printk("[Config L2] L2 flush done\n");
113 config_L2_size(size
);
114 //printk("[Config L2] Change L2 flush size done(size = %d)\n",size);
117 atomic_set(&L1_flush_done
, 0);
118 on_each_cpu((smp_call_func_t
)__enable_cache
, NULL
, true);
120 //update cr_alignment for other kernel function usage
121 cr_alignment
= cr_alignment
| (0x4); //C1_CBIT
123 printk("Config L2 size %x done\n", size
);
127 #include <linux/device.h>
128 #include <linux/platform_device.h>
129 static struct device_driver mt_l2c_drv
= {
131 .bus
= &platform_bus_type
,
132 .owner
= THIS_MODULE
,
135 int mt_l2c_get_status(void)
137 unsigned int size
, cache_cfg
;
138 cache_cfg
= readl(IOMEM(MCUSYS_CFGREG_BASE
));
139 cache_cfg
= cache_cfg
>> L2C_SIZE_CFG_OFF
;
141 if (cache_cfg
== 1) {
144 } else if (cache_cfg
== 3) {
149 printk("Wrong cache_cfg = %x, size = %d\n", cache_cfg
, size
);
155 * cur_l2c_show: To show cur_l2c size.
157 static ssize_t
cur_l2c_show(struct device_driver
*driver
, char *buf
)
161 size
= mt_l2c_get_status();
162 return snprintf(buf
, PAGE_SIZE
, "%d\n", size
);
166 * cur_l2c_store: To set cur_l2c size.
168 static ssize_t
cur_l2c_store(struct device_driver
*driver
, const char *buf
,
171 char *p
= (char *)buf
;
174 size
= simple_strtoul(p
, &p
, 10);
177 } else if (size
== 512) {
180 printk("invalid size value: %d\n", size
);
184 ret
= config_L2(size
);
186 printk("Config L2 error ret:%d size value: %d\n", ret
, size
);
190 DRIVER_ATTR(current_l2c
, 0644, cur_l2c_show
, cur_l2c_store
);
192 * mt_l2c_init: initialize l2c driver.
195 int mt_l2c_init(void)
199 ret
= driver_register(&mt_l2c_drv
);
201 printk("fail to register mt_l2c_drv\n");
204 ret
= driver_create_file(&mt_l2c_drv
, &driver_attr_current_l2c
);
206 printk("fail to create mt_l2c sysfs files\n");
211 arch_initcall(mt_l2c_init
);
213 /* To disable/enable auto invalidate cache API
214 @ disable == 1 to disable auto invalidate cache
215 @ disable == 0 to enable auto invalidate cache
216 return 0 -> success, -1 -> fail
218 int auto_inv_cache(unsigned int disable
)
220 volatile unsigned int cache_cfg
, cache_cfg_new
;
221 spin_lock(&cache_cfg1_lock
);
223 /* set cache auto disable */
224 cache_cfg
= readl(IOMEM(MCUSYS_CFGREG_BASE
));
226 writel(cache_cfg
, IOMEM(MCUSYS_CFGREG_BASE
));
227 } else if (disable
== 0){
228 /* set cache auto enable */
229 cache_cfg
= readl(IOMEM(MCUSYS_CFGREG_BASE
));
231 writel(cache_cfg
, IOMEM(MCUSYS_CFGREG_BASE
));
233 printk("Caller give a wrong arg:%d\n", disable
);
234 spin_unlock(&cache_cfg1_lock
);
237 cache_cfg_new
= readl(IOMEM(MCUSYS_CFGREG_BASE
));
238 spin_unlock(&cache_cfg1_lock
);
239 if((cache_cfg_new
& 0x1F) != (cache_cfg
& 0x1F))
245 EXPORT_SYMBOL(config_L2
);