// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2019-2024 Linaro Ltd. */ #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/iommu.h> #include <linux/platform_device.h> #include <linux/types.h> #include <linux/soc/qcom/smem.h> #include "gsi_trans.h" #include "ipa.h" #include "ipa_cmd.h" #include "ipa_data.h" #include "ipa_mem.h" #include "ipa_reg.h" #include "ipa_table.h" /* "Canary" value placed between memory regions to detect overflow */ #define IPA_MEM_CANARY_VAL … /* SMEM host id representing the modem. */ #define QCOM_SMEM_HOST_MODEM … const struct ipa_mem *ipa_mem_find(struct ipa *ipa, enum ipa_mem_id mem_id) { … } /* Add an immediate command to a transaction that zeroes a memory region */ static void ipa_mem_zero_region_add(struct gsi_trans *trans, enum ipa_mem_id mem_id) { … } /** * ipa_mem_setup() - Set up IPA AP and modem shared memory areas * @ipa: IPA pointer * * Set up the shared memory regions in IPA local memory. This involves * zero-filling memory regions, and in the case of header memory, telling * the IPA where it's located. * * This function performs the initial setup of this memory. If the modem * crashes, its regions are re-zeroed in ipa_mem_zero_modem(). * * The AP informs the modem where its portions of memory are located * in a QMI exchange that occurs at modem startup. * * There is no need for a matching ipa_mem_teardown() function. * * Return: 0 if successful, or a negative error code */ int ipa_mem_setup(struct ipa *ipa) { … } /* Is the given memory region ID is valid for the current IPA version? */ static bool ipa_mem_id_valid(struct ipa *ipa, enum ipa_mem_id mem_id) { … } /* Must the given memory region be present in the configuration? */ static bool ipa_mem_id_required(struct ipa *ipa, enum ipa_mem_id mem_id) { … } static bool ipa_mem_valid_one(struct ipa *ipa, const struct ipa_mem *mem) { … } /* Verify each defined memory region is valid. */ static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem_data *mem_data) { … } /* Do all memory regions fit within the IPA local memory? */ static bool ipa_mem_size_valid(struct ipa *ipa) { … } /** * ipa_mem_config() - Configure IPA shared memory * @ipa: IPA pointer * * Return: 0 if successful, or a negative error code */ int ipa_mem_config(struct ipa *ipa) { … } /* Inverse of ipa_mem_config() */ void ipa_mem_deconfig(struct ipa *ipa) { … } /** * ipa_mem_zero_modem() - Zero IPA-local memory regions owned by the modem * @ipa: IPA pointer * * Zero regions of IPA-local memory used by the modem. These are configured * (and initially zeroed) by ipa_mem_setup(), but if the modem crashes and * restarts via SSR we need to re-initialize them. A QMI message tells the * modem where to find regions of IPA local memory it needs to know about * (these included). */ int ipa_mem_zero_modem(struct ipa *ipa) { … } /** * ipa_imem_init() - Initialize IMEM memory used by the IPA * @ipa: IPA pointer * @addr: Physical address of the IPA region in IMEM * @size: Size (bytes) of the IPA region in IMEM * * IMEM is a block of shared memory separate from system DRAM, and * a portion of this memory is available for the IPA to use. The * modem accesses this memory directly, but the IPA accesses it * via the IOMMU, using the AP's credentials. * * If this region exists (size > 0) we map it for read/write access * through the IOMMU using the IPA device. * * Note: @addr and @size are not guaranteed to be page-aligned. */ static int ipa_imem_init(struct ipa *ipa, unsigned long addr, size_t size) { … } static void ipa_imem_exit(struct ipa *ipa) { … } /** * ipa_smem_init() - Initialize SMEM memory used by the IPA * @ipa: IPA pointer * @item: Item ID of SMEM memory * @size: Size (bytes) of SMEM memory region * * SMEM is a managed block of shared DRAM, from which numbered "items" * can be allocated. One item is designated for use by the IPA. * * The modem accesses SMEM memory directly, but the IPA accesses it * via the IOMMU, using the AP's credentials. * * If size provided is non-zero, we allocate it and map it for * access through the IOMMU. * * Note: @size and the item address are is not guaranteed to be page-aligned. */ static int ipa_smem_init(struct ipa *ipa, u32 item, size_t size) { … } static void ipa_smem_exit(struct ipa *ipa) { … } /* Perform memory region-related initialization */ int ipa_mem_init(struct ipa *ipa, struct platform_device *pdev, const struct ipa_mem_data *mem_data) { … } /* Inverse of ipa_mem_init() */ void ipa_mem_exit(struct ipa *ipa) { … }