11bd4fe43Sopenharmony_ci/* 21bd4fe43Sopenharmony_ci * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED. 31bd4fe43Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 41bd4fe43Sopenharmony_ci * you may not use this file except in compliance with the License. 51bd4fe43Sopenharmony_ci * You may obtain a copy of the License at 61bd4fe43Sopenharmony_ci * 71bd4fe43Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 81bd4fe43Sopenharmony_ci * 91bd4fe43Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 101bd4fe43Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 111bd4fe43Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121bd4fe43Sopenharmony_ci * See the License for the specific language governing permissions and 131bd4fe43Sopenharmony_ci * limitations under the License. 141bd4fe43Sopenharmony_ci */ 151bd4fe43Sopenharmony_ci 161bd4fe43Sopenharmony_ci#ifndef _OSAL_MMZ_H 171bd4fe43Sopenharmony_ci#define _OSAL_MMZ_H 181bd4fe43Sopenharmony_ci 191bd4fe43Sopenharmony_ci#include "hi_osal.h" 201bd4fe43Sopenharmony_ci#include "hi_osal_param.h" 211bd4fe43Sopenharmony_ci 221bd4fe43Sopenharmony_ci#define CACHE_LINE_SIZE 0x40 231bd4fe43Sopenharmony_ci#define HIL_MMZ_NAME_LEN 32 241bd4fe43Sopenharmony_ci#define HIL_MMB_NAME_LEN 32 251bd4fe43Sopenharmony_ci 261bd4fe43Sopenharmony_cistruct hil_media_memory_zone { 271bd4fe43Sopenharmony_ci char name[HIL_MMZ_NAME_LEN]; 281bd4fe43Sopenharmony_ci 291bd4fe43Sopenharmony_ci unsigned long gfp; 301bd4fe43Sopenharmony_ci 311bd4fe43Sopenharmony_ci unsigned long phys_start; 321bd4fe43Sopenharmony_ci unsigned long nbytes; 331bd4fe43Sopenharmony_ci 341bd4fe43Sopenharmony_ci struct osal_list_head list; 351bd4fe43Sopenharmony_ci union { 361bd4fe43Sopenharmony_ci struct device *cma_dev; 371bd4fe43Sopenharmony_ci unsigned char *bitmap; 381bd4fe43Sopenharmony_ci }; 391bd4fe43Sopenharmony_ci struct osal_list_head mmb_list; 401bd4fe43Sopenharmony_ci 411bd4fe43Sopenharmony_ci unsigned int alloc_type; 421bd4fe43Sopenharmony_ci unsigned long block_align; 431bd4fe43Sopenharmony_ci 441bd4fe43Sopenharmony_ci void (*destructor)(const void *); 451bd4fe43Sopenharmony_ci}; 461bd4fe43Sopenharmony_citypedef struct hil_media_memory_zone hil_mmz_t; 471bd4fe43Sopenharmony_ci 481bd4fe43Sopenharmony_ci#define HIL_MMZ_FMT_S "PHYS(0x%08lX, 0x%08lX), GFP=%lu, nBYTES=%luKB, NAME=\"%s\"" 491bd4fe43Sopenharmony_ci#define hil_mmz_fmt_arg(p) (p)->phys_start, (p)->phys_start + (p)->nbytes - 1, (p)->gfp, (p)->nbytes / SZ_1K, (p)->name 501bd4fe43Sopenharmony_ci 511bd4fe43Sopenharmony_cistruct hil_media_memory_block { 521bd4fe43Sopenharmony_ci#ifndef MMZ_V2_SUPPORT 531bd4fe43Sopenharmony_ci unsigned int id; 541bd4fe43Sopenharmony_ci#endif 551bd4fe43Sopenharmony_ci char name[HIL_MMB_NAME_LEN]; 561bd4fe43Sopenharmony_ci struct hil_media_memory_zone *zone; 571bd4fe43Sopenharmony_ci struct osal_list_head list; 581bd4fe43Sopenharmony_ci 591bd4fe43Sopenharmony_ci unsigned long phys_addr; 601bd4fe43Sopenharmony_ci void *kvirt; 611bd4fe43Sopenharmony_ci unsigned long length; 621bd4fe43Sopenharmony_ci 631bd4fe43Sopenharmony_ci unsigned long flags; 641bd4fe43Sopenharmony_ci 651bd4fe43Sopenharmony_ci unsigned int order; 661bd4fe43Sopenharmony_ci 671bd4fe43Sopenharmony_ci int phy_ref; 681bd4fe43Sopenharmony_ci int map_ref; 691bd4fe43Sopenharmony_ci}; 701bd4fe43Sopenharmony_citypedef struct hil_media_memory_block hil_mmb_t; 711bd4fe43Sopenharmony_ci 721bd4fe43Sopenharmony_ci#define hil_mmb_kvirt(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->kvirt; }) 731bd4fe43Sopenharmony_ci#define hil_mmb_phys(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->phys_addr; }) 741bd4fe43Sopenharmony_ci#define hil_mmb_length(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->length; }) 751bd4fe43Sopenharmony_ci#define hil_mmb_name(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->name; }) 761bd4fe43Sopenharmony_ci#define hil_mmb_zone(p) ({hil_mmb_t *__mmb=(p); OSAL_BUG_ON(__mmb==NULL); __mmb->zone; }) 771bd4fe43Sopenharmony_ci 781bd4fe43Sopenharmony_ci#define HIL_MMB_MAP2KERN (1 << 0) 791bd4fe43Sopenharmony_ci#define HIL_MMB_MAP2KERN_CACHED (1 << 1) 801bd4fe43Sopenharmony_ci#define HIL_MMB_RELEASED (1 << 2) 811bd4fe43Sopenharmony_ci 821bd4fe43Sopenharmony_ci#define HIL_MMB_FMT_S "phys(0x%08lX, 0x%08lX), kvirt=0x%08lX, flags=0x%08lX, length=%luKB, name=\"%s\"" 831bd4fe43Sopenharmony_ci#define hil_mmb_fmt_arg(p) \ 841bd4fe43Sopenharmony_ci (p)->phys_addr, mmz_grain_align((p)->phys_addr + (p)->length) - 1, \ 851bd4fe43Sopenharmony_ci (unsigned long)(uintptr_t)((p)->kvirt), (p)->flags, (p)->length / SZ_1K, (p)->name 861bd4fe43Sopenharmony_ci 871bd4fe43Sopenharmony_ci#define DEFAULT_ALLOC 0 881bd4fe43Sopenharmony_ci#define SLAB_ALLOC 1 891bd4fe43Sopenharmony_ci#define EQ_BLOCK_ALLOC 2 901bd4fe43Sopenharmony_ci 911bd4fe43Sopenharmony_ci#define LOW_TO_HIGH 0 921bd4fe43Sopenharmony_ci#define HIGH_TO_LOW 1 931bd4fe43Sopenharmony_ci 941bd4fe43Sopenharmony_ci#define MMZ_DBG_LEVEL 0x0 951bd4fe43Sopenharmony_ci#define MMZ_WARN_LEVEL 4 961bd4fe43Sopenharmony_ci#define MMZ_ERR_LEVEL 1 971bd4fe43Sopenharmony_ci 981bd4fe43Sopenharmony_ci#define mmz_trace(level, s, params...) \ 991bd4fe43Sopenharmony_ci do { \ 1001bd4fe43Sopenharmony_ci if (level & MMZ_DBG_LEVEL) \ 1011bd4fe43Sopenharmony_ci printk(KERN_INFO "[%s, %d]: " s "\n", __FUNCTION__, __LINE__, params); \ 1021bd4fe43Sopenharmony_ci } while (0) 1031bd4fe43Sopenharmony_ci 1041bd4fe43Sopenharmony_ci#define mmz_trace_func() mmz_trace(0x02, "%s", __FILE__) 1051bd4fe43Sopenharmony_ci 1061bd4fe43Sopenharmony_ci#define MMZ_GRAIN PAGE_SIZE 1071bd4fe43Sopenharmony_ci#define mmz_bitmap_size(p) (mmz_align2(mmz_length2grain((p)->nbytes), 8) / 8) 1081bd4fe43Sopenharmony_ci 1091bd4fe43Sopenharmony_ci#define mmz_get_bit(p, n) (((p)->bitmap[(n) / 8] >> ((n) & 0x7)) & 0x1) 1101bd4fe43Sopenharmony_ci#define mmz_set_bit(p, n) ((p)->bitmap[(n) / 8] |= 1 << ((n) & 0x7)) 1111bd4fe43Sopenharmony_ci#define mmz_clr_bit(p, n) ((p)->bitmap[(n) / 8] &= ~(1 << ((n) & 0x7))) 1121bd4fe43Sopenharmony_ci 1131bd4fe43Sopenharmony_ci#define mmz_pos2phy_addr(p, n) ((p)->phys_start + (n) * MMZ_GRAIN) 1141bd4fe43Sopenharmony_ci#define mmz_phy_addr2pos(p, a) (((a) - (p)->phys_start) / MMZ_GRAIN) 1151bd4fe43Sopenharmony_ci 1161bd4fe43Sopenharmony_ci#define mmz_align2low(x, g) (((x) / (g)) * (g)) 1171bd4fe43Sopenharmony_ci#define mmz_align2(x, g) ((((x) + (g) - 1) / (g)) * (g)) 1181bd4fe43Sopenharmony_ci#define mmz_grain_align(x) mmz_align2(x, MMZ_GRAIN) 1191bd4fe43Sopenharmony_ci#define mmz_length2grain(len) (mmz_grain_align(len) / MMZ_GRAIN) 1201bd4fe43Sopenharmony_ci 1211bd4fe43Sopenharmony_ci#define begin_list_for_each_mmz(p, gfp, mmz_name) \ 1221bd4fe43Sopenharmony_ci list_for_each_entry(p, &g_mmz_list, list) \ 1231bd4fe43Sopenharmony_ci { \ 1241bd4fe43Sopenharmony_ci if ((gfp) == 0 ? 0 : (p)->gfp != (gfp)) { \ 1251bd4fe43Sopenharmony_ci continue; \ 1261bd4fe43Sopenharmony_ci } \ 1271bd4fe43Sopenharmony_ci if (((mmz_name) == NULL) || (*(mmz_name) == '\0')) { \ 1281bd4fe43Sopenharmony_ci if (anony == 1) { \ 1291bd4fe43Sopenharmony_ci if (strcmp("anonymous", (p)->name)) { \ 1301bd4fe43Sopenharmony_ci continue; \ 1311bd4fe43Sopenharmony_ci } \ 1321bd4fe43Sopenharmony_ci } else { \ 1331bd4fe43Sopenharmony_ci break; \ 1341bd4fe43Sopenharmony_ci } \ 1351bd4fe43Sopenharmony_ci } else { \ 1361bd4fe43Sopenharmony_ci if (strcmp(mmz_name, (p)->name)) { \ 1371bd4fe43Sopenharmony_ci continue; \ 1381bd4fe43Sopenharmony_ci } \ 1391bd4fe43Sopenharmony_ci } \ 1401bd4fe43Sopenharmony_ci mmz_trace(1, HIL_MMZ_FMT_S, hil_mmz_fmt_arg(p)); 1411bd4fe43Sopenharmony_ci#define end_list_for_each_mmz() } 1421bd4fe43Sopenharmony_ci 1431bd4fe43Sopenharmony_ci#if defined(KERNEL_BIT_64) && defined(USER_BIT_32) 1441bd4fe43Sopenharmony_ci#define __phys_addr_type__ unsigned long long 1451bd4fe43Sopenharmony_ci#define __phys_len_type__ unsigned long long 1461bd4fe43Sopenharmony_ci#define __phys_addr_align__ __attribute__((aligned(8))) 1471bd4fe43Sopenharmony_ci#else 1481bd4fe43Sopenharmony_ci#define __phys_addr_type__ unsigned long 1491bd4fe43Sopenharmony_ci#define __phys_len_type__ unsigned long 1501bd4fe43Sopenharmony_ci#define __phys_addr_align__ __attribute__((aligned(sizeof(long)))) 1511bd4fe43Sopenharmony_ci#endif 1521bd4fe43Sopenharmony_ci 1531bd4fe43Sopenharmony_cistruct mmb_info { 1541bd4fe43Sopenharmony_ci __phys_addr_type__ phys_addr; /* phys-memory address */ 1551bd4fe43Sopenharmony_ci __phys_addr_type__ __phys_addr_align__ align; /* if you need your phys-memory have special align size */ 1561bd4fe43Sopenharmony_ci __phys_len_type__ __phys_addr_align__ size; /* length of memory you need, in bytes */ 1571bd4fe43Sopenharmony_ci unsigned int __phys_addr_align__ order; 1581bd4fe43Sopenharmony_ci 1591bd4fe43Sopenharmony_ci void *__phys_addr_align__ mapped; /* userspace mapped ptr */ 1601bd4fe43Sopenharmony_ci 1611bd4fe43Sopenharmony_ci union { 1621bd4fe43Sopenharmony_ci struct { 1631bd4fe43Sopenharmony_ci unsigned long prot : 8; /* PROT_READ or PROT_WRITE */ 1641bd4fe43Sopenharmony_ci unsigned long flags : 12; /* MAP_SHARED or MAP_PRIVATE */ 1651bd4fe43Sopenharmony_ci 1661bd4fe43Sopenharmony_ci#ifdef __KERNEL__ 1671bd4fe43Sopenharmony_ci unsigned long reserved : 8; /* reserved, do not use */ 1681bd4fe43Sopenharmony_ci unsigned long delayed_free : 1; 1691bd4fe43Sopenharmony_ci unsigned long map_cached : 1; 1701bd4fe43Sopenharmony_ci#endif 1711bd4fe43Sopenharmony_ci }; 1721bd4fe43Sopenharmony_ci unsigned long w32_stuf; 1731bd4fe43Sopenharmony_ci } __phys_addr_align__; 1741bd4fe43Sopenharmony_ci 1751bd4fe43Sopenharmony_ci char mmb_name[HIL_MMB_NAME_LEN]; 1761bd4fe43Sopenharmony_ci char mmz_name[HIL_MMZ_NAME_LEN]; 1771bd4fe43Sopenharmony_ci unsigned long __phys_addr_align__ gfp; /* reserved, do set to 0 */ 1781bd4fe43Sopenharmony_ci 1791bd4fe43Sopenharmony_ci#ifdef __KERNEL__ 1801bd4fe43Sopenharmony_ci int map_ref; 1811bd4fe43Sopenharmony_ci int mmb_ref; 1821bd4fe43Sopenharmony_ci 1831bd4fe43Sopenharmony_ci struct osal_list_head list; 1841bd4fe43Sopenharmony_ci hil_mmb_t *mmb; 1851bd4fe43Sopenharmony_ci#endif 1861bd4fe43Sopenharmony_ci} __attribute__((aligned(8))); 1871bd4fe43Sopenharmony_ci 1881bd4fe43Sopenharmony_cistruct dirty_area { 1891bd4fe43Sopenharmony_ci __phys_addr_type__ dirty_phys_start; /* dirty physical address */ 1901bd4fe43Sopenharmony_ci void *__phys_addr_align__ dirty_virt_start; /* dirty virtual address, 1911bd4fe43Sopenharmony_ci must be coherent with dirty_phys_addr */ 1921bd4fe43Sopenharmony_ci __phys_len_type__ __phys_addr_align__ dirty_size; 1931bd4fe43Sopenharmony_ci} __phys_addr_align__; 1941bd4fe43Sopenharmony_ci 1951bd4fe43Sopenharmony_ci#define IOC_MMB_ALLOC _IOWR('m', 10, struct mmb_info) 1961bd4fe43Sopenharmony_ci#define IOC_MMB_ATTR _IOR('m', 11, struct mmb_info) 1971bd4fe43Sopenharmony_ci#define IOC_MMB_FREE _IOW('m', 12, struct mmb_info) 1981bd4fe43Sopenharmony_ci#define IOC_MMB_ALLOC_V2 _IOWR('m', 13, struct mmb_info) 1991bd4fe43Sopenharmony_ci 2001bd4fe43Sopenharmony_ci#define IOC_MMB_USER_REMAP _IOWR('m', 20, struct mmb_info) 2011bd4fe43Sopenharmony_ci#define IOC_MMB_USER_REMAP_CACHED _IOWR('m', 21, struct mmb_info) 2021bd4fe43Sopenharmony_ci#define IOC_MMB_USER_UNMAP _IOWR('m', 22, struct mmb_info) 2031bd4fe43Sopenharmony_ci 2041bd4fe43Sopenharmony_ci#define IOC_MMB_VIRT_GET_PHYS _IOWR('m', 23, struct mmb_info) 2051bd4fe43Sopenharmony_ci 2061bd4fe43Sopenharmony_ci#define IOC_MMB_ADD_REF _IO('r', 30) /* ioctl(file, cmd, arg), arg is mmb_addr */ 2071bd4fe43Sopenharmony_ci#define IOC_MMB_DEC_REF _IO('r', 31) /* ioctl(file, cmd, arg), arg is mmb_addr */ 2081bd4fe43Sopenharmony_ci 2091bd4fe43Sopenharmony_ci#define IOC_MMB_FLUSH_DCACHE _IO('c', 40) 2101bd4fe43Sopenharmony_ci 2111bd4fe43Sopenharmony_ci#define IOC_MMB_FLUSH_DCACHE_DIRTY _IOW('d', 50, struct dirty_area) 2121bd4fe43Sopenharmony_ci#define IOC_MMB_TEST_CACHE _IOW('t', 11, struct mmb_info) 2131bd4fe43Sopenharmony_ci 2141bd4fe43Sopenharmony_ci/* 2151bd4fe43Sopenharmony_ci * APIs 2161bd4fe43Sopenharmony_ci */ 2171bd4fe43Sopenharmony_ciextern hil_mmz_t *hil_mmz_create(const char *name, unsigned long gfp, unsigned long phys_start, 2181bd4fe43Sopenharmony_ci unsigned long nbytes); 2191bd4fe43Sopenharmony_ciextern hil_mmz_t *hil_mmz_create_v2(const char *name, unsigned long gfp, unsigned long phys_start, 2201bd4fe43Sopenharmony_ci unsigned long nbytes, unsigned int alloc_type, unsigned long block_align); 2211bd4fe43Sopenharmony_ci 2221bd4fe43Sopenharmony_ciextern int hil_mmz_destroy(hil_mmz_t *zone); 2231bd4fe43Sopenharmony_ci 2241bd4fe43Sopenharmony_ciextern int hil_mmz_register(hil_mmz_t *zone); 2251bd4fe43Sopenharmony_ciextern int hil_mmz_unregister(hil_mmz_t *zone); 2261bd4fe43Sopenharmony_ciextern hil_mmz_t *hil_mmz_find(unsigned long gfp, const char *mmz_name); 2271bd4fe43Sopenharmony_ci 2281bd4fe43Sopenharmony_ciextern hil_mmb_t *hil_mmb_alloc(const char *name, unsigned long size, unsigned long align, 2291bd4fe43Sopenharmony_ci unsigned long gfp, const char *mmz_name); 2301bd4fe43Sopenharmony_ciextern hil_mmb_t *hil_mmb_alloc_v2(const char *name, unsigned long size, unsigned long align, 2311bd4fe43Sopenharmony_ci unsigned long gfp, const char *mmz_name, unsigned int order); 2321bd4fe43Sopenharmony_ciextern int hil_mmb_free(hil_mmb_t *mmb); 2331bd4fe43Sopenharmony_ciextern hil_mmb_t *hil_mmb_getby_phys(unsigned long addr); 2341bd4fe43Sopenharmony_ciextern hil_mmb_t *hil_mmb_getby_phys_2(unsigned long addr, unsigned long *out_offset); 2351bd4fe43Sopenharmony_ciextern hil_mmb_t *hil_mmb_getby_kvirt(void *virt); 2361bd4fe43Sopenharmony_ciextern unsigned long usr_virt_to_phys(unsigned long virt); 2371bd4fe43Sopenharmony_ci 2381bd4fe43Sopenharmony_ciextern int hil_map_mmz_check_phys(unsigned long addr_start, unsigned long addr_len); 2391bd4fe43Sopenharmony_ciextern int hil_is_phys_in_mmz(unsigned long addr_start, unsigned long addr_len); 2401bd4fe43Sopenharmony_ci 2411bd4fe43Sopenharmony_ciextern int hil_vma_check(unsigned long vm_start, unsigned long vm_end); 2421bd4fe43Sopenharmony_ciextern int hil_mmb_flush_dcache_byaddr_safe(void *kvirt, unsigned long phys_addr, unsigned long length); 2431bd4fe43Sopenharmony_ci 2441bd4fe43Sopenharmony_ciextern unsigned long hil_mmz_get_phys(const char *zone_name); 2451bd4fe43Sopenharmony_ci 2461bd4fe43Sopenharmony_ciextern hil_mmb_t *hil_mmb_alloc_in(const char *name, unsigned long size, unsigned long align, 2471bd4fe43Sopenharmony_ci hil_mmz_t *_user_mmz); 2481bd4fe43Sopenharmony_ciextern hil_mmb_t *hil_mmb_alloc_in_v2(const char *name, unsigned long size, unsigned long align, 2491bd4fe43Sopenharmony_ci hil_mmz_t *_user_mmz, unsigned int order); 2501bd4fe43Sopenharmony_ci 2511bd4fe43Sopenharmony_ci#define hil_mmb_freeby_phys(phys_addr) hil_mmb_free(hil_mmb_getby_phys(phys_addr)) 2521bd4fe43Sopenharmony_ci#define hil_mmb_freeby_kvirt(kvirt) hil_mmb_free(hil_mmb_getby_kvirt(kvirt)) 2531bd4fe43Sopenharmony_ci 2541bd4fe43Sopenharmony_ciextern void *hil_mmb_map2kern(hil_mmb_t *mmb); 2551bd4fe43Sopenharmony_ciextern void *hil_mmb_map2kern_cached(hil_mmb_t *mmb); 2561bd4fe43Sopenharmony_ci 2571bd4fe43Sopenharmony_ciextern int hil_mmb_flush_dcache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length); 2581bd4fe43Sopenharmony_ciextern int hil_mmb_invalid_cache_byaddr(void *kvirt, unsigned long phys_addr, unsigned long length); 2591bd4fe43Sopenharmony_ci 2601bd4fe43Sopenharmony_ciextern int hil_mmb_unmap(hil_mmb_t *mmb); 2611bd4fe43Sopenharmony_ciextern int hil_mmb_get(hil_mmb_t *mmb); 2621bd4fe43Sopenharmony_ciextern int hil_mmb_put(hil_mmb_t *mmb); 2631bd4fe43Sopenharmony_ci 2641bd4fe43Sopenharmony_ciextern void *hil_mmf_map2kern_nocache(unsigned long phys, int len); 2651bd4fe43Sopenharmony_ciextern void *hil_mmf_map2kern_cache(unsigned long phys, int len); 2661bd4fe43Sopenharmony_ciextern void hil_mmf_unmap(void *virt); 2671bd4fe43Sopenharmony_ci 2681bd4fe43Sopenharmony_ci/* for mmz userdev */ 2691bd4fe43Sopenharmony_ciint mmz_userdev_init(void); 2701bd4fe43Sopenharmony_civoid mmz_userdev_exit(void); 2711bd4fe43Sopenharmony_ciint mmz_flush_dcache_all(void); 2721bd4fe43Sopenharmony_ci 2731bd4fe43Sopenharmony_ci#endif 274