linux_dsm_epyc7002/drivers/media/platform/qcom/venus/firmware.c

290 lines
6.3 KiB
C
Raw Normal View History

/*
* Copyright (C) 2017 Linaro Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/iommu.h>
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
#include <linux/io.h>
#include <linux/of.h>
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/qcom_scm.h>
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
#include <linux/sizes.h>
#include <linux/soc/qcom/mdt_loader.h>
#include "core.h"
#include "firmware.h"
#include "hfi_venus_io.h"
#define VENUS_PAS_ID 9
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
#define VENUS_FW_MEM_SIZE (6 * SZ_1M)
#define VENUS_FW_START_ADDR 0x0
static void venus_reset_cpu(struct venus_core *core)
{
void __iomem *base = core->base;
writel(0, base + WRAPPER_FW_START_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_FW_END_ADDR);
writel(0, base + WRAPPER_CPA_START_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_CPA_END_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_NONPIX_START_ADDR);
writel(VENUS_FW_MEM_SIZE, base + WRAPPER_NONPIX_END_ADDR);
writel(0x0, base + WRAPPER_CPU_CGC_DIS);
writel(0x0, base + WRAPPER_CPU_CLOCK_CONFIG);
/* Bring ARM9 out of reset */
writel(0, base + WRAPPER_A9SS_SW_RESET);
}
int venus_set_hw_state(struct venus_core *core, bool resume)
{
if (core->use_tz)
return qcom_scm_set_remote_state(resume, 0);
if (resume)
venus_reset_cpu(core);
else
writel(1, core->base + WRAPPER_A9SS_SW_RESET);
return 0;
}
static int venus_load_fw(struct venus_core *core, const char *fwname,
phys_addr_t *mem_phys, size_t *mem_size)
{
const struct firmware *mdt;
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
struct device_node *node;
struct device *dev;
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
struct resource r;
ssize_t fw_size;
void *mem_va;
int ret;
dev = core->dev;
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
node = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!node) {
dev_err(dev, "no memory-region specified\n");
return -EINVAL;
}
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
ret = of_address_to_resource(node, 0, &r);
if (ret)
return ret;
*mem_phys = r.start;
*mem_size = resource_size(&r);
if (*mem_size < VENUS_FW_MEM_SIZE)
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
return -EINVAL;
mem_va = memremap(r.start, *mem_size, MEMREMAP_WC);
if (!mem_va) {
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
dev_err(dev, "unable to map memory region: %pa+%zx\n",
&r.start, *mem_size);
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
return -ENOMEM;
}
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
ret = request_firmware(&mdt, fwname, dev);
if (ret < 0)
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
goto err_unmap;
fw_size = qcom_mdt_get_size(mdt);
if (fw_size < 0) {
ret = fw_size;
release_firmware(mdt);
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
goto err_unmap;
}
if (core->use_tz)
ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID,
mem_va, *mem_phys, *mem_size, NULL);
else
ret = qcom_mdt_load_no_init(dev, mdt, fwname, VENUS_PAS_ID,
mem_va, *mem_phys, *mem_size, NULL);
release_firmware(mdt);
media: venus: don't abuse dma_alloc for non-DMA allocations In venus_boot(), we pass a pointer to a phys_addr_t into dmam_alloc_coherent, which the compiler warns about: platform/qcom/venus/firmware.c: In function 'venus_boot': platform/qcom/venus/firmware.c:63:49: error: passing argument 3 of 'dmam_alloc_coherent' from incompatible pointer type [-Werror=incompatible-pointer-types] To avoid the error refactor venus_boot function by discard dma_alloc_coherent invocation because we don't want to map the memory for the device. Something more, the usage of DMA mapping API is actually wrong and the current implementation relies on several bugs in DMA mapping code. When these bugs are fixed that will break firmware loading, so fix this now to avoid future troubles. The meaning of venus_boot is to copy the content of the firmware buffer into reserved (and memblock removed) block of memory and pass that physical address to the trusted zone for authentication and mapping through iommu form the secure world. After iommu mapping is done the iova is passed as ane entry point to the remote processor. After this change memory-region property is parsed manually and the physical address is memremap to CPU, call mdt_load to load firmware segments into proper places and unmap reserved memory. Fixes: af2c3834c8ca ("[media] media: venus: adding core part and helper functions") Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2017-07-19 18:51:37 +07:00
err_unmap:
memunmap(mem_va);
return ret;
}
static int venus_boot_no_tz(struct venus_core *core, phys_addr_t mem_phys,
size_t mem_size)
{
struct iommu_domain *iommu;
struct device *dev;
int ret;
dev = core->fw.dev;
if (!dev)
return -EPROBE_DEFER;
iommu = core->fw.iommu_domain;
ret = iommu_map(iommu, VENUS_FW_START_ADDR, mem_phys, mem_size,
IOMMU_READ | IOMMU_WRITE | IOMMU_PRIV);
if (ret) {
dev_err(dev, "could not map video firmware region\n");
return ret;
}
venus_reset_cpu(core);
return 0;
}
static int venus_shutdown_no_tz(struct venus_core *core)
{
struct iommu_domain *iommu;
size_t unmapped;
u32 reg;
struct device *dev = core->fw.dev;
void __iomem *base = core->base;
/* Assert the reset to ARM9 */
reg = readl_relaxed(base + WRAPPER_A9SS_SW_RESET);
reg |= WRAPPER_A9SS_SW_RESET_BIT;
writel_relaxed(reg, base + WRAPPER_A9SS_SW_RESET);
/* Make sure reset is asserted before the mapping is removed */
mb();
iommu = core->fw.iommu_domain;
unmapped = iommu_unmap(iommu, VENUS_FW_START_ADDR, VENUS_FW_MEM_SIZE);
if (unmapped != VENUS_FW_MEM_SIZE)
dev_err(dev, "failed to unmap firmware\n");
return 0;
}
int venus_boot(struct venus_core *core)
{
struct device *dev = core->dev;
phys_addr_t mem_phys;
size_t mem_size;
int ret;
if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) ||
(core->use_tz && !qcom_scm_is_available()))
return -EPROBE_DEFER;
ret = venus_load_fw(core, core->res->fwname, &mem_phys, &mem_size);
if (ret) {
dev_err(dev, "fail to load video firmware\n");
return -EINVAL;
}
if (core->use_tz)
ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
else
ret = venus_boot_no_tz(core, mem_phys, mem_size);
return ret;
}
int venus_shutdown(struct venus_core *core)
{
int ret;
if (core->use_tz)
ret = qcom_scm_pas_shutdown(VENUS_PAS_ID);
else
ret = venus_shutdown_no_tz(core);
return ret;
}
int venus_firmware_init(struct venus_core *core)
{
struct platform_device_info info;
struct iommu_domain *iommu_dom;
struct platform_device *pdev;
struct device_node *np;
int ret;
np = of_get_child_by_name(core->dev->of_node, "video-firmware");
if (!np) {
core->use_tz = true;
return 0;
}
memset(&info, 0, sizeof(info));
info.fwnode = &np->fwnode;
info.parent = core->dev;
info.name = np->name;
info.dma_mask = DMA_BIT_MASK(32);
pdev = platform_device_register_full(&info);
if (IS_ERR(pdev)) {
of_node_put(np);
return PTR_ERR(pdev);
}
pdev->dev.of_node = np;
ret = of_dma_configure(&pdev->dev, np, true);
if (ret) {
dev_err(core->dev, "dma configure fail\n");
goto err_unregister;
}
core->fw.dev = &pdev->dev;
iommu_dom = iommu_domain_alloc(&platform_bus_type);
if (!iommu_dom) {
dev_err(core->fw.dev, "Failed to allocate iommu domain\n");
ret = -ENOMEM;
goto err_unregister;
}
ret = iommu_attach_device(iommu_dom, core->fw.dev);
if (ret) {
dev_err(core->fw.dev, "could not attach device\n");
goto err_iommu_free;
}
core->fw.iommu_domain = iommu_dom;
of_node_put(np);
return 0;
err_iommu_free:
iommu_domain_free(iommu_dom);
err_unregister:
platform_device_unregister(pdev);
of_node_put(np);
return ret;
}
void venus_firmware_deinit(struct venus_core *core)
{
struct iommu_domain *iommu;
if (!core->fw.dev)
return;
iommu = core->fw.iommu_domain;
iommu_detach_device(iommu, core->fw.dev);
iommu_domain_free(iommu);
platform_device_unregister(to_platform_device(core->fw.dev));
}