/* * 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. * */ #include #include #include #include #include #include #include #include #include #include "firmware.h" #define VENUS_PAS_ID 9 #define VENUS_FW_MEM_SIZE (6 * SZ_1M) int venus_boot(struct device *dev, const char *fwname) { const struct firmware *mdt; struct device_node *node; phys_addr_t mem_phys; struct resource r; ssize_t fw_size; size_t mem_size; void *mem_va; int ret; if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || !qcom_scm_is_available()) return -EPROBE_DEFER; node = of_parse_phandle(dev->of_node, "memory-region", 0); if (!node) { dev_err(dev, "no memory-region specified\n"); return -EINVAL; } 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) return -EINVAL; mem_va = memremap(r.start, mem_size, MEMREMAP_WC); if (!mem_va) { dev_err(dev, "unable to map memory region: %pa+%zx\n", &r.start, mem_size); return -ENOMEM; } ret = request_firmware(&mdt, fwname, dev); if (ret < 0) goto err_unmap; fw_size = qcom_mdt_get_size(mdt); if (fw_size < 0) { ret = fw_size; release_firmware(mdt); goto err_unmap; } ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys, mem_size, NULL); release_firmware(mdt); if (ret) goto err_unmap; ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID); if (ret) goto err_unmap; err_unmap: memunmap(mem_va); return ret; } int venus_shutdown(struct device *dev) { return qcom_scm_pas_shutdown(VENUS_PAS_ID); }