]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/media/atomisp/pci/atomisp2/mmu/isp_mmu.c
scsi: cxgb4i: libcxgbi: in error case RST tcp conn
[karo-tx-linux.git] / drivers / staging / media / atomisp / pci / atomisp2 / mmu / isp_mmu.c
1 /*
2  * Support for Medifield PNW Camera Imaging ISP subsystem.
3  *
4  * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
5  *
6  * Copyright (c) 2010 Silicon Hive www.siliconhive.com.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version
10  * 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  * 02110-1301, USA.
21  *
22  */
23 /*
24  * ISP MMU management wrap code
25  */
26 #include <linux/kernel.h>
27 #include <linux/types.h>
28 #include <linux/gfp.h>
29 #include <linux/mm.h>           /* for GFP_ATOMIC */
30 #include <linux/slab.h>         /* for kmalloc */
31 #include <linux/list.h>
32 #include <linux/io.h>
33 #include <asm/cacheflush.h>
34 #include <linux/module.h>
35 #include <linux/moduleparam.h>
36 #include <linux/string.h>
37 #include <linux/errno.h>
38 #include <linux/sizes.h>
39
40 #include "atomisp_internal.h"
41 #include "mmu/isp_mmu.h"
42
43 /*
44  * 64-bit x86 processor physical address layout:
45  * 0            - 0x7fffffff            DDR RAM (2GB)
46  * 0x80000000   - 0xffffffff            MMIO    (2GB)
47  * 0x100000000  - 0x3fffffffffff        DDR RAM (64TB)
48  * So if the system has more than 2GB DDR memory, the lower 2GB occupies the
49  * physical address 0 - 0x7fffffff and the rest will start from 0x100000000.
50  * We have to make sure memory is allocated from the lower 2GB for devices
51  * that are only 32-bit capable(e.g. the ISP MMU).
52  *
53  * For any confusion, contact bin.gao@intel.com.
54  */
55 #define NR_PAGES_2GB    (SZ_2G / PAGE_SIZE)
56
57 static void free_mmu_map(struct isp_mmu *mmu, unsigned int start_isp_virt,
58                                 unsigned int end_isp_virt);
59
60 static unsigned int atomisp_get_pte(phys_addr_t pt, unsigned int idx)
61 {
62         unsigned int *pt_virt = phys_to_virt(pt);
63         return *(pt_virt + idx);
64 }
65
66 static void atomisp_set_pte(phys_addr_t pt,
67                             unsigned int idx, unsigned int pte)
68 {
69         unsigned int *pt_virt = phys_to_virt(pt);
70         *(pt_virt + idx) = pte;
71 }
72
73 static void *isp_pt_phys_to_virt(phys_addr_t phys)
74 {
75         return phys_to_virt(phys);
76 }
77
78 static phys_addr_t isp_pte_to_pgaddr(struct isp_mmu *mmu,
79                                      unsigned int pte)
80 {
81         return mmu->driver->pte_to_phys(mmu, pte);
82 }
83
84 static unsigned int isp_pgaddr_to_pte_valid(struct isp_mmu *mmu,
85                                             phys_addr_t phys)
86 {
87         unsigned int pte = mmu->driver->phys_to_pte(mmu, phys);
88         return (unsigned int) (pte | ISP_PTE_VALID_MASK(mmu));
89 }
90
91 /*
92  * allocate a uncacheable page table.
93  * return physical address.
94  */
95 static phys_addr_t alloc_page_table(struct isp_mmu *mmu)
96 {
97         int i;
98         phys_addr_t page;
99         void *virt;
100
101         /*page table lock may needed here*/
102         /*
103          * The slab allocator(kmem_cache and kmalloc family) doesn't handle
104          * GFP_DMA32 flag, so we have to use buddy allocator.
105          */
106         if (totalram_pages > (unsigned long)NR_PAGES_2GB)
107                 virt = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
108         else
109                 virt = kmem_cache_zalloc(mmu->tbl_cache, GFP_KERNEL);
110         if (!virt)
111                 return (phys_addr_t)NULL_PAGE;
112
113         /*
114          * we need a uncacheable page table.
115          */
116 #ifdef  CONFIG_X86
117         set_memory_uc((unsigned long)virt, 1);
118 #endif
119
120         page = virt_to_phys(virt);
121
122         for (i = 0; i < 1024; i++) {
123                 /* NEED CHECK */
124                 atomisp_set_pte(page, i, mmu->driver->null_pte);
125         }
126
127         return page;
128 }
129
130 static void free_page_table(struct isp_mmu *mmu, phys_addr_t page)
131 {
132         void *virt;
133         page &= ISP_PAGE_MASK;
134         /*
135          * reset the page to write back before free
136          */
137         virt = phys_to_virt(page);
138
139 #ifdef  CONFIG_X86
140         set_memory_wb((unsigned long)virt, 1);
141 #endif
142
143         kmem_cache_free(mmu->tbl_cache, virt);
144 }
145
146 static void mmu_remap_error(struct isp_mmu *mmu,
147                             phys_addr_t l1_pt, unsigned int l1_idx,
148                             phys_addr_t l2_pt, unsigned int l2_idx,
149                             unsigned int isp_virt, phys_addr_t old_phys,
150                             phys_addr_t new_phys)
151 {
152         dev_err(atomisp_dev, "address remap:\n\n"
153                      "\tL1 PT: virt = %p, phys = 0x%llx, "
154                      "idx = %d\n"
155                      "\tL2 PT: virt = %p, phys = 0x%llx, "
156                      "idx = %d\n"
157                      "\told: isp_virt = 0x%x, phys = 0x%llx\n"
158                      "\tnew: isp_virt = 0x%x, phys = 0x%llx\n",
159                      isp_pt_phys_to_virt(l1_pt),
160                      (u64)l1_pt, l1_idx,
161                      isp_pt_phys_to_virt(l2_pt),
162                      (u64)l2_pt, l2_idx, isp_virt,
163                      (u64)old_phys, isp_virt,
164                      (u64)new_phys);
165 }
166
167 static void mmu_unmap_l2_pte_error(struct isp_mmu *mmu,
168                                    phys_addr_t l1_pt, unsigned int l1_idx,
169                                    phys_addr_t l2_pt, unsigned int l2_idx,
170                                    unsigned int isp_virt, unsigned int pte)
171 {
172         dev_err(atomisp_dev, "unmap unvalid L2 pte:\n\n"
173                      "\tL1 PT: virt = %p, phys = 0x%llx, "
174                      "idx = %d\n"
175                      "\tL2 PT: virt = %p, phys = 0x%llx, "
176                      "idx = %d\n"
177                      "\tisp_virt = 0x%x, pte(page phys) = 0x%x\n",
178                      isp_pt_phys_to_virt(l1_pt),
179                      (u64)l1_pt, l1_idx,
180                      isp_pt_phys_to_virt(l2_pt),
181                      (u64)l2_pt, l2_idx, isp_virt,
182                      pte);
183 }
184
185 static void mmu_unmap_l1_pte_error(struct isp_mmu *mmu,
186                                    phys_addr_t l1_pt, unsigned int l1_idx,
187                                    unsigned int isp_virt, unsigned int pte)
188 {
189         dev_err(atomisp_dev, "unmap unvalid L1 pte (L2 PT):\n\n"
190                      "\tL1 PT: virt = %p, phys = 0x%llx, "
191                      "idx = %d\n"
192                      "\tisp_virt = 0x%x, l1_pte(L2 PT) = 0x%x\n",
193                      isp_pt_phys_to_virt(l1_pt),
194                      (u64)l1_pt, l1_idx, (unsigned int)isp_virt,
195                      pte);
196 }
197
198 static void mmu_unmap_l1_pt_error(struct isp_mmu *mmu, unsigned int pte)
199 {
200         dev_err(atomisp_dev, "unmap unvalid L1PT:\n\n"
201                      "L1PT = 0x%x\n", (unsigned int)pte);
202 }
203
204 /*
205  * Update L2 page table according to isp virtual address and page physical
206  * address
207  */
208 static int mmu_l2_map(struct isp_mmu *mmu, phys_addr_t l1_pt,
209                       unsigned int l1_idx, phys_addr_t l2_pt,
210                       unsigned int start, unsigned int end, phys_addr_t phys)
211 {
212         unsigned int ptr;
213         unsigned int idx;
214         unsigned int pte;
215
216         l2_pt &= ISP_PAGE_MASK;
217
218         start = start & ISP_PAGE_MASK;
219         end = ISP_PAGE_ALIGN(end);
220         phys &= ISP_PAGE_MASK;
221
222         ptr = start;
223         do {
224                 idx = ISP_PTR_TO_L2_IDX(ptr);
225
226                 pte = atomisp_get_pte(l2_pt, idx);
227
228                 if (ISP_PTE_VALID(mmu, pte)) {
229                         mmu_remap_error(mmu, l1_pt, l1_idx,
230                                           l2_pt, idx, ptr, pte, phys);
231
232                         /* free all mapped pages */
233                         free_mmu_map(mmu, start, ptr);
234
235                         return -EINVAL;
236                 }
237
238                 pte = isp_pgaddr_to_pte_valid(mmu, phys);
239
240                 atomisp_set_pte(l2_pt, idx, pte);
241                 mmu->l2_pgt_refcount[l1_idx]++;
242                 ptr += (1U << ISP_L2PT_OFFSET);
243                 phys += (1U << ISP_L2PT_OFFSET);
244         } while (ptr < end && idx < ISP_L2PT_PTES - 1);
245
246         return 0;
247 }
248
249 /*
250  * Update L1 page table according to isp virtual address and page physical
251  * address
252  */
253 static int mmu_l1_map(struct isp_mmu *mmu, phys_addr_t l1_pt,
254                       unsigned int start, unsigned int end,
255                       phys_addr_t phys)
256 {
257         phys_addr_t l2_pt;
258         unsigned int ptr, l1_aligned;
259         unsigned int idx;
260         unsigned int l2_pte;
261         int ret;
262
263         l1_pt &= ISP_PAGE_MASK;
264
265         start = start & ISP_PAGE_MASK;
266         end = ISP_PAGE_ALIGN(end);
267         phys &= ISP_PAGE_MASK;
268
269         ptr = start;
270         do {
271                 idx = ISP_PTR_TO_L1_IDX(ptr);
272
273                 l2_pte = atomisp_get_pte(l1_pt, idx);
274
275                 if (!ISP_PTE_VALID(mmu, l2_pte)) {
276                         l2_pt = alloc_page_table(mmu);
277                         if (l2_pt == NULL_PAGE) {
278                                 dev_err(atomisp_dev,
279                                              "alloc page table fail.\n");
280
281                                 /* free all mapped pages */
282                                 free_mmu_map(mmu, start, ptr);
283
284                                 return -ENOMEM;
285                         }
286
287                         l2_pte = isp_pgaddr_to_pte_valid(mmu, l2_pt);
288
289                         atomisp_set_pte(l1_pt, idx, l2_pte);
290                         mmu->l2_pgt_refcount[idx] = 0;
291                 }
292
293                 l2_pt = isp_pte_to_pgaddr(mmu, l2_pte);
294
295                 l1_aligned = (ptr & ISP_PAGE_MASK) + (1U << ISP_L1PT_OFFSET);
296
297                 if (l1_aligned < end) {
298                         ret = mmu_l2_map(mmu, l1_pt, idx,
299                                            l2_pt, ptr, l1_aligned, phys);
300                         phys += (l1_aligned - ptr);
301                         ptr = l1_aligned;
302                 } else {
303                         ret = mmu_l2_map(mmu, l1_pt, idx,
304                                            l2_pt, ptr, end, phys);
305                         phys += (end - ptr);
306                         ptr = end;
307                 }
308
309                 if (ret) {
310                         dev_err(atomisp_dev, "setup mapping in L2PT fail.\n");
311
312                         /* free all mapped pages */
313                         free_mmu_map(mmu, start, ptr);
314
315                         return -EINVAL;
316                 }
317         } while (ptr < end && idx < ISP_L1PT_PTES);
318
319         return 0;
320 }
321
322 /*
323  * Update page table according to isp virtual address and page physical
324  * address
325  */
326 static int mmu_map(struct isp_mmu *mmu, unsigned int isp_virt,
327                    phys_addr_t phys, unsigned int pgnr)
328 {
329         unsigned int start, end;
330         phys_addr_t l1_pt;
331         int ret;
332
333         mutex_lock(&mmu->pt_mutex);
334         if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) {
335                 /*
336                  * allocate 1 new page for L1 page table
337                  */
338                 l1_pt = alloc_page_table(mmu);
339                 if (l1_pt == NULL_PAGE) {
340                         dev_err(atomisp_dev, "alloc page table fail.\n");
341                         mutex_unlock(&mmu->pt_mutex);
342                         return -ENOMEM;
343                 }
344
345                 /*
346                  * setup L1 page table physical addr to MMU
347                  */
348                 ret = mmu->driver->set_pd_base(mmu, l1_pt);
349                 if (ret) {
350                         dev_err(atomisp_dev,
351                                  "set page directory base address fail.\n");
352                         mutex_unlock(&mmu->pt_mutex);
353                         return ret;
354                 }
355                 mmu->base_address = l1_pt;
356                 mmu->l1_pte = isp_pgaddr_to_pte_valid(mmu, l1_pt);
357                 memset(mmu->l2_pgt_refcount, 0, sizeof(int) * ISP_L1PT_PTES);
358         }
359
360         l1_pt = isp_pte_to_pgaddr(mmu, mmu->l1_pte);
361
362         start = (isp_virt) & ISP_PAGE_MASK;
363         end = start + (pgnr << ISP_PAGE_OFFSET);
364         phys &= ISP_PAGE_MASK;
365
366         ret = mmu_l1_map(mmu, l1_pt, start, end, phys);
367
368         if (ret)
369                 dev_err(atomisp_dev, "setup mapping in L1PT fail.\n");
370
371         mutex_unlock(&mmu->pt_mutex);
372         return ret;
373 }
374
375 /*
376  * Free L2 page table according to isp virtual address and page physical
377  * address
378  */
379 static void mmu_l2_unmap(struct isp_mmu *mmu, phys_addr_t l1_pt,
380                            unsigned int l1_idx, phys_addr_t l2_pt,
381                            unsigned int start, unsigned int end)
382 {
383
384         unsigned int ptr;
385         unsigned int idx;
386         unsigned int pte;
387
388         l2_pt &= ISP_PAGE_MASK;
389
390         start = start & ISP_PAGE_MASK;
391         end = ISP_PAGE_ALIGN(end);
392
393         ptr = start;
394         do {
395                 idx = ISP_PTR_TO_L2_IDX(ptr);
396
397                 pte = atomisp_get_pte(l2_pt, idx);
398
399                 if (!ISP_PTE_VALID(mmu, pte))
400                         mmu_unmap_l2_pte_error(mmu, l1_pt, l1_idx,
401                                                  l2_pt, idx, ptr, pte);
402
403                 atomisp_set_pte(l2_pt, idx, mmu->driver->null_pte);
404                 mmu->l2_pgt_refcount[l1_idx]--;
405                 ptr += (1U << ISP_L2PT_OFFSET);
406         } while (ptr < end && idx < ISP_L2PT_PTES - 1);
407
408         if (mmu->l2_pgt_refcount[l1_idx] == 0) {
409                 free_page_table(mmu, l2_pt);
410                 atomisp_set_pte(l1_pt, l1_idx, mmu->driver->null_pte);
411         }
412 }
413
414 /*
415  * Free L1 page table according to isp virtual address and page physical
416  * address
417  */
418 static void mmu_l1_unmap(struct isp_mmu *mmu, phys_addr_t l1_pt,
419                            unsigned int start, unsigned int end)
420 {
421         phys_addr_t l2_pt;
422         unsigned int ptr, l1_aligned;
423         unsigned int idx;
424         unsigned int l2_pte;
425
426         l1_pt &= ISP_PAGE_MASK;
427
428         start = start & ISP_PAGE_MASK;
429         end = ISP_PAGE_ALIGN(end);
430
431         ptr = start;
432         do {
433                 idx = ISP_PTR_TO_L1_IDX(ptr);
434
435                 l2_pte = atomisp_get_pte(l1_pt, idx);
436
437                 if (!ISP_PTE_VALID(mmu, l2_pte)) {
438                         mmu_unmap_l1_pte_error(mmu, l1_pt, idx, ptr, l2_pte);
439                         continue;
440                 }
441
442                 l2_pt = isp_pte_to_pgaddr(mmu, l2_pte);
443
444                 l1_aligned = (ptr & ISP_PAGE_MASK) + (1U << ISP_L1PT_OFFSET);
445
446                 if (l1_aligned < end) {
447                         mmu_l2_unmap(mmu, l1_pt, idx, l2_pt, ptr, l1_aligned);
448                         ptr = l1_aligned;
449                 } else {
450                         mmu_l2_unmap(mmu, l1_pt, idx, l2_pt, ptr, end);
451                         ptr = end;
452                 }
453                 /*
454                  * use the same L2 page next time, so we dont
455                  * need to invalidate and free this PT.
456                  */
457                 /*      atomisp_set_pte(l1_pt, idx, NULL_PTE); */
458         } while (ptr < end && idx < ISP_L1PT_PTES);
459 }
460
461 /*
462  * Free page table according to isp virtual address and page physical
463  * address
464  */
465 static void mmu_unmap(struct isp_mmu *mmu, unsigned int isp_virt,
466                         unsigned int pgnr)
467 {
468         unsigned int start, end;
469         phys_addr_t l1_pt;
470
471         mutex_lock(&mmu->pt_mutex);
472         if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) {
473                 mmu_unmap_l1_pt_error(mmu, mmu->l1_pte);
474                 mutex_unlock(&mmu->pt_mutex);
475                 return;
476         }
477
478         l1_pt = isp_pte_to_pgaddr(mmu, mmu->l1_pte);
479
480         start = (isp_virt) & ISP_PAGE_MASK;
481         end = start + (pgnr << ISP_PAGE_OFFSET);
482
483         mmu_l1_unmap(mmu, l1_pt, start, end);
484         mutex_unlock(&mmu->pt_mutex);
485 }
486
487 /*
488  * Free page tables according to isp start virtual address and end virtual
489  * address.
490  */
491 static void free_mmu_map(struct isp_mmu *mmu, unsigned int start_isp_virt,
492                                 unsigned int end_isp_virt)
493 {
494         unsigned int pgnr;
495         unsigned int start, end;
496
497         start = (start_isp_virt) & ISP_PAGE_MASK;
498         end = (end_isp_virt) & ISP_PAGE_MASK;
499         pgnr = (end - start) >> ISP_PAGE_OFFSET;
500         mmu_unmap(mmu, start, pgnr);
501 }
502
503 int isp_mmu_map(struct isp_mmu *mmu, unsigned int isp_virt,
504                 phys_addr_t phys, unsigned int pgnr)
505 {
506         return mmu_map(mmu, isp_virt, phys, pgnr);
507 }
508
509 void isp_mmu_unmap(struct isp_mmu *mmu, unsigned int isp_virt,
510                    unsigned int pgnr)
511 {
512         mmu_unmap(mmu, isp_virt, pgnr);
513 }
514
515 static void isp_mmu_flush_tlb_range_default(struct isp_mmu *mmu,
516                                               unsigned int start,
517                                               unsigned int size)
518 {
519         isp_mmu_flush_tlb(mmu);
520 }
521
522 /*MMU init for internal structure*/
523 int isp_mmu_init(struct isp_mmu *mmu, struct isp_mmu_client *driver)
524 {
525         if (!mmu)               /* error */
526                 return -EINVAL;
527         if (!driver)            /* error */
528                 return -EINVAL;
529
530         if (!driver->name)
531                 dev_warn(atomisp_dev, "NULL name for MMU driver...\n");
532
533         mmu->driver = driver;
534
535         if (!driver->set_pd_base || !driver->tlb_flush_all) {
536                 dev_err(atomisp_dev,
537                             "set_pd_base or tlb_flush_all operation "
538                              "not provided.\n");
539                 return -EINVAL;
540         }
541
542         if (!driver->tlb_flush_range)
543                 driver->tlb_flush_range = isp_mmu_flush_tlb_range_default;
544
545         if (!driver->pte_valid_mask) {
546                 dev_err(atomisp_dev, "PTE_MASK is missing from mmu driver\n");
547                 return -EINVAL;
548         }
549
550         mmu->l1_pte = driver->null_pte;
551
552         mutex_init(&mmu->pt_mutex);
553
554         mmu->tbl_cache = kmem_cache_create("iopte_cache", ISP_PAGE_SIZE,
555                                            ISP_PAGE_SIZE, SLAB_HWCACHE_ALIGN,
556                                            NULL);
557         if (!mmu->tbl_cache)
558                 return -ENOMEM;
559
560         return 0;
561 }
562
563 /*Free L1 and L2 page table*/
564 void isp_mmu_exit(struct isp_mmu *mmu)
565 {
566         unsigned int idx;
567         unsigned int pte;
568         phys_addr_t l1_pt, l2_pt;
569
570         if (!mmu)
571                 return;
572
573         if (!ISP_PTE_VALID(mmu, mmu->l1_pte)) {
574                 dev_warn(atomisp_dev, "invalid L1PT: pte = 0x%x\n",
575                             (unsigned int)mmu->l1_pte);
576                 return;
577         }
578
579         l1_pt = isp_pte_to_pgaddr(mmu, mmu->l1_pte);
580
581         for (idx = 0; idx < ISP_L1PT_PTES; idx++) {
582                 pte = atomisp_get_pte(l1_pt, idx);
583
584                 if (ISP_PTE_VALID(mmu, pte)) {
585                         l2_pt = isp_pte_to_pgaddr(mmu, pte);
586
587                         free_page_table(mmu, l2_pt);
588                 }
589         }
590
591         free_page_table(mmu, l1_pt);
592
593         kmem_cache_destroy(mmu->tbl_cache);
594 }