1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 #include <linux/module.h>
19
20 #include "hi_osal.h"
21 #include "osal_mmz.h"
22
23 #include "hi_debug.h"
24 #include "hi_common.h"
25
26 #ifdef __cplusplus
27 #if __cplusplus
28 extern "C" {
29 #endif
30 #endif /* __cplusplus */
31
cmpi_mmz_malloc(const hi_char * mmz_name,const hi_char * buf_name,hi_ulong size)32 hi_u64 cmpi_mmz_malloc(const hi_char *mmz_name, const hi_char *buf_name, hi_ulong size)
33 {
34 hil_mmb_t *pmmb = NULL;
35
36 pmmb = hil_mmb_alloc(buf_name, size, 0, 0, mmz_name);
37 if (pmmb == NULL) {
38 osal_printk("mmz malloc failed!\n");
39 return HI_NULL;
40 }
41
42 return hil_mmb_phys(pmmb);
43 }
44 EXPORT_SYMBOL(cmpi_mmz_malloc);
45
cmpi_mmz_free(hi_u64 phy_addr,hi_void * vir_addr)46 hi_void cmpi_mmz_free(hi_u64 phy_addr, hi_void *vir_addr)
47 {
48 if (vir_addr != NULL) {
49 hil_mmb_t *pmmb = hil_mmb_getby_kvirt(vir_addr);
50
51 if (pmmb != NULL) {
52 hil_mmb_unmap(pmmb);
53 }
54 }
55
56 if (phy_addr != 0) {
57 hil_mmb_freeby_phys(phy_addr);
58 }
59 }
60 EXPORT_SYMBOL(cmpi_mmz_free);
61
cmpi_remap_cached(hi_u64 phy_addr,hi_ulong size)62 hi_void *cmpi_remap_cached(hi_u64 phy_addr, hi_ulong size)
63 {
64 hi_u32 diff;
65 hi_u64 page_phy;
66 hi_u8 *page_addr;
67 hi_ulong page_size;
68
69 /* the mmap address should align with page */
70 page_phy = phy_addr & 0xfffffffffffff000ULL;
71 diff = phy_addr - page_phy;
72
73 /* the mmap size should be multiples of 1024 */
74 page_size = ((size + diff - 1) & 0xfffff000UL) + 0x1000;
75
76 page_addr = hil_mmf_map2kern_cache(page_phy, page_size);
77 if (page_addr == NULL) {
78 osal_printk("phy(0x%llx) size(0x%lx) map cache err!\n", page_phy, page_size);
79 return NULL;
80 }
81
82 return (page_addr + diff);
83 }
84 EXPORT_SYMBOL(cmpi_remap_cached);
85
cmpi_remap_nocache(hi_u64 phy_addr,hi_ulong size)86 hi_void *cmpi_remap_nocache(hi_u64 phy_addr, hi_ulong size)
87 {
88 hi_u32 diff;
89 hi_u64 page_phy;
90 hi_u8 *page_addr;
91 hi_ulong page_size;
92
93 /* the mmap address should align with page */
94 page_phy = phy_addr & 0xfffffffffffff000ULL;
95 diff = phy_addr - page_phy;
96
97 /* the mmap size should be multiples of 1024 */
98 page_size = ((size + diff - 1) & 0xfffff000UL) + 0x1000;
99
100 page_addr = hil_mmf_map2kern_nocache(page_phy, page_size);
101 if (page_addr == NULL) {
102 osal_printk("phy(0x%llx) size(0x%lx) map nocache err!\n", page_phy, page_size);
103 return NULL;
104 }
105
106 return (page_addr + diff);
107 }
108 EXPORT_SYMBOL(cmpi_remap_nocache);
109
cmpi_unmap(hi_void * virt_addr)110 hi_void cmpi_unmap(hi_void *virt_addr)
111 {
112 hil_mmf_unmap(virt_addr);
113 }
114 EXPORT_SYMBOL(cmpi_unmap);
115
cmpi_mmz_malloc_nocache(const hi_char * cp_mmz_name,const hi_char * buf_name,hi_u64 * phy_addr,hi_void ** pp_vir_addr,hi_ulong len)116 hi_s32 cmpi_mmz_malloc_nocache(const hi_char *cp_mmz_name, const hi_char *buf_name,
117 hi_u64 *phy_addr, hi_void **pp_vir_addr, hi_ulong len)
118 {
119 hil_mmb_t *pmmb = NULL;
120
121 pmmb = hil_mmb_alloc(buf_name, len, 0, 0, cp_mmz_name);
122 if (pmmb == NULL) {
123 osal_printk("mmz malloc failed!\n");
124 return HI_FAILURE;
125 }
126
127 // the buffer allocated by mmz is 4k align
128 *pp_vir_addr = hil_mmb_map2kern(pmmb);
129 if (*pp_vir_addr == NULL) {
130 hil_mmb_free(pmmb);
131 osal_printk("mmz remap no cache failed!\n");
132 return HI_FAILURE;
133 }
134 *phy_addr = hil_mmb_phys(pmmb);
135
136 return HI_SUCCESS;
137 }
138 EXPORT_SYMBOL(cmpi_mmz_malloc_nocache);
139
140
cmpi_mmz_malloc_cached(const hi_char * cp_mmz_name,const hi_char * buf_name,hi_u64 * phy_addr,hi_void ** pp_vir_addr,hi_ulong len)141 hi_s32 cmpi_mmz_malloc_cached(const hi_char *cp_mmz_name, const hi_char *buf_name,
142 hi_u64 *phy_addr, hi_void **pp_vir_addr, hi_ulong len)
143 {
144 hil_mmb_t *pmmb = NULL;
145
146 pmmb = hil_mmb_alloc(buf_name, len, 0, 0, cp_mmz_name);
147 if (pmmb == NULL) {
148 osal_printk("mmz malloc failed!\n");
149 return HI_FAILURE;
150 }
151
152 // the buffer allocated by mmz is 4k align
153 *pp_vir_addr = hil_mmb_map2kern_cached(pmmb);
154 if (*pp_vir_addr == NULL) {
155 hil_mmb_free(pmmb);
156 osal_printk("mmz remap cache failed!\n");
157 return HI_FAILURE;
158 }
159 *phy_addr = hil_mmb_phys(pmmb);
160
161 return HI_SUCCESS;
162 }
163 EXPORT_SYMBOL(cmpi_mmz_malloc_cached);
164
cmpi_check_mmz_phy_addr(unsigned long long phy_addr,unsigned int len)165 int cmpi_check_mmz_phy_addr(unsigned long long phy_addr, unsigned int len)
166 {
167 /* if address in mmz of current system */
168 if (hil_is_phys_in_mmz(phy_addr, len)) {
169 /* if in other system */
170 if (hil_map_mmz_check_phys(phy_addr, len)) {
171 return -1;
172 }
173 }
174
175 return 0;
176 }
177 EXPORT_SYMBOL(cmpi_check_mmz_phy_addr);
178
179 #ifdef __cplusplus
180 #if __cplusplus
181 }
182 #endif
183 #endif /* __cplusplus */
184
185