1ba764c4dSAlex Elder // SPDX-License-Identifier: GPL-2.0 2ba764c4dSAlex Elder 3ba764c4dSAlex Elder /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. 474858b63SAlex Elder * Copyright (C) 2019-2021 Linaro Ltd. 5ba764c4dSAlex Elder */ 6ba764c4dSAlex Elder 7ba764c4dSAlex Elder #include <linux/types.h> 8ba764c4dSAlex Elder #include <linux/bitfield.h> 9ba764c4dSAlex Elder #include <linux/bug.h> 10ba764c4dSAlex Elder #include <linux/dma-mapping.h> 113e313c3fSAlex Elder #include <linux/iommu.h> 12ba764c4dSAlex Elder #include <linux/io.h> 13a0036bb4SAlex Elder #include <linux/soc/qcom/smem.h> 14ba764c4dSAlex Elder 15ba764c4dSAlex Elder #include "ipa.h" 16ba764c4dSAlex Elder #include "ipa_reg.h" 173128aae8SAlex Elder #include "ipa_data.h" 18ba764c4dSAlex Elder #include "ipa_cmd.h" 19ba764c4dSAlex Elder #include "ipa_mem.h" 20ba764c4dSAlex Elder #include "ipa_table.h" 21ba764c4dSAlex Elder #include "gsi_trans.h" 22ba764c4dSAlex Elder 23ba764c4dSAlex Elder /* "Canary" value placed between memory regions to detect overflow */ 24ba764c4dSAlex Elder #define IPA_MEM_CANARY_VAL cpu_to_le32(0xdeadbeef) 25ba764c4dSAlex Elder 26a0036bb4SAlex Elder /* SMEM host id representing the modem. */ 27a0036bb4SAlex Elder #define QCOM_SMEM_HOST_MODEM 1 28a0036bb4SAlex Elder 29ba764c4dSAlex Elder /* Add an immediate command to a transaction that zeroes a memory region */ 30ba764c4dSAlex Elder static void 31ba764c4dSAlex Elder ipa_mem_zero_region_add(struct gsi_trans *trans, const struct ipa_mem *mem) 32ba764c4dSAlex Elder { 33ba764c4dSAlex Elder struct ipa *ipa = container_of(trans->gsi, struct ipa, gsi); 34ba764c4dSAlex Elder dma_addr_t addr = ipa->zero_addr; 35ba764c4dSAlex Elder 36ba764c4dSAlex Elder if (!mem->size) 37ba764c4dSAlex Elder return; 38ba764c4dSAlex Elder 39ba764c4dSAlex Elder ipa_cmd_dma_shared_mem_add(trans, mem->offset, mem->size, addr, true); 40ba764c4dSAlex Elder } 41ba764c4dSAlex Elder 42ba764c4dSAlex Elder /** 43ba764c4dSAlex Elder * ipa_mem_setup() - Set up IPA AP and modem shared memory areas 44e3eea08eSAlex Elder * @ipa: IPA pointer 45ba764c4dSAlex Elder * 46ba764c4dSAlex Elder * Set up the shared memory regions in IPA local memory. This involves 47ba764c4dSAlex Elder * zero-filling memory regions, and in the case of header memory, telling 48ba764c4dSAlex Elder * the IPA where it's located. 49ba764c4dSAlex Elder * 50ba764c4dSAlex Elder * This function performs the initial setup of this memory. If the modem 51ba764c4dSAlex Elder * crashes, its regions are re-zeroed in ipa_mem_zero_modem(). 52ba764c4dSAlex Elder * 53ba764c4dSAlex Elder * The AP informs the modem where its portions of memory are located 54ba764c4dSAlex Elder * in a QMI exchange that occurs at modem startup. 55ba764c4dSAlex Elder * 5674858b63SAlex Elder * There is no need for a matching ipa_mem_teardown() function. 5774858b63SAlex Elder * 58e3eea08eSAlex Elder * Return: 0 if successful, or a negative error code 59ba764c4dSAlex Elder */ 60ba764c4dSAlex Elder int ipa_mem_setup(struct ipa *ipa) 61ba764c4dSAlex Elder { 62ba764c4dSAlex Elder dma_addr_t addr = ipa->zero_addr; 63ba764c4dSAlex Elder struct gsi_trans *trans; 64ba764c4dSAlex Elder u32 offset; 65ba764c4dSAlex Elder u16 size; 66e6e49e43SAlex Elder u32 val; 67ba764c4dSAlex Elder 68ba764c4dSAlex Elder /* Get a transaction to define the header memory region and to zero 69ba764c4dSAlex Elder * the processing context and modem memory regions. 70ba764c4dSAlex Elder */ 71ba764c4dSAlex Elder trans = ipa_cmd_trans_alloc(ipa, 4); 72ba764c4dSAlex Elder if (!trans) { 73ba764c4dSAlex Elder dev_err(&ipa->pdev->dev, "no transaction for memory setup\n"); 74ba764c4dSAlex Elder return -EBUSY; 75ba764c4dSAlex Elder } 76ba764c4dSAlex Elder 77ba764c4dSAlex Elder /* Initialize IPA-local header memory. The modem and AP header 78ba764c4dSAlex Elder * regions are contiguous, and initialized together. 79ba764c4dSAlex Elder */ 80ba764c4dSAlex Elder offset = ipa->mem[IPA_MEM_MODEM_HEADER].offset; 81ba764c4dSAlex Elder size = ipa->mem[IPA_MEM_MODEM_HEADER].size; 82ba764c4dSAlex Elder size += ipa->mem[IPA_MEM_AP_HEADER].size; 83ba764c4dSAlex Elder 84ba764c4dSAlex Elder ipa_cmd_hdr_init_local_add(trans, offset, size, addr); 85ba764c4dSAlex Elder 86ba764c4dSAlex Elder ipa_mem_zero_region_add(trans, &ipa->mem[IPA_MEM_MODEM_PROC_CTX]); 87ba764c4dSAlex Elder 88ba764c4dSAlex Elder ipa_mem_zero_region_add(trans, &ipa->mem[IPA_MEM_AP_PROC_CTX]); 89ba764c4dSAlex Elder 90ba764c4dSAlex Elder ipa_mem_zero_region_add(trans, &ipa->mem[IPA_MEM_MODEM]); 91ba764c4dSAlex Elder 92ba764c4dSAlex Elder gsi_trans_commit_wait(trans); 93ba764c4dSAlex Elder 94ba764c4dSAlex Elder /* Tell the hardware where the processing context area is located */ 95e6e49e43SAlex Elder offset = ipa->mem_offset + ipa->mem[IPA_MEM_MODEM_PROC_CTX].offset; 96e6e49e43SAlex Elder val = proc_cntxt_base_addr_encoded(ipa->version, offset); 97e6e49e43SAlex Elder iowrite32(val, ipa->reg_virt + IPA_REG_LOCAL_PKT_PROC_CNTXT_OFFSET); 98ba764c4dSAlex Elder 99ba764c4dSAlex Elder return 0; 100ba764c4dSAlex Elder } 101ba764c4dSAlex Elder 102ba764c4dSAlex Elder #ifdef IPA_VALIDATE 103ba764c4dSAlex Elder 104ba764c4dSAlex Elder static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) 105ba764c4dSAlex Elder { 106ba764c4dSAlex Elder const struct ipa_mem *mem = &ipa->mem[mem_id]; 107ba764c4dSAlex Elder struct device *dev = &ipa->pdev->dev; 108ba764c4dSAlex Elder u16 size_multiple; 109ba764c4dSAlex Elder 110ba764c4dSAlex Elder /* Other than modem memory, sizes must be a multiple of 8 */ 111ba764c4dSAlex Elder size_multiple = mem_id == IPA_MEM_MODEM ? 4 : 8; 112ba764c4dSAlex Elder if (mem->size % size_multiple) 113ba764c4dSAlex Elder dev_err(dev, "region %u size not a multiple of %u bytes\n", 114ba764c4dSAlex Elder mem_id, size_multiple); 115ba764c4dSAlex Elder else if (mem->offset % 8) 116ba764c4dSAlex Elder dev_err(dev, "region %u offset not 8-byte aligned\n", mem_id); 117ba764c4dSAlex Elder else if (mem->offset < mem->canary_count * sizeof(__le32)) 118ba764c4dSAlex Elder dev_err(dev, "region %u offset too small for %hu canaries\n", 119ba764c4dSAlex Elder mem_id, mem->canary_count); 120ba764c4dSAlex Elder else if (mem->offset + mem->size > ipa->mem_size) 121ba764c4dSAlex Elder dev_err(dev, "region %u ends beyond memory limit (0x%08x)\n", 122ba764c4dSAlex Elder mem_id, ipa->mem_size); 123ba764c4dSAlex Elder else 124ba764c4dSAlex Elder return true; 125ba764c4dSAlex Elder 126ba764c4dSAlex Elder return false; 127ba764c4dSAlex Elder } 128ba764c4dSAlex Elder 129ba764c4dSAlex Elder #else /* !IPA_VALIDATE */ 130ba764c4dSAlex Elder 131ba764c4dSAlex Elder static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) 132ba764c4dSAlex Elder { 133ba764c4dSAlex Elder return true; 134ba764c4dSAlex Elder } 135ba764c4dSAlex Elder 136ba764c4dSAlex Elder #endif /*! IPA_VALIDATE */ 137ba764c4dSAlex Elder 138ba764c4dSAlex Elder /** 139ba764c4dSAlex Elder * ipa_mem_config() - Configure IPA shared memory 140e3eea08eSAlex Elder * @ipa: IPA pointer 141ba764c4dSAlex Elder * 142e3eea08eSAlex Elder * Return: 0 if successful, or a negative error code 143ba764c4dSAlex Elder */ 144ba764c4dSAlex Elder int ipa_mem_config(struct ipa *ipa) 145ba764c4dSAlex Elder { 146ba764c4dSAlex Elder struct device *dev = &ipa->pdev->dev; 147ba764c4dSAlex Elder enum ipa_mem_id mem_id; 148ba764c4dSAlex Elder dma_addr_t addr; 149ba764c4dSAlex Elder u32 mem_size; 150ba764c4dSAlex Elder void *virt; 151ba764c4dSAlex Elder u32 val; 152ba764c4dSAlex Elder 153ba764c4dSAlex Elder /* Check the advertised location and size of the shared memory area */ 154ba764c4dSAlex Elder val = ioread32(ipa->reg_virt + IPA_REG_SHARED_MEM_SIZE_OFFSET); 155ba764c4dSAlex Elder 156ba764c4dSAlex Elder /* The fields in the register are in 8 byte units */ 157ba764c4dSAlex Elder ipa->mem_offset = 8 * u32_get_bits(val, SHARED_MEM_BADDR_FMASK); 158ba764c4dSAlex Elder /* Make sure the end is within the region's mapped space */ 159ba764c4dSAlex Elder mem_size = 8 * u32_get_bits(val, SHARED_MEM_SIZE_FMASK); 160ba764c4dSAlex Elder 161ba764c4dSAlex Elder /* If the sizes don't match, issue a warning */ 1622c642c48SAlex Elder if (ipa->mem_offset + mem_size < ipa->mem_size) { 163ba764c4dSAlex Elder dev_warn(dev, "limiting IPA memory size to 0x%08x\n", 164ba764c4dSAlex Elder mem_size); 165ba764c4dSAlex Elder ipa->mem_size = mem_size; 1662c642c48SAlex Elder } else if (ipa->mem_offset + mem_size > ipa->mem_size) { 1672c642c48SAlex Elder dev_dbg(dev, "ignoring larger reported memory size: 0x%08x\n", 1682c642c48SAlex Elder mem_size); 169ba764c4dSAlex Elder } 170ba764c4dSAlex Elder 171ba764c4dSAlex Elder /* Prealloc DMA memory for zeroing regions */ 172ba764c4dSAlex Elder virt = dma_alloc_coherent(dev, IPA_MEM_MAX, &addr, GFP_KERNEL); 173ba764c4dSAlex Elder if (!virt) 174ba764c4dSAlex Elder return -ENOMEM; 175ba764c4dSAlex Elder ipa->zero_addr = addr; 176ba764c4dSAlex Elder ipa->zero_virt = virt; 177ba764c4dSAlex Elder ipa->zero_size = IPA_MEM_MAX; 178ba764c4dSAlex Elder 179ba764c4dSAlex Elder /* Verify each defined memory region is valid, and if indicated 180ba764c4dSAlex Elder * for the region, write "canary" values in the space prior to 181ba764c4dSAlex Elder * the region's base address. 182ba764c4dSAlex Elder */ 183*440c3247SAlex Elder for (mem_id = 0; mem_id < ipa->mem_count; mem_id++) { 184ba764c4dSAlex Elder const struct ipa_mem *mem = &ipa->mem[mem_id]; 185ba764c4dSAlex Elder u16 canary_count; 186ba764c4dSAlex Elder __le32 *canary; 187ba764c4dSAlex Elder 188ba764c4dSAlex Elder /* Validate all regions (even undefined ones) */ 189ba764c4dSAlex Elder if (!ipa_mem_valid(ipa, mem_id)) 190ba764c4dSAlex Elder goto err_dma_free; 191ba764c4dSAlex Elder 192ba764c4dSAlex Elder /* Skip over undefined regions */ 193ba764c4dSAlex Elder if (!mem->offset && !mem->size) 194ba764c4dSAlex Elder continue; 195ba764c4dSAlex Elder 196ba764c4dSAlex Elder canary_count = mem->canary_count; 197ba764c4dSAlex Elder if (!canary_count) 198ba764c4dSAlex Elder continue; 199ba764c4dSAlex Elder 200ba764c4dSAlex Elder /* Write canary values in the space before the region */ 201ba764c4dSAlex Elder canary = ipa->mem_virt + ipa->mem_offset + mem->offset; 202ba764c4dSAlex Elder do 203ba764c4dSAlex Elder *--canary = IPA_MEM_CANARY_VAL; 204ba764c4dSAlex Elder while (--canary_count); 205ba764c4dSAlex Elder } 206ba764c4dSAlex Elder 207ba764c4dSAlex Elder /* Make sure filter and route table memory regions are valid */ 208ba764c4dSAlex Elder if (!ipa_table_valid(ipa)) 209ba764c4dSAlex Elder goto err_dma_free; 210ba764c4dSAlex Elder 211ba764c4dSAlex Elder /* Validate memory-related properties relevant to immediate commands */ 212ba764c4dSAlex Elder if (!ipa_cmd_data_valid(ipa)) 213ba764c4dSAlex Elder goto err_dma_free; 214ba764c4dSAlex Elder 215ba764c4dSAlex Elder /* Verify the microcontroller ring alignment (0 is OK too) */ 216ba764c4dSAlex Elder if (ipa->mem[IPA_MEM_UC_EVENT_RING].offset % 1024) { 217ba764c4dSAlex Elder dev_err(dev, "microcontroller ring not 1024-byte aligned\n"); 218ba764c4dSAlex Elder goto err_dma_free; 219ba764c4dSAlex Elder } 220ba764c4dSAlex Elder 221ba764c4dSAlex Elder return 0; 222ba764c4dSAlex Elder 223ba764c4dSAlex Elder err_dma_free: 224ba764c4dSAlex Elder dma_free_coherent(dev, IPA_MEM_MAX, ipa->zero_virt, ipa->zero_addr); 225ba764c4dSAlex Elder 226ba764c4dSAlex Elder return -EINVAL; 227ba764c4dSAlex Elder } 228ba764c4dSAlex Elder 229ba764c4dSAlex Elder /* Inverse of ipa_mem_config() */ 230ba764c4dSAlex Elder void ipa_mem_deconfig(struct ipa *ipa) 231ba764c4dSAlex Elder { 232ba764c4dSAlex Elder struct device *dev = &ipa->pdev->dev; 233ba764c4dSAlex Elder 234ba764c4dSAlex Elder dma_free_coherent(dev, ipa->zero_size, ipa->zero_virt, ipa->zero_addr); 235ba764c4dSAlex Elder ipa->zero_size = 0; 236ba764c4dSAlex Elder ipa->zero_virt = NULL; 237ba764c4dSAlex Elder ipa->zero_addr = 0; 238ba764c4dSAlex Elder } 239ba764c4dSAlex Elder 240ba764c4dSAlex Elder /** 241ba764c4dSAlex Elder * ipa_mem_zero_modem() - Zero IPA-local memory regions owned by the modem 242e3eea08eSAlex Elder * @ipa: IPA pointer 243ba764c4dSAlex Elder * 244ba764c4dSAlex Elder * Zero regions of IPA-local memory used by the modem. These are configured 245ba764c4dSAlex Elder * (and initially zeroed) by ipa_mem_setup(), but if the modem crashes and 246ba764c4dSAlex Elder * restarts via SSR we need to re-initialize them. A QMI message tells the 247ba764c4dSAlex Elder * modem where to find regions of IPA local memory it needs to know about 248ba764c4dSAlex Elder * (these included). 249ba764c4dSAlex Elder */ 250ba764c4dSAlex Elder int ipa_mem_zero_modem(struct ipa *ipa) 251ba764c4dSAlex Elder { 252ba764c4dSAlex Elder struct gsi_trans *trans; 253ba764c4dSAlex Elder 254ba764c4dSAlex Elder /* Get a transaction to zero the modem memory, modem header, 255ba764c4dSAlex Elder * and modem processing context regions. 256ba764c4dSAlex Elder */ 257ba764c4dSAlex Elder trans = ipa_cmd_trans_alloc(ipa, 3); 258ba764c4dSAlex Elder if (!trans) { 259ba764c4dSAlex Elder dev_err(&ipa->pdev->dev, 260ba764c4dSAlex Elder "no transaction to zero modem memory\n"); 261ba764c4dSAlex Elder return -EBUSY; 262ba764c4dSAlex Elder } 263ba764c4dSAlex Elder 264ba764c4dSAlex Elder ipa_mem_zero_region_add(trans, &ipa->mem[IPA_MEM_MODEM_HEADER]); 265ba764c4dSAlex Elder 266ba764c4dSAlex Elder ipa_mem_zero_region_add(trans, &ipa->mem[IPA_MEM_MODEM_PROC_CTX]); 267ba764c4dSAlex Elder 268ba764c4dSAlex Elder ipa_mem_zero_region_add(trans, &ipa->mem[IPA_MEM_MODEM]); 269ba764c4dSAlex Elder 270ba764c4dSAlex Elder gsi_trans_commit_wait(trans); 271ba764c4dSAlex Elder 272ba764c4dSAlex Elder return 0; 273ba764c4dSAlex Elder } 274ba764c4dSAlex Elder 2753e313c3fSAlex Elder /** 2763e313c3fSAlex Elder * ipa_imem_init() - Initialize IMEM memory used by the IPA 2773e313c3fSAlex Elder * @ipa: IPA pointer 2783e313c3fSAlex Elder * @addr: Physical address of the IPA region in IMEM 2793e313c3fSAlex Elder * @size: Size (bytes) of the IPA region in IMEM 2803e313c3fSAlex Elder * 2813e313c3fSAlex Elder * IMEM is a block of shared memory separate from system DRAM, and 2823e313c3fSAlex Elder * a portion of this memory is available for the IPA to use. The 2833e313c3fSAlex Elder * modem accesses this memory directly, but the IPA accesses it 2843e313c3fSAlex Elder * via the IOMMU, using the AP's credentials. 2853e313c3fSAlex Elder * 2863e313c3fSAlex Elder * If this region exists (size > 0) we map it for read/write access 2873e313c3fSAlex Elder * through the IOMMU using the IPA device. 2883e313c3fSAlex Elder * 2893e313c3fSAlex Elder * Note: @addr and @size are not guaranteed to be page-aligned. 2903e313c3fSAlex Elder */ 2913e313c3fSAlex Elder static int ipa_imem_init(struct ipa *ipa, unsigned long addr, size_t size) 2923e313c3fSAlex Elder { 2933e313c3fSAlex Elder struct device *dev = &ipa->pdev->dev; 2943e313c3fSAlex Elder struct iommu_domain *domain; 2953e313c3fSAlex Elder unsigned long iova; 2963e313c3fSAlex Elder phys_addr_t phys; 2973e313c3fSAlex Elder int ret; 2983e313c3fSAlex Elder 2993e313c3fSAlex Elder if (!size) 3003e313c3fSAlex Elder return 0; /* IMEM memory not used */ 3013e313c3fSAlex Elder 3023e313c3fSAlex Elder domain = iommu_get_domain_for_dev(dev); 3033e313c3fSAlex Elder if (!domain) { 3043e313c3fSAlex Elder dev_err(dev, "no IOMMU domain found for IMEM\n"); 3053e313c3fSAlex Elder return -EINVAL; 3063e313c3fSAlex Elder } 3073e313c3fSAlex Elder 3083e313c3fSAlex Elder /* Align the address down and the size up to page boundaries */ 3093e313c3fSAlex Elder phys = addr & PAGE_MASK; 3103e313c3fSAlex Elder size = PAGE_ALIGN(size + addr - phys); 3113e313c3fSAlex Elder iova = phys; /* We just want a direct mapping */ 3123e313c3fSAlex Elder 3133e313c3fSAlex Elder ret = iommu_map(domain, iova, phys, size, IOMMU_READ | IOMMU_WRITE); 3143e313c3fSAlex Elder if (ret) 3153e313c3fSAlex Elder return ret; 3163e313c3fSAlex Elder 3173e313c3fSAlex Elder ipa->imem_iova = iova; 3183e313c3fSAlex Elder ipa->imem_size = size; 3193e313c3fSAlex Elder 3203e313c3fSAlex Elder return 0; 3213e313c3fSAlex Elder } 3223e313c3fSAlex Elder 3233e313c3fSAlex Elder static void ipa_imem_exit(struct ipa *ipa) 3243e313c3fSAlex Elder { 3253e313c3fSAlex Elder struct iommu_domain *domain; 3263e313c3fSAlex Elder struct device *dev; 3273e313c3fSAlex Elder 3283e313c3fSAlex Elder if (!ipa->imem_size) 3293e313c3fSAlex Elder return; 3303e313c3fSAlex Elder 3313e313c3fSAlex Elder dev = &ipa->pdev->dev; 3323e313c3fSAlex Elder domain = iommu_get_domain_for_dev(dev); 3333e313c3fSAlex Elder if (domain) { 3343e313c3fSAlex Elder size_t size; 3353e313c3fSAlex Elder 3363e313c3fSAlex Elder size = iommu_unmap(domain, ipa->imem_iova, ipa->imem_size); 3373e313c3fSAlex Elder if (size != ipa->imem_size) 338113b6ea0SAlex Elder dev_warn(dev, "unmapped %zu IMEM bytes, expected %zu\n", 3393e313c3fSAlex Elder size, ipa->imem_size); 3403e313c3fSAlex Elder } else { 3413e313c3fSAlex Elder dev_err(dev, "couldn't get IPA IOMMU domain for IMEM\n"); 3423e313c3fSAlex Elder } 3433e313c3fSAlex Elder 3443e313c3fSAlex Elder ipa->imem_size = 0; 3453e313c3fSAlex Elder ipa->imem_iova = 0; 3463e313c3fSAlex Elder } 3473e313c3fSAlex Elder 348a0036bb4SAlex Elder /** 349a0036bb4SAlex Elder * ipa_smem_init() - Initialize SMEM memory used by the IPA 350a0036bb4SAlex Elder * @ipa: IPA pointer 351a0036bb4SAlex Elder * @item: Item ID of SMEM memory 352a0036bb4SAlex Elder * @size: Size (bytes) of SMEM memory region 353a0036bb4SAlex Elder * 354a0036bb4SAlex Elder * SMEM is a managed block of shared DRAM, from which numbered "items" 355a0036bb4SAlex Elder * can be allocated. One item is designated for use by the IPA. 356a0036bb4SAlex Elder * 357a0036bb4SAlex Elder * The modem accesses SMEM memory directly, but the IPA accesses it 358a0036bb4SAlex Elder * via the IOMMU, using the AP's credentials. 359a0036bb4SAlex Elder * 360a0036bb4SAlex Elder * If size provided is non-zero, we allocate it and map it for 361a0036bb4SAlex Elder * access through the IOMMU. 362a0036bb4SAlex Elder * 363a0036bb4SAlex Elder * Note: @size and the item address are is not guaranteed to be page-aligned. 364a0036bb4SAlex Elder */ 365a0036bb4SAlex Elder static int ipa_smem_init(struct ipa *ipa, u32 item, size_t size) 366a0036bb4SAlex Elder { 367a0036bb4SAlex Elder struct device *dev = &ipa->pdev->dev; 368a0036bb4SAlex Elder struct iommu_domain *domain; 369a0036bb4SAlex Elder unsigned long iova; 370a0036bb4SAlex Elder phys_addr_t phys; 371a0036bb4SAlex Elder phys_addr_t addr; 372a0036bb4SAlex Elder size_t actual; 373a0036bb4SAlex Elder void *virt; 374a0036bb4SAlex Elder int ret; 375a0036bb4SAlex Elder 376a0036bb4SAlex Elder if (!size) 377a0036bb4SAlex Elder return 0; /* SMEM memory not used */ 378a0036bb4SAlex Elder 379a0036bb4SAlex Elder /* SMEM is memory shared between the AP and another system entity 380a0036bb4SAlex Elder * (in this case, the modem). An allocation from SMEM is persistent 381a0036bb4SAlex Elder * until the AP reboots; there is no way to free an allocated SMEM 382a0036bb4SAlex Elder * region. Allocation only reserves the space; to use it you need 383a0036bb4SAlex Elder * to "get" a pointer it (this implies no reference counting). 384a0036bb4SAlex Elder * The item might have already been allocated, in which case we 385a0036bb4SAlex Elder * use it unless the size isn't what we expect. 386a0036bb4SAlex Elder */ 387a0036bb4SAlex Elder ret = qcom_smem_alloc(QCOM_SMEM_HOST_MODEM, item, size); 388a0036bb4SAlex Elder if (ret && ret != -EEXIST) { 389a0036bb4SAlex Elder dev_err(dev, "error %d allocating size %zu SMEM item %u\n", 390a0036bb4SAlex Elder ret, size, item); 391a0036bb4SAlex Elder return ret; 392a0036bb4SAlex Elder } 393a0036bb4SAlex Elder 394a0036bb4SAlex Elder /* Now get the address of the SMEM memory region */ 395a0036bb4SAlex Elder virt = qcom_smem_get(QCOM_SMEM_HOST_MODEM, item, &actual); 396a0036bb4SAlex Elder if (IS_ERR(virt)) { 397a0036bb4SAlex Elder ret = PTR_ERR(virt); 398a0036bb4SAlex Elder dev_err(dev, "error %d getting SMEM item %u\n", ret, item); 399a0036bb4SAlex Elder return ret; 400a0036bb4SAlex Elder } 401a0036bb4SAlex Elder 402a0036bb4SAlex Elder /* In case the region was already allocated, verify the size */ 403a0036bb4SAlex Elder if (ret && actual != size) { 404a0036bb4SAlex Elder dev_err(dev, "SMEM item %u has size %zu, expected %zu\n", 405a0036bb4SAlex Elder item, actual, size); 406a0036bb4SAlex Elder return -EINVAL; 407a0036bb4SAlex Elder } 408a0036bb4SAlex Elder 409a0036bb4SAlex Elder domain = iommu_get_domain_for_dev(dev); 410a0036bb4SAlex Elder if (!domain) { 411a0036bb4SAlex Elder dev_err(dev, "no IOMMU domain found for SMEM\n"); 412a0036bb4SAlex Elder return -EINVAL; 413a0036bb4SAlex Elder } 414a0036bb4SAlex Elder 415a0036bb4SAlex Elder /* Align the address down and the size up to a page boundary */ 416a0036bb4SAlex Elder addr = qcom_smem_virt_to_phys(virt) & PAGE_MASK; 417a0036bb4SAlex Elder phys = addr & PAGE_MASK; 418a0036bb4SAlex Elder size = PAGE_ALIGN(size + addr - phys); 419a0036bb4SAlex Elder iova = phys; /* We just want a direct mapping */ 420a0036bb4SAlex Elder 421a0036bb4SAlex Elder ret = iommu_map(domain, iova, phys, size, IOMMU_READ | IOMMU_WRITE); 422a0036bb4SAlex Elder if (ret) 423a0036bb4SAlex Elder return ret; 424a0036bb4SAlex Elder 425a0036bb4SAlex Elder ipa->smem_iova = iova; 426a0036bb4SAlex Elder ipa->smem_size = size; 427a0036bb4SAlex Elder 428a0036bb4SAlex Elder return 0; 429a0036bb4SAlex Elder } 430a0036bb4SAlex Elder 431a0036bb4SAlex Elder static void ipa_smem_exit(struct ipa *ipa) 432a0036bb4SAlex Elder { 433a0036bb4SAlex Elder struct device *dev = &ipa->pdev->dev; 434a0036bb4SAlex Elder struct iommu_domain *domain; 435a0036bb4SAlex Elder 436a0036bb4SAlex Elder domain = iommu_get_domain_for_dev(dev); 437a0036bb4SAlex Elder if (domain) { 438a0036bb4SAlex Elder size_t size; 439a0036bb4SAlex Elder 440a0036bb4SAlex Elder size = iommu_unmap(domain, ipa->smem_iova, ipa->smem_size); 441a0036bb4SAlex Elder if (size != ipa->smem_size) 442113b6ea0SAlex Elder dev_warn(dev, "unmapped %zu SMEM bytes, expected %zu\n", 443a0036bb4SAlex Elder size, ipa->smem_size); 444a0036bb4SAlex Elder 445a0036bb4SAlex Elder } else { 446a0036bb4SAlex Elder dev_err(dev, "couldn't get IPA IOMMU domain for SMEM\n"); 447a0036bb4SAlex Elder } 448a0036bb4SAlex Elder 449a0036bb4SAlex Elder ipa->smem_size = 0; 450a0036bb4SAlex Elder ipa->smem_iova = 0; 451a0036bb4SAlex Elder } 452a0036bb4SAlex Elder 453ba764c4dSAlex Elder /* Perform memory region-related initialization */ 4543128aae8SAlex Elder int ipa_mem_init(struct ipa *ipa, const struct ipa_mem_data *mem_data) 455ba764c4dSAlex Elder { 456ba764c4dSAlex Elder struct device *dev = &ipa->pdev->dev; 457ba764c4dSAlex Elder struct resource *res; 458ba764c4dSAlex Elder int ret; 459ba764c4dSAlex Elder 4603128aae8SAlex Elder if (mem_data->local_count > IPA_MEM_COUNT) { 461ba764c4dSAlex Elder dev_err(dev, "to many memory regions (%u > %u)\n", 4623128aae8SAlex Elder mem_data->local_count, IPA_MEM_COUNT); 463ba764c4dSAlex Elder return -EINVAL; 464ba764c4dSAlex Elder } 465ba764c4dSAlex Elder 466ba764c4dSAlex Elder ret = dma_set_mask_and_coherent(&ipa->pdev->dev, DMA_BIT_MASK(64)); 467ba764c4dSAlex Elder if (ret) { 468ba764c4dSAlex Elder dev_err(dev, "error %d setting DMA mask\n", ret); 469ba764c4dSAlex Elder return ret; 470ba764c4dSAlex Elder } 471ba764c4dSAlex Elder 472ba764c4dSAlex Elder res = platform_get_resource_byname(ipa->pdev, IORESOURCE_MEM, 473ba764c4dSAlex Elder "ipa-shared"); 474ba764c4dSAlex Elder if (!res) { 475ba764c4dSAlex Elder dev_err(dev, 476ba764c4dSAlex Elder "DT error getting \"ipa-shared\" memory property\n"); 477ba764c4dSAlex Elder return -ENODEV; 478ba764c4dSAlex Elder } 479ba764c4dSAlex Elder 480ba764c4dSAlex Elder ipa->mem_virt = memremap(res->start, resource_size(res), MEMREMAP_WC); 481ba764c4dSAlex Elder if (!ipa->mem_virt) { 482ba764c4dSAlex Elder dev_err(dev, "unable to remap \"ipa-shared\" memory\n"); 483ba764c4dSAlex Elder return -ENOMEM; 484ba764c4dSAlex Elder } 485ba764c4dSAlex Elder 486ba764c4dSAlex Elder ipa->mem_addr = res->start; 487ba764c4dSAlex Elder ipa->mem_size = resource_size(res); 488ba764c4dSAlex Elder 489ba764c4dSAlex Elder /* The ipa->mem[] array is indexed by enum ipa_mem_id values */ 490*440c3247SAlex Elder ipa->mem_count = mem_data->local_count; 4913128aae8SAlex Elder ipa->mem = mem_data->local; 492ba764c4dSAlex Elder 4933e313c3fSAlex Elder ret = ipa_imem_init(ipa, mem_data->imem_addr, mem_data->imem_size); 4943e313c3fSAlex Elder if (ret) 4953e313c3fSAlex Elder goto err_unmap; 4963e313c3fSAlex Elder 497a0036bb4SAlex Elder ret = ipa_smem_init(ipa, mem_data->smem_id, mem_data->smem_size); 498a0036bb4SAlex Elder if (ret) 499a0036bb4SAlex Elder goto err_imem_exit; 500a0036bb4SAlex Elder 501ba764c4dSAlex Elder return 0; 5023e313c3fSAlex Elder 503a0036bb4SAlex Elder err_imem_exit: 504a0036bb4SAlex Elder ipa_imem_exit(ipa); 5053e313c3fSAlex Elder err_unmap: 5063e313c3fSAlex Elder memunmap(ipa->mem_virt); 5073e313c3fSAlex Elder 5083e313c3fSAlex Elder return ret; 509ba764c4dSAlex Elder } 510ba764c4dSAlex Elder 511ba764c4dSAlex Elder /* Inverse of ipa_mem_init() */ 512ba764c4dSAlex Elder void ipa_mem_exit(struct ipa *ipa) 513ba764c4dSAlex Elder { 514a0036bb4SAlex Elder ipa_smem_exit(ipa); 5153e313c3fSAlex Elder ipa_imem_exit(ipa); 516ba764c4dSAlex Elder memunmap(ipa->mem_virt); 517ba764c4dSAlex Elder } 518