staging: ti dspbridge: Rename words with camel case
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / tidspbridge / hw / hw_mmu.c
CommitLineData
5cc28e62
ORL
1/*
2 * hw_mmu.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * API definitions to setup MMU TLB and PTE
7 *
8 * Copyright (C) 2007 Texas Instruments, Inc.
9 *
10 * This package is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 */
18
19#include <GlobalTypes.h>
20#include <linux/io.h>
21#include "MMURegAcM.h"
22#include <hw_defs.h>
23#include <hw_mmu.h>
24#include <linux/types.h>
25
26#define MMU_BASE_VAL_MASK 0xFC00
27#define MMU_PAGE_MAX 3
28#define MMU_ELEMENTSIZE_MAX 3
29#define MMU_ADDR_MASK 0xFFFFF000
30#define MMU_TTB_MASK 0xFFFFC000
31#define MMU_SECTION_ADDR_MASK 0xFFF00000
32#define MMU_SSECTION_ADDR_MASK 0xFF000000
33#define MMU_PAGE_TABLE_MASK 0xFFFFFC00
34#define MMU_LARGE_PAGE_MASK 0xFFFF0000
35#define MMU_SMALL_PAGE_MASK 0xFFFFF000
36
37#define MMU_LOAD_TLB 0x00000001
4574fae5 38#define MMU_GFLUSH 0x60
5cc28e62
ORL
39
40/*
41 * hw_mmu_page_size_t: Enumerated Type used to specify the MMU Page Size(SLSS)
42 */
43enum hw_mmu_page_size_t {
44 HW_MMU_SECTION,
45 HW_MMU_LARGE_PAGE,
46 HW_MMU_SMALL_PAGE,
47 HW_MMU_SUPERSECTION
48};
49
50/*
51 * FUNCTION : mmu_flush_entry
52 *
53 * INPUTS:
54 *
a6bff488 55 * Identifier : base_address
5cc28e62
ORL
56 * Type : const u32
57 * Description : Base Address of instance of MMU module
58 *
59 * RETURNS:
60 *
61 * Type : hw_status
62 * Description : RET_OK -- No errors occured
63 * RET_BAD_NULL_PARAM -- A Pointer
64 * Paramater was set to NULL
65 *
66 * PURPOSE: : Flush the TLB entry pointed by the
67 * lock counter register
68 * even if this entry is set protected
69 *
70 * METHOD: : Check the Input parameter and Flush a
71 * single entry in the TLB.
72 */
a6bff488 73static hw_status mmu_flush_entry(const void __iomem *base_address);
5cc28e62
ORL
74
75/*
76 * FUNCTION : mmu_set_cam_entry
77 *
78 * INPUTS:
79 *
a6bff488 80 * Identifier : base_address
5cc28e62
ORL
81 * TypE : const u32
82 * Description : Base Address of instance of MMU module
83 *
95870a88 84 * Identifier : page_sz
5cc28e62
ORL
85 * TypE : const u32
86 * Description : It indicates the page size
87 *
13b18c29 88 * Identifier : preserved_bit
5cc28e62
ORL
89 * Type : const u32
90 * Description : It indicates the TLB entry is preserved entry
91 * or not
92 *
93 * Identifier : validBit
94 * Type : const u32
95 * Description : It indicates the TLB entry is valid entry or not
96 *
97 *
98 * Identifier : virtual_addr_tag
99 * Type : const u32
100 * Description : virtual Address
101 *
102 * RETURNS:
103 *
104 * Type : hw_status
105 * Description : RET_OK -- No errors occured
106 * RET_BAD_NULL_PARAM -- A Pointer Paramater
107 * was set to NULL
108 * RET_PARAM_OUT_OF_RANGE -- Input Parameter out
109 * of Range
110 *
111 * PURPOSE: : Set MMU_CAM reg
112 *
113 * METHOD: : Check the Input parameters and set the CAM entry.
114 */
a6bff488 115static hw_status mmu_set_cam_entry(const void __iomem *base_address,
95870a88 116 const u32 page_sz,
13b18c29 117 const u32 preserved_bit,
5cc28e62
ORL
118 const u32 validBit,
119 const u32 virtual_addr_tag);
120
121/*
122 * FUNCTION : mmu_set_ram_entry
123 *
124 * INPUTS:
125 *
a6bff488 126 * Identifier : base_address
5cc28e62
ORL
127 * Type : const u32
128 * Description : Base Address of instance of MMU module
129 *
daa89e6c 130 * Identifier : physical_addr
5cc28e62
ORL
131 * Type : const u32
132 * Description : Physical Address to which the corresponding
133 * virtual Address shouldpoint
134 *
135 * Identifier : endianism
136 * Type : hw_endianism_t
137 * Description : endianism for the given page
138 *
139 * Identifier : element_size
140 * Type : hw_element_size_t
141 * Description : The element size ( 8,16, 32 or 64 bit)
142 *
143 * Identifier : mixed_size
144 * Type : hw_mmu_mixed_size_t
145 * Description : Element Size to follow CPU or TLB
146 *
147 * RETURNS:
148 *
149 * Type : hw_status
150 * Description : RET_OK -- No errors occured
151 * RET_BAD_NULL_PARAM -- A Pointer Paramater
152 * was set to NULL
153 * RET_PARAM_OUT_OF_RANGE -- Input Parameter
154 * out of Range
155 *
156 * PURPOSE: : Set MMU_CAM reg
157 *
158 * METHOD: : Check the Input parameters and set the RAM entry.
159 */
a6bff488 160static hw_status mmu_set_ram_entry(const void __iomem *base_address,
daa89e6c 161 const u32 physical_addr,
5cc28e62
ORL
162 enum hw_endianism_t endianism,
163 enum hw_element_size_t element_size,
164 enum hw_mmu_mixed_size_t mixed_size);
165
166/* HW FUNCTIONS */
167
a6bff488 168hw_status hw_mmu_enable(const void __iomem *base_address)
5cc28e62
ORL
169{
170 hw_status status = RET_OK;
171
a6bff488 172 MMUMMU_CNTLMMU_ENABLE_WRITE32(base_address, HW_SET);
5cc28e62
ORL
173
174 return status;
175}
176
a6bff488 177hw_status hw_mmu_disable(const void __iomem *base_address)
5cc28e62
ORL
178{
179 hw_status status = RET_OK;
180
a6bff488 181 MMUMMU_CNTLMMU_ENABLE_WRITE32(base_address, HW_CLEAR);
5cc28e62
ORL
182
183 return status;
184}
185
a6bff488 186hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
95870a88 187 u32 num_locked_entries)
5cc28e62
ORL
188{
189 hw_status status = RET_OK;
190
95870a88 191 MMUMMU_LOCK_BASE_VALUE_WRITE32(base_address, num_locked_entries);
5cc28e62
ORL
192
193 return status;
194}
195
a6bff488 196hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
5cc28e62
ORL
197 u32 victimEntryNum)
198{
199 hw_status status = RET_OK;
200
a6bff488 201 MMUMMU_LOCK_CURRENT_VICTIM_WRITE32(base_address, victimEntryNum);
5cc28e62
ORL
202
203 return status;
204}
205
95870a88 206hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
5cc28e62
ORL
207{
208 hw_status status = RET_OK;
209
95870a88 210 MMUMMU_IRQSTATUS_WRITE_REGISTER32(base_address, irq_mask);
5cc28e62
ORL
211
212 return status;
213}
214
95870a88 215hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
5cc28e62
ORL
216{
217 hw_status status = RET_OK;
218 u32 irq_reg;
219
a6bff488 220 irq_reg = MMUMMU_IRQENABLE_READ_REGISTER32(base_address);
5cc28e62 221
95870a88 222 MMUMMU_IRQENABLE_WRITE_REGISTER32(base_address, irq_reg & ~irq_mask);
5cc28e62
ORL
223
224 return status;
225}
226
95870a88 227hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
5cc28e62
ORL
228{
229 hw_status status = RET_OK;
230 u32 irq_reg;
231
a6bff488 232 irq_reg = MMUMMU_IRQENABLE_READ_REGISTER32(base_address);
5cc28e62 233
95870a88 234 MMUMMU_IRQENABLE_WRITE_REGISTER32(base_address, irq_reg | irq_mask);
5cc28e62
ORL
235
236 return status;
237}
238
95870a88 239hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
5cc28e62
ORL
240{
241 hw_status status = RET_OK;
242
95870a88 243 *irq_mask = MMUMMU_IRQSTATUS_READ_REGISTER32(base_address);
5cc28e62
ORL
244
245 return status;
246}
247
a6bff488 248hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
5cc28e62
ORL
249{
250 hw_status status = RET_OK;
251
252 /*Check the input Parameters */
a6bff488 253 CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
5cc28e62
ORL
254 RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
255
256 /* read values from register */
a6bff488 257 *addr = MMUMMU_FAULT_AD_READ_REGISTER32(base_address);
5cc28e62
ORL
258
259 return status;
260}
261
0cd343a4 262hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
5cc28e62
ORL
263{
264 hw_status status = RET_OK;
265 u32 load_ttb;
266
267 /*Check the input Parameters */
a6bff488 268 CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
5cc28e62
ORL
269 RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
270
0cd343a4 271 load_ttb = ttb_phys_addr & ~0x7FUL;
5cc28e62 272 /* write values to register */
a6bff488 273 MMUMMU_TTB_WRITE_REGISTER32(base_address, load_ttb);
5cc28e62
ORL
274
275 return status;
276}
277
a6bff488 278hw_status hw_mmu_twl_enable(const void __iomem *base_address)
5cc28e62
ORL
279{
280 hw_status status = RET_OK;
281
a6bff488 282 MMUMMU_CNTLTWL_ENABLE_WRITE32(base_address, HW_SET);
5cc28e62
ORL
283
284 return status;
285}
286
a6bff488 287hw_status hw_mmu_twl_disable(const void __iomem *base_address)
5cc28e62
ORL
288{
289 hw_status status = RET_OK;
290
a6bff488 291 MMUMMU_CNTLTWL_ENABLE_WRITE32(base_address, HW_CLEAR);
5cc28e62
ORL
292
293 return status;
294}
295
a6bff488 296hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtualAddr,
95870a88 297 u32 page_sz)
5cc28e62
ORL
298{
299 hw_status status = RET_OK;
300 u32 virtual_addr_tag;
301 enum hw_mmu_page_size_t pg_size_bits;
302
95870a88 303 switch (page_sz) {
5cc28e62
ORL
304 case HW_PAGE_SIZE4KB:
305 pg_size_bits = HW_MMU_SMALL_PAGE;
306 break;
307
308 case HW_PAGE_SIZE64KB:
309 pg_size_bits = HW_MMU_LARGE_PAGE;
310 break;
311
312 case HW_PAGE_SIZE1MB:
313 pg_size_bits = HW_MMU_SECTION;
314 break;
315
316 case HW_PAGE_SIZE16MB:
317 pg_size_bits = HW_MMU_SUPERSECTION;
318 break;
319
320 default:
321 return RET_FAIL;
322 }
323
324 /* Generate the 20-bit tag from virtual address */
325 virtual_addr_tag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
326
a6bff488 327 mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag);
5cc28e62 328
a6bff488 329 mmu_flush_entry(base_address);
5cc28e62
ORL
330
331 return status;
332}
333
a6bff488 334hw_status hw_mmu_tlb_add(const void __iomem *base_address,
daa89e6c 335 u32 physical_addr,
5cc28e62 336 u32 virtualAddr,
95870a88 337 u32 page_sz,
b301c858 338 u32 entry_num,
5cc28e62 339 struct hw_mmu_map_attrs_t *map_attrs,
13b18c29 340 s8 preserved_bit, s8 validBit)
5cc28e62
ORL
341{
342 hw_status status = RET_OK;
343 u32 lock_reg;
344 u32 virtual_addr_tag;
345 enum hw_mmu_page_size_t mmu_pg_size;
346
347 /*Check the input Parameters */
a6bff488 348 CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
5cc28e62 349 RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
95870a88 350 CHECK_INPUT_RANGE_MIN0(page_sz, MMU_PAGE_MAX, RET_PARAM_OUT_OF_RANGE,
5cc28e62
ORL
351 RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
352 CHECK_INPUT_RANGE_MIN0(map_attrs->element_size, MMU_ELEMENTSIZE_MAX,
353 RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
354 RES_INVALID_INPUT_PARAM);
355
95870a88 356 switch (page_sz) {
5cc28e62
ORL
357 case HW_PAGE_SIZE4KB:
358 mmu_pg_size = HW_MMU_SMALL_PAGE;
359 break;
360
361 case HW_PAGE_SIZE64KB:
362 mmu_pg_size = HW_MMU_LARGE_PAGE;
363 break;
364
365 case HW_PAGE_SIZE1MB:
366 mmu_pg_size = HW_MMU_SECTION;
367 break;
368
369 case HW_PAGE_SIZE16MB:
370 mmu_pg_size = HW_MMU_SUPERSECTION;
371 break;
372
373 default:
374 return RET_FAIL;
375 }
376
a6bff488 377 lock_reg = MMUMMU_LOCK_READ_REGISTER32(base_address);
5cc28e62
ORL
378
379 /* Generate the 20-bit tag from virtual address */
380 virtual_addr_tag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
381
382 /* Write the fields in the CAM Entry Register */
13b18c29 383 mmu_set_cam_entry(base_address, mmu_pg_size, preserved_bit, validBit,
5cc28e62
ORL
384 virtual_addr_tag);
385
386 /* Write the different fields of the RAM Entry Register */
387 /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit) */
daa89e6c 388 mmu_set_ram_entry(base_address, physical_addr, map_attrs->endianism,
5cc28e62
ORL
389 map_attrs->element_size, map_attrs->mixed_size);
390
391 /* Update the MMU Lock Register */
392 /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1) */
b301c858 393 MMUMMU_LOCK_CURRENT_VICTIM_WRITE32(base_address, entry_num);
5cc28e62
ORL
394
395 /* Enable loading of an entry in TLB by writing 1
396 into LD_TLB_REG register */
a6bff488 397 MMUMMU_LD_TLB_WRITE_REGISTER32(base_address, MMU_LOAD_TLB);
5cc28e62 398
a6bff488 399 MMUMMU_LOCK_WRITE_REGISTER32(base_address, lock_reg);
5cc28e62
ORL
400
401 return status;
402}
403
404hw_status hw_mmu_pte_set(const u32 pg_tbl_va,
daa89e6c 405 u32 physical_addr,
5cc28e62 406 u32 virtualAddr,
95870a88 407 u32 page_sz, struct hw_mmu_map_attrs_t *map_attrs)
5cc28e62
ORL
408{
409 hw_status status = RET_OK;
410 u32 pte_addr, pte_val;
411 s32 num_entries = 1;
412
95870a88 413 switch (page_sz) {
5cc28e62
ORL
414 case HW_PAGE_SIZE4KB:
415 pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va,
416 virtualAddr &
417 MMU_SMALL_PAGE_MASK);
418 pte_val =
daa89e6c 419 ((physical_addr & MMU_SMALL_PAGE_MASK) |
5cc28e62
ORL
420 (map_attrs->endianism << 9) | (map_attrs->
421 element_size << 4) |
422 (map_attrs->mixed_size << 11) | 2);
423 break;
424
425 case HW_PAGE_SIZE64KB:
426 num_entries = 16;
427 pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va,
428 virtualAddr &
429 MMU_LARGE_PAGE_MASK);
430 pte_val =
daa89e6c 431 ((physical_addr & MMU_LARGE_PAGE_MASK) |
5cc28e62
ORL
432 (map_attrs->endianism << 9) | (map_attrs->
433 element_size << 4) |
434 (map_attrs->mixed_size << 11) | 1);
435 break;
436
437 case HW_PAGE_SIZE1MB:
438 pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va,
439 virtualAddr &
440 MMU_SECTION_ADDR_MASK);
441 pte_val =
daa89e6c 442 ((((physical_addr & MMU_SECTION_ADDR_MASK) |
5cc28e62
ORL
443 (map_attrs->endianism << 15) | (map_attrs->
444 element_size << 10) |
445 (map_attrs->mixed_size << 17)) & ~0x40000) | 0x2);
446 break;
447
448 case HW_PAGE_SIZE16MB:
449 num_entries = 16;
450 pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va,
451 virtualAddr &
452 MMU_SSECTION_ADDR_MASK);
453 pte_val =
daa89e6c 454 (((physical_addr & MMU_SSECTION_ADDR_MASK) |
5cc28e62
ORL
455 (map_attrs->endianism << 15) | (map_attrs->
456 element_size << 10) |
457 (map_attrs->mixed_size << 17)
458 ) | 0x40000 | 0x2);
459 break;
460
461 case HW_MMU_COARSE_PAGE_SIZE:
462 pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va,
463 virtualAddr &
464 MMU_SECTION_ADDR_MASK);
daa89e6c 465 pte_val = (physical_addr & MMU_PAGE_TABLE_MASK) | 1;
5cc28e62
ORL
466 break;
467
468 default:
469 return RET_FAIL;
470 }
471
472 while (--num_entries >= 0)
473 ((u32 *) pte_addr)[num_entries] = pte_val;
474
475 return status;
476}
477
478hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtualAddr, u32 page_size)
479{
480 hw_status status = RET_OK;
481 u32 pte_addr;
482 s32 num_entries = 1;
483
484 switch (page_size) {
485 case HW_PAGE_SIZE4KB:
486 pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va,
487 virtualAddr &
488 MMU_SMALL_PAGE_MASK);
489 break;
490
491 case HW_PAGE_SIZE64KB:
492 num_entries = 16;
493 pte_addr = hw_mmu_pte_addr_l2(pg_tbl_va,
494 virtualAddr &
495 MMU_LARGE_PAGE_MASK);
496 break;
497
498 case HW_PAGE_SIZE1MB:
499 case HW_MMU_COARSE_PAGE_SIZE:
500 pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va,
501 virtualAddr &
502 MMU_SECTION_ADDR_MASK);
503 break;
504
505 case HW_PAGE_SIZE16MB:
506 num_entries = 16;
507 pte_addr = hw_mmu_pte_addr_l1(pg_tbl_va,
508 virtualAddr &
509 MMU_SSECTION_ADDR_MASK);
510 break;
511
512 default:
513 return RET_FAIL;
514 }
515
516 while (--num_entries >= 0)
517 ((u32 *) pte_addr)[num_entries] = 0;
518
519 return status;
520}
521
522/* mmu_flush_entry */
a6bff488 523static hw_status mmu_flush_entry(const void __iomem *base_address)
5cc28e62
ORL
524{
525 hw_status status = RET_OK;
526 u32 flush_entry_data = 0x1;
527
528 /*Check the input Parameters */
a6bff488 529 CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
5cc28e62
ORL
530 RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
531
532 /* write values to register */
a6bff488 533 MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data);
5cc28e62
ORL
534
535 return status;
536}
537
538/* mmu_set_cam_entry */
a6bff488 539static hw_status mmu_set_cam_entry(const void __iomem *base_address,
95870a88 540 const u32 page_sz,
13b18c29 541 const u32 preserved_bit,
5cc28e62
ORL
542 const u32 validBit,
543 const u32 virtual_addr_tag)
544{
545 hw_status status = RET_OK;
546 u32 mmu_cam_reg;
547
548 /*Check the input Parameters */
a6bff488 549 CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
5cc28e62
ORL
550 RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
551
552 mmu_cam_reg = (virtual_addr_tag << 12);
95870a88 553 mmu_cam_reg = (mmu_cam_reg) | (page_sz) | (validBit << 2) |
13b18c29 554 (preserved_bit << 3);
5cc28e62
ORL
555
556 /* write values to register */
a6bff488 557 MMUMMU_CAM_WRITE_REGISTER32(base_address, mmu_cam_reg);
5cc28e62
ORL
558
559 return status;
560}
561
562/* mmu_set_ram_entry */
a6bff488 563static hw_status mmu_set_ram_entry(const void __iomem *base_address,
daa89e6c 564 const u32 physical_addr,
5cc28e62
ORL
565 enum hw_endianism_t endianism,
566 enum hw_element_size_t element_size,
567 enum hw_mmu_mixed_size_t mixed_size)
568{
569 hw_status status = RET_OK;
570 u32 mmu_ram_reg;
571
572 /*Check the input Parameters */
a6bff488 573 CHECK_INPUT_PARAM(base_address, 0, RET_BAD_NULL_PARAM,
5cc28e62
ORL
574 RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
575 CHECK_INPUT_RANGE_MIN0(element_size, MMU_ELEMENTSIZE_MAX,
576 RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
577 RES_INVALID_INPUT_PARAM);
578
daa89e6c 579 mmu_ram_reg = (physical_addr & MMU_ADDR_MASK);
5cc28e62
ORL
580 mmu_ram_reg = (mmu_ram_reg) | ((endianism << 9) | (element_size << 7) |
581 (mixed_size << 6));
582
583 /* write values to register */
a6bff488 584 MMUMMU_RAM_WRITE_REGISTER32(base_address, mmu_ram_reg);
5cc28e62
ORL
585
586 return status;
587
588}
4574fae5
FC
589
590void hw_mmu_tlb_flush_all(const void __iomem *base)
591{
592 __raw_writeb(1, base + MMU_GFLUSH);
593}