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: 9546259 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8868B60425 for ; Tue, 31 Jan 2017 00:54:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 751C127FE4 for ; Tue, 31 Jan 2017 00:54:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 667B8282F5; Tue, 31 Jan 2017 00:54:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.7 required=2.0 tests=BAYES_00, DATE_IN_PAST_06_12, DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A0AB227FE4 for ; Tue, 31 Jan 2017 00:54:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753755AbdAaAyi (ORCPT ); Mon, 30 Jan 2017 19:54:38 -0500 Received: from mail-pf0-f174.google.com ([209.85.192.174]:36028 "EHLO mail-pf0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753682AbdAaAyh (ORCPT ); Mon, 30 Jan 2017 19:54:37 -0500 Received: by mail-pf0-f174.google.com with SMTP id 189so96289296pfu.3 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=TL+c6cEWg4TyI2yYST3po2xXK7cWZ3pgubIb3bxgwwGGBKskl0/eC2Z0SOxqrSwsQz IW4bpenxk78vlSBI8z6PuICCPSMRZs2lBARBCfj2HRkT1cWsm9BOt2V8hO2N7+UPGokt ityRb/KUDkur61tb/mVnlZXTzWpY4ZC8xELNSkW1/8wjIczPK9O1w7MotKEDCWAFU3qp A0KcEmwD8rMUrxjKnkS9KY55Pg7fwR9BUNh6BgLJsVxD2lLHm6+PGFS14cRJxIAp9RcX MHOVamLfRTGrQtV+/kxR55XAicV8pVmPmBgxMHczOBmz7VlCEXmV/Frv/2/YLD9J1ai7 fxlQ== X-Gm-Message-State: AIkVDXJRnRyM2zNIWB7fLWCF+2BS+EcvLXs4KzU6LAXiuU83A2Zro5O9A0rm//csXykWfBps 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-remoteproc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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(-) 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);