From patchwork Mon Jan 30 16:55:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 92925 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp1705298qgi; Mon, 30 Jan 2017 16:54:44 -0800 (PST) X-Received: by 10.84.229.13 with SMTP id b13mr35764856plk.175.1485824084631; Mon, 30 Jan 2017 16:54:44 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p126si14244953pfg.209.2017.01.30.16.54.44; Mon, 30 Jan 2017 16:54:44 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-arm-msm-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753748AbdAaAyi (ORCPT + 9 others); Mon, 30 Jan 2017 19:54:38 -0500 Received: from mail-pf0-f181.google.com ([209.85.192.181]:35786 "EHLO mail-pf0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753681AbdAaAyh (ORCPT ); Mon, 30 Jan 2017 19:54:37 -0500 Received: by mail-pf0-f181.google.com with SMTP id f144so96140835pfa.2 for ; Mon, 30 Jan 2017 16:54:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=n7Ty3Tz49y7j+1FUv0o2t5EK4zsjtRhzGFJ90j2mKbg=; b=HJ9DqeOJkoqFf4OacoyA0+zijvjneYubuhqS/m2qapwlelpZm28m+gVhx2FbKRbqTh Zn75jmDXLpLfr8y85FVXZ4e4RXMgrzRCd9JyN1t4loO2mww1+klU+1tnPSIAgZrU5bF2 T86Wcc5nGmPzvf0+pbab00sIcWGDG7O0cC4ys= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=n7Ty3Tz49y7j+1FUv0o2t5EK4zsjtRhzGFJ90j2mKbg=; b=pHuSXFWUgvUnzbHDdTaeFq0jWKquVVRj3Kbvo7t5UDW8pXDbIGVdOPDSalUbaJI0BN sV6zP/MKVjUekDUY3exHdUhkG+Lc8CdKPUPafU6rGJ5X+SOLrWmm1nB8TXV+newWs53e R46Hh1L/lv/Y2L9bnSKlDMF/FkIfyaaQ6zX4nB30FF4tOwr02lirNMj0uldzkyma4GI+ 9TLPXy0cCrNu5W21YdRwnkUkUrx7InTGtnEUz3Y1nf+dSBkNq4W/As/2oy79lAdwq1ao zSq1MsDbSufvySzjJZXvZTtlTMZ609Z/M7vpjdNwQ1c6S1VWSDkmGllqxWCiDOET4wJo uErw== X-Gm-Message-State: AIkVDXIF5KdDhzY/Y1DNIQbLMYfOWW8Y+L/KUAdvpYG1CxOdKFWuHUHGPOoikVDApQ734ph7 X-Received: by 10.98.144.218 with SMTP id q87mr26326283pfk.51.1485824076827; Mon, 30 Jan 2017 16:54:36 -0800 (PST) Received: from localhost.localdomain (ip68-111-223-48.sd.sd.cox.net. [68.111.223.48]) by smtp.gmail.com with ESMTPSA id d78sm35466933pfb.43.2017.01.30.16.54.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 30 Jan 2017 16:54:35 -0800 (PST) From: Bjorn Andersson To: Ohad Ben-Cohen , Bjorn Andersson Cc: linux-remoteproc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Avaneesh Kumar Dwivedi Subject: [PATCH 1/5] remoteproc: qcom: q6v5: Decouple driver from MDT loader Date: Mon, 30 Jan 2017 08:55:43 -0800 Message-Id: <20170130165547.4344-1-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.11.0 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Rather than duplicating half of the MDT loader in the validation step move the entire MDT parser into the q6v5 driver. This allows us to make the shared MDT-loader call the SCM PAS operations directly which simplifies the client code and allows for better reuse of the code. Cc: Avaneesh Kumar Dwivedi Signed-off-by: Bjorn Andersson --- drivers/remoteproc/Kconfig | 1 - drivers/remoteproc/qcom_q6v5_pil.c | 149 +++++++++++++++++++++++-------------- 2 files changed, 92 insertions(+), 58 deletions(-) -- 2.11.0 -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index a5e888043f1f..454fd9a4dd96 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -92,7 +92,6 @@ config QCOM_Q6V5_PIL depends on QCOM_SMEM depends on REMOTEPROC select MFD_SYSCON - select QCOM_MDT_LOADER select QCOM_SCM help Say y here to support the Qualcomm Peripherial Image Loader for the diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index 79a8a371a2fb..db341028f2d1 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -37,7 +37,7 @@ #include -#define MPSS_FIRMWARE_NAME "modem.mdt" +#define MPSS_FIRMWARE_NAME "modem" #define MPSS_CRASH_REASON_SMEM 421 @@ -277,6 +277,16 @@ static void q6v5_clk_disable(struct device *dev, clk_disable_unprepare(clks[i]); } +static struct resource_table *q6v5_find_rsc_table(struct rproc *rproc, + const struct firmware *fw, + int *tablesz) +{ + static struct resource_table table = { .ver = 1, }; + + *tablesz = sizeof(table); + return &table; +} + static int q6v5_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5 *qproc = rproc->priv; @@ -287,7 +297,7 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw) } static const struct rproc_fw_ops q6v5_fw_ops = { - .find_rsc_table = qcom_mdt_find_rsc_table, + .find_rsc_table = q6v5_find_rsc_table, .load = q6v5_load, }; @@ -464,46 +474,109 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw) return ret < 0 ? ret : 0; } -static int q6v5_mpss_validate(struct q6v5 *qproc, const struct firmware *fw) +static bool q6v5_phdr_valid(const struct elf32_phdr *phdr) +{ + if (phdr->p_type != PT_LOAD) + return false; + + if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH) + return false; + + if (!phdr->p_memsz) + return false; + + return true; +} + +static int q6v5_mpss_load(struct q6v5 *qproc) { const struct elf32_phdr *phdrs; const struct elf32_phdr *phdr; + const struct firmware *seg_fw; + const struct firmware *fw; struct elf32_hdr *ehdr; - phys_addr_t boot_addr; - phys_addr_t fw_addr; - bool relocate; + phys_addr_t mpss_reloc; + phys_addr_t min_addr = (phys_addr_t)ULLONG_MAX; + phys_addr_t max_addr = 0; + bool relocate = false; + char seg_name[10]; + size_t offset; size_t size; + void *ptr; int ret; int i; - ret = qcom_mdt_parse(fw, &fw_addr, NULL, &relocate); - if (ret) { - dev_err(qproc->dev, "failed to parse mdt header\n"); + ret = request_firmware(&fw, MPSS_FIRMWARE_NAME ".mdt", qproc->dev); + if (ret < 0) { + dev_err(qproc->dev, "unable to load " MPSS_FIRMWARE_NAME ".mdt\n"); return ret; } - if (relocate) - boot_addr = qproc->mpss_phys; - else - boot_addr = fw_addr; + /* Initialize the RMB validator */ + writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); + + ret = q6v5_mpss_init_image(qproc, fw); + if (ret) + goto release_firmware; ehdr = (struct elf32_hdr *)fw->data; phdrs = (struct elf32_phdr *)(ehdr + 1); - for (i = 0; i < ehdr->e_phnum; i++, phdr++) { + + for (i = 0; i < ehdr->e_phnum; i++) { phdr = &phdrs[i]; - if (phdr->p_type != PT_LOAD) + if (!q6v5_phdr_valid(phdr)) continue; - if ((phdr->p_flags & QCOM_MDT_TYPE_MASK) == QCOM_MDT_TYPE_HASH) - continue; + if (phdr->p_flags & QCOM_MDT_RELOCATABLE) + relocate = true; - if (!phdr->p_memsz) + if (phdr->p_paddr < min_addr) + min_addr = phdr->p_paddr; + + if (phdr->p_paddr + phdr->p_memsz > max_addr) + max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K); + } + + mpss_reloc = relocate ? min_addr : qproc->mpss_phys; + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = &phdrs[i]; + + if (!q6v5_phdr_valid(phdr)) continue; + offset = phdr->p_paddr - mpss_reloc; + if (offset < 0 || offset + phdr->p_memsz > qproc->mpss_size) { + dev_err(qproc->dev, "segment outside memory range\n"); + ret = -EINVAL; + goto release_firmware; + } + + ptr = qproc->mpss_region + offset; + + if (phdr->p_filesz) { + snprintf(seg_name, sizeof(seg_name), + MPSS_FIRMWARE_NAME ".b%02d", i); + ret = request_firmware(&seg_fw, seg_name, qproc->dev); + if (ret) { + dev_err(qproc->dev, "failed to load %s\n", seg_name); + goto release_firmware; + } + + memcpy(ptr, seg_fw->data, seg_fw->size); + + release_firmware(seg_fw); + } + + if (phdr->p_memsz > phdr->p_filesz) { + memset(ptr + phdr->p_filesz, 0, + phdr->p_memsz - phdr->p_filesz); + } + size = readl(qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); if (!size) { - writel(boot_addr, qproc->rmb_base + RMB_PMI_CODE_START_REG); + writel(mpss_reloc, qproc->rmb_base + RMB_PMI_CODE_START_REG); writel(RMB_CMD_LOAD_READY, qproc->rmb_base + RMB_MBA_COMMAND_REG); } @@ -517,44 +590,6 @@ static int q6v5_mpss_validate(struct q6v5 *qproc, const struct firmware *fw) else if (ret < 0) dev_err(qproc->dev, "MPSS authentication failed: %d\n", ret); - return ret < 0 ? ret : 0; -} - -static int q6v5_mpss_load(struct q6v5 *qproc) -{ - const struct firmware *fw; - phys_addr_t fw_addr; - bool relocate; - int ret; - - ret = request_firmware(&fw, MPSS_FIRMWARE_NAME, qproc->dev); - if (ret < 0) { - dev_err(qproc->dev, "unable to load " MPSS_FIRMWARE_NAME "\n"); - return ret; - } - - ret = qcom_mdt_parse(fw, &fw_addr, NULL, &relocate); - if (ret) { - dev_err(qproc->dev, "failed to parse mdt header\n"); - goto release_firmware; - } - - if (relocate) - qproc->mpss_reloc = fw_addr; - - /* Initialize the RMB validator */ - writel(0, qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG); - - ret = q6v5_mpss_init_image(qproc, fw); - if (ret) - goto release_firmware; - - ret = qcom_mdt_load(qproc->rproc, fw, MPSS_FIRMWARE_NAME); - if (ret) - goto release_firmware; - - ret = q6v5_mpss_validate(qproc, fw); - release_firmware: release_firmware(fw);