1*d81734caSHemant Agrawal /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 223df3960SShreyansh Jain * 323df3960SShreyansh Jain * Copyright 2011-2016 Freescale Semiconductor Inc. 4*d81734caSHemant Agrawal * Copyright 2017 NXP 523df3960SShreyansh Jain * 623df3960SShreyansh Jain */ 723df3960SShreyansh Jain #include <assert.h> 823df3960SShreyansh Jain #include <fcntl.h> 923df3960SShreyansh Jain #include <unistd.h> 1023df3960SShreyansh Jain #include <sys/ioctl.h> 1123df3960SShreyansh Jain 1223df3960SShreyansh Jain #include "process.h" 1323df3960SShreyansh Jain 1423df3960SShreyansh Jain #include <fsl_usd.h> 1523df3960SShreyansh Jain 1623df3960SShreyansh Jain /* As higher-level drivers will be built on top of this (dma_mem, qbman, ...), 1723df3960SShreyansh Jain * it's preferable that the process driver itself not provide any exported API. 1823df3960SShreyansh Jain * As such, combined with the fact that none of these operations are 1923df3960SShreyansh Jain * performance critical, it is justified to use lazy initialisation, so that's 2023df3960SShreyansh Jain * what the lock is for. 2123df3960SShreyansh Jain */ 2223df3960SShreyansh Jain static int fd = -1; 2323df3960SShreyansh Jain static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER; 2423df3960SShreyansh Jain 2523df3960SShreyansh Jain static int check_fd(void) 2623df3960SShreyansh Jain { 2723df3960SShreyansh Jain int ret; 2823df3960SShreyansh Jain 2923df3960SShreyansh Jain if (fd >= 0) 3023df3960SShreyansh Jain return 0; 3123df3960SShreyansh Jain ret = pthread_mutex_lock(&fd_init_lock); 3223df3960SShreyansh Jain assert(!ret); 3323df3960SShreyansh Jain /* check again with the lock held */ 3423df3960SShreyansh Jain if (fd < 0) 3523df3960SShreyansh Jain fd = open(PROCESS_PATH, O_RDWR); 3623df3960SShreyansh Jain ret = pthread_mutex_unlock(&fd_init_lock); 3723df3960SShreyansh Jain assert(!ret); 3823df3960SShreyansh Jain return (fd >= 0) ? 0 : -ENODEV; 3923df3960SShreyansh Jain } 4023df3960SShreyansh Jain 4123df3960SShreyansh Jain #define DPAA_IOCTL_MAGIC 'u' 4223df3960SShreyansh Jain struct dpaa_ioctl_id_alloc { 4323df3960SShreyansh Jain uint32_t base; /* Return value, the start of the allocated range */ 4423df3960SShreyansh Jain enum dpaa_id_type id_type; /* what kind of resource(s) to allocate */ 4523df3960SShreyansh Jain uint32_t num; /* how many IDs to allocate (and return value) */ 4623df3960SShreyansh Jain uint32_t align; /* must be a power of 2, 0 is treated like 1 */ 4723df3960SShreyansh Jain int partial; /* whether to allow less than 'num' */ 4823df3960SShreyansh Jain }; 4923df3960SShreyansh Jain 5023df3960SShreyansh Jain struct dpaa_ioctl_id_release { 5123df3960SShreyansh Jain /* Input; */ 5223df3960SShreyansh Jain enum dpaa_id_type id_type; 5323df3960SShreyansh Jain uint32_t base; 5423df3960SShreyansh Jain uint32_t num; 5523df3960SShreyansh Jain }; 5623df3960SShreyansh Jain 5723df3960SShreyansh Jain struct dpaa_ioctl_id_reserve { 5823df3960SShreyansh Jain enum dpaa_id_type id_type; 5923df3960SShreyansh Jain uint32_t base; 6023df3960SShreyansh Jain uint32_t num; 6123df3960SShreyansh Jain }; 6223df3960SShreyansh Jain 6323df3960SShreyansh Jain #define DPAA_IOCTL_ID_ALLOC \ 6423df3960SShreyansh Jain _IOWR(DPAA_IOCTL_MAGIC, 0x01, struct dpaa_ioctl_id_alloc) 6523df3960SShreyansh Jain #define DPAA_IOCTL_ID_RELEASE \ 6623df3960SShreyansh Jain _IOW(DPAA_IOCTL_MAGIC, 0x02, struct dpaa_ioctl_id_release) 6723df3960SShreyansh Jain #define DPAA_IOCTL_ID_RESERVE \ 6823df3960SShreyansh Jain _IOW(DPAA_IOCTL_MAGIC, 0x0A, struct dpaa_ioctl_id_reserve) 6923df3960SShreyansh Jain 7023df3960SShreyansh Jain int process_alloc(enum dpaa_id_type id_type, uint32_t *base, uint32_t num, 7123df3960SShreyansh Jain uint32_t align, int partial) 7223df3960SShreyansh Jain { 7323df3960SShreyansh Jain struct dpaa_ioctl_id_alloc id = { 7423df3960SShreyansh Jain .id_type = id_type, 7523df3960SShreyansh Jain .num = num, 7623df3960SShreyansh Jain .align = align, 7723df3960SShreyansh Jain .partial = partial 7823df3960SShreyansh Jain }; 7923df3960SShreyansh Jain int ret = check_fd(); 8023df3960SShreyansh Jain 8123df3960SShreyansh Jain if (ret) 8223df3960SShreyansh Jain return ret; 8323df3960SShreyansh Jain ret = ioctl(fd, DPAA_IOCTL_ID_ALLOC, &id); 8423df3960SShreyansh Jain if (ret) 8523df3960SShreyansh Jain return ret; 8623df3960SShreyansh Jain for (ret = 0; ret < (int)id.num; ret++) 8723df3960SShreyansh Jain base[ret] = id.base + ret; 8823df3960SShreyansh Jain return id.num; 8923df3960SShreyansh Jain } 9023df3960SShreyansh Jain 9123df3960SShreyansh Jain void process_release(enum dpaa_id_type id_type, uint32_t base, uint32_t num) 9223df3960SShreyansh Jain { 9323df3960SShreyansh Jain struct dpaa_ioctl_id_release id = { 9423df3960SShreyansh Jain .id_type = id_type, 9523df3960SShreyansh Jain .base = base, 9623df3960SShreyansh Jain .num = num 9723df3960SShreyansh Jain }; 9823df3960SShreyansh Jain int ret = check_fd(); 9923df3960SShreyansh Jain 10023df3960SShreyansh Jain if (ret) { 10123df3960SShreyansh Jain fprintf(stderr, "Process FD failure\n"); 10223df3960SShreyansh Jain return; 10323df3960SShreyansh Jain } 10423df3960SShreyansh Jain ret = ioctl(fd, DPAA_IOCTL_ID_RELEASE, &id); 10523df3960SShreyansh Jain if (ret) 10623df3960SShreyansh Jain fprintf(stderr, "Process FD ioctl failure type %d base 0x%x num %d\n", 10723df3960SShreyansh Jain id_type, base, num); 10823df3960SShreyansh Jain } 10923df3960SShreyansh Jain 11023df3960SShreyansh Jain int process_reserve(enum dpaa_id_type id_type, uint32_t base, uint32_t num) 11123df3960SShreyansh Jain { 11223df3960SShreyansh Jain struct dpaa_ioctl_id_reserve id = { 11323df3960SShreyansh Jain .id_type = id_type, 11423df3960SShreyansh Jain .base = base, 11523df3960SShreyansh Jain .num = num 11623df3960SShreyansh Jain }; 11723df3960SShreyansh Jain int ret = check_fd(); 11823df3960SShreyansh Jain 11923df3960SShreyansh Jain if (ret) 12023df3960SShreyansh Jain return ret; 12123df3960SShreyansh Jain return ioctl(fd, DPAA_IOCTL_ID_RESERVE, &id); 12223df3960SShreyansh Jain } 12323df3960SShreyansh Jain 12423df3960SShreyansh Jain /***************************************/ 12523df3960SShreyansh Jain /* Mapping and using QMan/BMan portals */ 12623df3960SShreyansh Jain /***************************************/ 12723df3960SShreyansh Jain 12823df3960SShreyansh Jain #define DPAA_IOCTL_PORTAL_MAP \ 12923df3960SShreyansh Jain _IOWR(DPAA_IOCTL_MAGIC, 0x07, struct dpaa_ioctl_portal_map) 13023df3960SShreyansh Jain #define DPAA_IOCTL_PORTAL_UNMAP \ 13123df3960SShreyansh Jain _IOW(DPAA_IOCTL_MAGIC, 0x08, struct dpaa_portal_map) 13223df3960SShreyansh Jain 13323df3960SShreyansh Jain int process_portal_map(struct dpaa_ioctl_portal_map *params) 13423df3960SShreyansh Jain { 13523df3960SShreyansh Jain int ret = check_fd(); 13623df3960SShreyansh Jain 13723df3960SShreyansh Jain if (ret) 13823df3960SShreyansh Jain return ret; 13923df3960SShreyansh Jain 14023df3960SShreyansh Jain ret = ioctl(fd, DPAA_IOCTL_PORTAL_MAP, params); 14123df3960SShreyansh Jain if (ret) { 14223df3960SShreyansh Jain perror("ioctl(DPAA_IOCTL_PORTAL_MAP)"); 14323df3960SShreyansh Jain return ret; 14423df3960SShreyansh Jain } 14523df3960SShreyansh Jain return 0; 14623df3960SShreyansh Jain } 14723df3960SShreyansh Jain 14823df3960SShreyansh Jain int process_portal_unmap(struct dpaa_portal_map *map) 14923df3960SShreyansh Jain { 15023df3960SShreyansh Jain int ret = check_fd(); 15123df3960SShreyansh Jain 15223df3960SShreyansh Jain if (ret) 15323df3960SShreyansh Jain return ret; 15423df3960SShreyansh Jain 15523df3960SShreyansh Jain ret = ioctl(fd, DPAA_IOCTL_PORTAL_UNMAP, map); 15623df3960SShreyansh Jain if (ret) { 15723df3960SShreyansh Jain perror("ioctl(DPAA_IOCTL_PORTAL_UNMAP)"); 15823df3960SShreyansh Jain return ret; 15923df3960SShreyansh Jain } 16023df3960SShreyansh Jain return 0; 16123df3960SShreyansh Jain } 16223df3960SShreyansh Jain 16323df3960SShreyansh Jain #define DPAA_IOCTL_PORTAL_IRQ_MAP \ 16423df3960SShreyansh Jain _IOW(DPAA_IOCTL_MAGIC, 0x09, struct dpaa_ioctl_irq_map) 16523df3960SShreyansh Jain 16623df3960SShreyansh Jain int process_portal_irq_map(int ifd, struct dpaa_ioctl_irq_map *map) 16723df3960SShreyansh Jain { 16823df3960SShreyansh Jain map->fd = fd; 16923df3960SShreyansh Jain return ioctl(ifd, DPAA_IOCTL_PORTAL_IRQ_MAP, map); 17023df3960SShreyansh Jain } 17123df3960SShreyansh Jain 17223df3960SShreyansh Jain int process_portal_irq_unmap(int ifd) 17323df3960SShreyansh Jain { 17423df3960SShreyansh Jain return close(ifd); 17523df3960SShreyansh Jain } 17623df3960SShreyansh Jain 17723df3960SShreyansh Jain struct dpaa_ioctl_raw_portal { 17823df3960SShreyansh Jain /* inputs */ 17923df3960SShreyansh Jain enum dpaa_portal_type type; /* Type of portal to allocate */ 18023df3960SShreyansh Jain 18123df3960SShreyansh Jain uint8_t enable_stash; /* set to non zero to turn on stashing */ 18223df3960SShreyansh Jain /* Stashing attributes for the portal */ 18323df3960SShreyansh Jain uint32_t cpu; 18423df3960SShreyansh Jain uint32_t cache; 18523df3960SShreyansh Jain uint32_t window; 18623df3960SShreyansh Jain /* Specifies the stash request queue this portal should use */ 18723df3960SShreyansh Jain uint8_t sdest; 18823df3960SShreyansh Jain 18923df3960SShreyansh Jain /* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX 19023df3960SShreyansh Jain * for don't care. The portal index will be populated by the 19123df3960SShreyansh Jain * driver when the ioctl() successfully completes. 19223df3960SShreyansh Jain */ 19323df3960SShreyansh Jain uint32_t index; 19423df3960SShreyansh Jain 19523df3960SShreyansh Jain /* outputs */ 19623df3960SShreyansh Jain uint64_t cinh; 19723df3960SShreyansh Jain uint64_t cena; 19823df3960SShreyansh Jain }; 19923df3960SShreyansh Jain 20023df3960SShreyansh Jain #define DPAA_IOCTL_ALLOC_RAW_PORTAL \ 20123df3960SShreyansh Jain _IOWR(DPAA_IOCTL_MAGIC, 0x0C, struct dpaa_ioctl_raw_portal) 20223df3960SShreyansh Jain 20323df3960SShreyansh Jain #define DPAA_IOCTL_FREE_RAW_PORTAL \ 20423df3960SShreyansh Jain _IOR(DPAA_IOCTL_MAGIC, 0x0D, struct dpaa_ioctl_raw_portal) 20523df3960SShreyansh Jain 20623df3960SShreyansh Jain static int process_portal_allocate(struct dpaa_ioctl_raw_portal *portal) 20723df3960SShreyansh Jain { 20823df3960SShreyansh Jain int ret = check_fd(); 20923df3960SShreyansh Jain 21023df3960SShreyansh Jain if (ret) 21123df3960SShreyansh Jain return ret; 21223df3960SShreyansh Jain 21323df3960SShreyansh Jain ret = ioctl(fd, DPAA_IOCTL_ALLOC_RAW_PORTAL, portal); 21423df3960SShreyansh Jain if (ret) { 21523df3960SShreyansh Jain perror("ioctl(DPAA_IOCTL_ALLOC_RAW_PORTAL)"); 21623df3960SShreyansh Jain return ret; 21723df3960SShreyansh Jain } 21823df3960SShreyansh Jain return 0; 21923df3960SShreyansh Jain } 22023df3960SShreyansh Jain 22123df3960SShreyansh Jain static int process_portal_free(struct dpaa_ioctl_raw_portal *portal) 22223df3960SShreyansh Jain { 22323df3960SShreyansh Jain int ret = check_fd(); 22423df3960SShreyansh Jain 22523df3960SShreyansh Jain if (ret) 22623df3960SShreyansh Jain return ret; 22723df3960SShreyansh Jain 22823df3960SShreyansh Jain ret = ioctl(fd, DPAA_IOCTL_FREE_RAW_PORTAL, portal); 22923df3960SShreyansh Jain if (ret) { 23023df3960SShreyansh Jain perror("ioctl(DPAA_IOCTL_FREE_RAW_PORTAL)"); 23123df3960SShreyansh Jain return ret; 23223df3960SShreyansh Jain } 23323df3960SShreyansh Jain return 0; 23423df3960SShreyansh Jain } 23523df3960SShreyansh Jain 23623df3960SShreyansh Jain int qman_allocate_raw_portal(struct dpaa_raw_portal *portal) 23723df3960SShreyansh Jain { 23823df3960SShreyansh Jain struct dpaa_ioctl_raw_portal input; 23923df3960SShreyansh Jain int ret; 24023df3960SShreyansh Jain 24123df3960SShreyansh Jain input.type = dpaa_portal_qman; 24223df3960SShreyansh Jain input.index = portal->index; 24323df3960SShreyansh Jain input.enable_stash = portal->enable_stash; 24423df3960SShreyansh Jain input.cpu = portal->cpu; 24523df3960SShreyansh Jain input.cache = portal->cache; 24623df3960SShreyansh Jain input.window = portal->window; 24723df3960SShreyansh Jain input.sdest = portal->sdest; 24823df3960SShreyansh Jain 24923df3960SShreyansh Jain ret = process_portal_allocate(&input); 25023df3960SShreyansh Jain if (ret) 25123df3960SShreyansh Jain return ret; 25223df3960SShreyansh Jain portal->index = input.index; 25323df3960SShreyansh Jain portal->cinh = input.cinh; 25423df3960SShreyansh Jain portal->cena = input.cena; 25523df3960SShreyansh Jain return 0; 25623df3960SShreyansh Jain } 25723df3960SShreyansh Jain 25823df3960SShreyansh Jain int qman_free_raw_portal(struct dpaa_raw_portal *portal) 25923df3960SShreyansh Jain { 26023df3960SShreyansh Jain struct dpaa_ioctl_raw_portal input; 26123df3960SShreyansh Jain 26223df3960SShreyansh Jain input.type = dpaa_portal_qman; 26323df3960SShreyansh Jain input.index = portal->index; 26423df3960SShreyansh Jain input.cinh = portal->cinh; 26523df3960SShreyansh Jain input.cena = portal->cena; 26623df3960SShreyansh Jain 26723df3960SShreyansh Jain return process_portal_free(&input); 26823df3960SShreyansh Jain } 26923df3960SShreyansh Jain 27023df3960SShreyansh Jain int bman_allocate_raw_portal(struct dpaa_raw_portal *portal) 27123df3960SShreyansh Jain { 27223df3960SShreyansh Jain struct dpaa_ioctl_raw_portal input; 27323df3960SShreyansh Jain int ret; 27423df3960SShreyansh Jain 27523df3960SShreyansh Jain input.type = dpaa_portal_bman; 27623df3960SShreyansh Jain input.index = portal->index; 27723df3960SShreyansh Jain input.enable_stash = 0; 27823df3960SShreyansh Jain 27923df3960SShreyansh Jain ret = process_portal_allocate(&input); 28023df3960SShreyansh Jain if (ret) 28123df3960SShreyansh Jain return ret; 28223df3960SShreyansh Jain portal->index = input.index; 28323df3960SShreyansh Jain portal->cinh = input.cinh; 28423df3960SShreyansh Jain portal->cena = input.cena; 28523df3960SShreyansh Jain return 0; 28623df3960SShreyansh Jain } 28723df3960SShreyansh Jain 28823df3960SShreyansh Jain int bman_free_raw_portal(struct dpaa_raw_portal *portal) 28923df3960SShreyansh Jain { 29023df3960SShreyansh Jain struct dpaa_ioctl_raw_portal input; 29123df3960SShreyansh Jain 29223df3960SShreyansh Jain input.type = dpaa_portal_bman; 29323df3960SShreyansh Jain input.index = portal->index; 29423df3960SShreyansh Jain input.cinh = portal->cinh; 29523df3960SShreyansh Jain input.cena = portal->cena; 29623df3960SShreyansh Jain 29723df3960SShreyansh Jain return process_portal_free(&input); 29823df3960SShreyansh Jain } 299