MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / net / ks8695 / ks8695_cache.c
blob0a95a326252f5ead2cb1bb2b561f1169c4a29c76
1 /*
2 Copyright (c) 2002, Micrel Kendin Operations
4 Written 2002 by LIQUN RUAN
6 This software may be used and distributed according to the terms of
7 the GNU General Public License (GPL), incorporated herein by reference.
8 Drivers based on or derived from this code fall under the GPL and must
9 retain the authorship, copyright and license notice. This file is not
10 a complete program and may only be used when the entire operating
11 system is licensed under the GPL.
13 The author may be reached as lruan@kendin.com
14 Micrel Kendin Operations
15 486 Mercury Dr.
16 Sunnyvale, CA 94085
18 This driver is for Kendin's KS8695 SOHO Router Chipset as ethernet driver.
20 Support and updates available at
21 www.kendin.com or www.micrel.com
24 #include "ks8695_drv.h"
25 #include "ks8695_cache.h"
27 /* for 922T, the values are fixed */
28 #if 0
29 static uint32_t uICacheLineLen = 8; /* 8 dwords, 32 bytes */
30 static uint32_t uICacheSize = 8192; /* 8K cache size */
31 #endif
33 static uint32_t bPowerSaving = FALSE;
34 static uint32_t bAllowPowerSaving = FALSE;
37 * ks8695_icache_read_c9
38 * This function is use to read lockdown register
40 * Argument(s)
41 * NONE
43 * Return(s)
44 * NONE
46 void ks8695_icache_read_c9(void)
48 register int base;
50 __asm__(
51 "mrc p15, 0, %0, c9, c0, 1"
52 : "=r" (base)
55 DRV_INFO("%s: lockdown index=%d", __FUNCTION__, (base >> 26));
58 #if 0
60 * ks8695_icache_lock
61 * This function is use to lock given icache
63 * Argument(s)
64 * icache_start pointer to starting icache address
65 * icache_end pointer to ending icache address
67 * Return(s)
68 * 0 if success
69 * error otherwise
71 int ks8695_icache_lock(void *icache_start, void *icache_end)
73 uint32_t victim_base = (ICACHE_VICTIM_BASE << ICACHE_VICTIM_INDEX);
74 int len;
75 spinlock_t lock = SPIN_LOCK_UNLOCKED;
76 unsigned long flags;
78 len = (int)(icache_end - icache_start);
79 DRV_INFO("%s: start=%p, end=%p, len=%d, victim=0x%x", __FUNCTION__, icache_start, icache_end, len, victim_base);
81 /* if lockdown lines are more than half of max associtivity */
82 if ((len / ICACHE_BYTES_PER_LINE) > (ICACHE_ASSOCITIVITY >> 1)) {
83 DRV_WARN("%s: lockdown lines = %d is too many, (Assoc=%d)", __FUNCTION__, (len / ICACHE_BYTES_PER_LINE), ICACHE_ASSOCITIVITY);
84 return -1;
87 spin_lock_irqsave(&lock, flags);
89 __asm__(
90 " \n\
91 ADRL r0, ks8695_isr \n\
92 ADRL r1, ks8695_isre \n\
93 MOV r2, %1 \n\
94 MCR p15, 0, r2, c9, c4, 1 \n\
95 lock_loop: \n\
96 MCR p15, 0, r0, c7, c13, 1 \n\
97 ADD r0, r0, #32 \n\
98 \n\
99 AND r3, r0, #0x60 \n\
100 CMP r3, #0x0 \n\
101 ADDEQ r2, r2, #0x1<<26 \n\
102 MCREQ p15, 0, r2, c9, c0, 1 \n\
104 CMP r0, r1 \n\
105 BLE lock_loop \n\
107 CMP r3, #0x0 \n\
108 ADDNE r2, r2, #0x1<<26 \n\
109 MCRNE p15, 0, r2, c9, c0, 1 \n\
111 : "=r" (len)
112 : "r" (victim_base)
113 : "r0", "r1", "r2", "r3"
116 ks8695_icache_read_c9();
118 #if 0
119 /* following are the assemble code for icache lock down, a C version should be implemented, accordingly */
120 ADRL r0, start_address ; address pointer
121 ADRL r1, end_address
122 MOV r2, #lockdown_base<<26 ; victim pointer
123 MCR p15, 0, r2, c9, c0, 1
125 loop
126 MCR p15, 0, r0, c7, c13, 1 ; prefetch ICache line
127 ADD r0, r0, #32 ; increment address pointer to next ICache line
129 ; do we need to increment the victim pointer ?
130 ; thest for segment 0, and if so, increment the victim pointer
131 ; and write the Icache victime and lockdown base
133 AND r3, r0, #0x60 ; extract the segment bits from the addr.
134 CMP r3, #0x0 ; test the segment
135 ADDEQ r2, r2, #0x1<<26 ; if segment 0, increment victim pointer
136 MCREQ p15, 0, r2, c9, c0, 1 ; and write ICaceh victim and lockdown
138 ; have we linefilled enough code?
139 ; test for the address pointer being less than or equal to the end_address
140 ; pointer and if so, loop and perform another linefill
142 CMP r0, r1 ; test for less than or equal to end_address
143 BLE loop ; if not, loop
145 ; have we exited with r3 pointer to segment 0?
146 ; if so, the ICaceh victim and lockdown base has already been set to one higher
147 ; than the last entry written.
148 ; if not, increment the victim pointer and write the ICache victim and
149 ; lockdown base.
151 CMP r3, #0x0 ; test for segments 1 to 3
152 ADDNE r2, r2, #0x1 << 26 ; if address is segment 1 to 3
153 MCRNE p15, 0, r2, c9, c0, 1 ; write ICache victim and lockdown base.
155 #endif
157 spin_unlock_irqrestore(&lock, flags);
159 return 0;
161 #endif
164 * ks8695_icache_unlock
165 * This function is use to unlock the icache locked previously
167 * Argument(s)
168 * NONE.
170 * Return(s)
171 * NONE.
173 void ks8695_icache_unlock(void)
175 #ifdef DEBUG_THIS
176 DRV_INFO("%s", __FUNCTION__);
177 #endif
179 __asm__(
180 " \n\
181 MOV r1, #0 \n\
182 MCR p15, 0, r1, c9, c0, 1 /* reset victim base to 0 */ \n\
186 DRV_INFO("%s", __FUNCTION__);
190 * ks8695_icache_change_policy
191 * This function is use to change cache policy for ARM chipset
193 * Argument(s)
194 * bRoundRobin round robin or random mode
196 * Return(s)
197 * NONE
199 void ks8695_icache_change_policy(int bRoundRobin)
201 uint32_t tmp;
203 __asm__ (
204 " \n\
205 mrc p15, 0, r1, c1, c0, 0 \n\
206 mov r2, %1 \n\
207 cmp r2, #0 \n\
208 orrne r1, r1, #0x4000 \n\
209 biceq r1, r1, #0x4000 \n\
210 mov %0, r1 \n\
211 /* Write this to the control register */ \n\
212 mcr p15, 0, r1, c1, c0, 0 \n\
213 /* Make sure the pipeline is clear of any cached entries */ \n\
214 nop \n\
215 nop \n\
216 nop"
217 : "=r" (tmp)
218 : "r" (bRoundRobin)
219 : "r1", "r2"
222 /*#ifdef DEBUG_THIS*/
223 DRV_INFO("Icache mode = %s", bRoundRobin ? "roundrobin" : "random");
224 /*#endif*/
228 * ks8695_enable_power_saving
229 * This function is use to enable/disable power saving
231 * Argument(s)
232 * bSaving
234 * Return(s)
235 * NONE
237 void ks8695_enable_power_saving(int bEnablePowerSaving)
239 bAllowPowerSaving = bEnablePowerSaving;
243 * ks8695_power_saving
244 * This function is use to put ARM chipset in low power mode (wait for interrupt)
246 * Argument(s)
247 * bSaving
249 * Return(s)
250 * NONE
252 void ks8695_power_saving(int bSaving)
254 uint32_t tmp;
256 /* if not allowed by configuration option */
257 if (!bAllowPowerSaving)
258 return;
260 /* if already set */
261 if (bPowerSaving == bSaving)
262 return;
264 bPowerSaving = bSaving;
266 __asm__ (
267 " \n\
268 mov r1, %1 \n\
269 mcr p15, 0, r1, c7, c0, 4 \n\
270 /* Make sure the pipeline is clear of any cached entries */ \n\
271 nop \n\
272 nop \n\
273 nop"
274 : "=r" (tmp)
275 : "r" (bSaving)
276 : "r1", "r2"
279 DRV_INFO("%s: power saving = %s", __FUNCTION__, bSaving ? "enabled" : "disabled");