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