From patchwork Mon Jun 4 20:30:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Andersson X-Patchwork-Id: 137663 Delivered-To: patch@linaro.org Received: by 2002:a2e:970d:0:0:0:0:0 with SMTP id r13-v6csp100140lji; Mon, 4 Jun 2018 13:31:33 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLW4OLjSS6zz54OTrhGMRfxLCc8Xl5QpeikH+8OyqQulqkmqTzv/zxraQ2jaM6u3o2Z3u1X X-Received: by 2002:a17:902:b7c4:: with SMTP id v4-v6mr23543231plz.188.1528144293325; Mon, 04 Jun 2018 13:31:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528144293; cv=none; d=google.com; s=arc-20160816; b=iQe8U7lUrRV6+uR8zdMOSPSYnDcXNlBiBlAKU0alfxslyGWXVHbOyHAFCORqKr/84q 7jsI6Ue/m+1yQJMk4N5gz89MqFq79Gk4hPzpcKWi3Nr3InkcISYtRGjvybv+ucOz912Z gCwjXGsbrL8nHCY9J+gCIT+30ULyckFHhcbpReIowBvHtArSbj2/9pGOVSJ0urvO/HJP GHx8RX0ZVvfLvLselwOsxPSL4g7jTYYt1YXjAxDDSb2+znS65F80g5BUNm6f7ibNidTX a0X5YqhpK9eEiG6lAgouJxGJ7enHLWONZ9QzI1N7+8ZEyVhEcJhByTctcKq3TO/5eGBF wjqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=3aV1z6ctVDm8/cwV8AHVCWQoYhfwsPmr95jE9Y1HWi0=; b=trbMRrHi7f/A4Hz9Kb5nO8QU3+3Je7kH8aUki2rzndOE7SbPKiaFbi7LdmeqNruKBM URHfH8rqEJBScTgB4Fri9aDkw0v096eqTNB/Gi1RqxzIJ/JqBxkYb7+YmjYg6echYI01 PlOSNZ9EXpnNXoASyzO2mYgUxMRnqd09LAfEV8xuwo3MtOUDtdBI3P1HmfmD5IsHI1Di Ajl1oy471k/ZIcEoN7isq43ahmJhJLqSoMXlRo7uoolmm0zkxJiVIpspehl5q9nSG2Hu rJIksAtJksFI+IuANjUL2/hG6SMbGlexAX4XK54f6SRglXYpYuteeS9aRlooZvjsxKLu ABWA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kb1H64+i; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e3-v6si4818848pgn.523.2018.06.04.13.31.33; Mon, 04 Jun 2018 13:31:33 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kb1H64+i; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751526AbeFDUb2 (ORCPT + 30 others); Mon, 4 Jun 2018 16:31:28 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:43989 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751313AbeFDUaq (ORCPT ); Mon, 4 Jun 2018 16:30:46 -0400 Received: by mail-pl0-f68.google.com with SMTP id c41-v6so20376207plj.10 for ; Mon, 04 Jun 2018 13:30:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3aV1z6ctVDm8/cwV8AHVCWQoYhfwsPmr95jE9Y1HWi0=; b=kb1H64+izBWNBVfzjY3M/JvlnM37+tLi9enBBkq4UY3tZBsD0U4BKl8McpK/zEYWi+ bSGYSL+tKet8+q7TdT/zZzQcbBXUMXG3YcRVdMzuEq/UZbySUIj29swmyxPjLZKyOvdx w32WalYkCNfvpLP7xGoAYwguZ5OUDjQVMV4Ak= 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:in-reply-to :references; bh=3aV1z6ctVDm8/cwV8AHVCWQoYhfwsPmr95jE9Y1HWi0=; b=m5CpRRLKYH67vIKvPqPMf4OLJ4r7JoHqzXu1lvThrCjzRPIxPeNyr1IkS8yfAwfz6L t7EvTu7wmt50VHaLvE6bbvI2X+GqLQTfH7ZCs98Zdvt0OvWi5s0oHN2EU86TtO7y/Hoj oBG9+LuIO9nFONj5ePZf8YomcYVkOutz7U3+8J2huj/Km1XHSrxQAHo7APZsI8GA0l5f p/crTzf8Mu+RVe7CySCD/WPDDSKHRZOR6j1ETX8+YiZKuIOTD+DehPcYH8VKABM/c3lG oXsEjjSEDIIDNsCDhdxO3uaVOnxjRF/H/mAco9dvXmNblQxPLjXHA+8/vh3oOGIIKrVw Q2Ow== X-Gm-Message-State: ALKqPwf7+zvWahe6UD0S6KYU3xlaYzB1lSh6HeiHhE6nRf8sZbLjlOcx 46B8d9L2M+qMl7k1hjHK5UDfTWTJL1o= X-Received: by 2002:a17:902:aa95:: with SMTP id d21-v6mr22959924plr.73.1528144245425; Mon, 04 Jun 2018 13:30:45 -0700 (PDT) Received: from localhost.localdomain (104-188-17-28.lightspeed.sndgca.sbcglobal.net. [104.188.17.28]) by smtp.gmail.com with ESMTPSA id u68-v6sm83058641pfu.32.2018.06.04.13.30.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Jun 2018 13:30:44 -0700 (PDT) From: Bjorn Andersson To: Ohad Ben-Cohen , Bjorn Andersson , Sricharan R , Sibi Sankar , Rohit kumar Cc: Andy Gross , linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org, linux-arm-msm@vger.kernel.org Subject: [PATCH 2/4] remoteproc: q6v5: Extract common resource handling Date: Mon, 4 Jun 2018 13:30:36 -0700 Message-Id: <20180604203038.14080-3-bjorn.andersson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180604203038.14080-1-bjorn.andersson@linaro.org> References: <20180604203038.14080-1-bjorn.andersson@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Shared between all Hexagon V5 based remoteprocs is the handling of the 5 interrupts and the SMP2P stop request, so break this out into a separate function in order to allow these drivers to be cleaned up. Reviewed-by: Rohit kumar Tested-by: Rohit kumar Signed-off-by: Bjorn Andersson --- Changes since RFC: - Corrected header comment - Corrected copy-pasted crash type in wdog_intr - Picked up Rohit's reviewed-by drivers/remoteproc/Kconfig | 5 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/qcom_q6v5.c | 243 +++++++++++++++++++++++++++++++++ drivers/remoteproc/qcom_q6v5.h | 46 +++++++ 4 files changed, 295 insertions(+) create mode 100644 drivers/remoteproc/qcom_q6v5.c create mode 100644 drivers/remoteproc/qcom_q6v5.h -- 2.17.0 diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index cd1c168fd188..63b79ea91a21 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -102,6 +102,11 @@ config QCOM_ADSP_PIL config QCOM_RPROC_COMMON tristate +config QCOM_Q6V5_COMMON + tristate + depends on ARCH_QCOM + depends on QCOM_SMEM + config QCOM_Q6V5_PIL tristate "Qualcomm Hexagon V5 Peripherial Image Loader" depends on OF && ARCH_QCOM diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 02627ede8d4a..5dd0249cf76a 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o obj-$(CONFIG_KEYSTONE_REMOTEPROC) += keystone_remoteproc.o obj-$(CONFIG_QCOM_ADSP_PIL) += qcom_adsp_pil.o obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o +obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o obj-$(CONFIG_QCOM_Q6V5_PIL) += qcom_q6v5_pil.o obj-$(CONFIG_QCOM_SYSMON) += qcom_sysmon.o obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss_pil.o diff --git a/drivers/remoteproc/qcom_q6v5.c b/drivers/remoteproc/qcom_q6v5.c new file mode 100644 index 000000000000..400cdf936f6b --- /dev/null +++ b/drivers/remoteproc/qcom_q6v5.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm Peripheral Image Loader for Q6V5 + * + * Copyright (C) 2016-2018 Linaro Ltd. + * Copyright (C) 2014 Sony Mobile Communications AB + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include "qcom_q6v5.h" + +/** + * qcom_q6v5_prepare() - reinitialize the qcom_q6v5 context before start + * @q6v5: reference to qcom_q6v5 context to be reinitialized + * + * Return: 0 on success, negative errno on failure + */ +int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5) +{ + reinit_completion(&q6v5->start_done); + reinit_completion(&q6v5->stop_done); + + q6v5->running = true; + q6v5->handover_issued = false; + + enable_irq(q6v5->handover_irq); + + return 0; +} + +/** + * qcom_q6v5_unprepare() - unprepare the qcom_q6v5 context after stop + * @q6v5: reference to qcom_q6v5 context to be unprepared + * + * Return: 0 on success, 1 if handover hasn't yet been called + */ +int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5) +{ + disable_irq(q6v5->handover_irq); + + return !q6v5->handover_issued; +} + +static irqreturn_t q6v5_wdog_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + size_t len; + char *msg; + + /* Sometimes the stop triggers a watchdog rather than a stop-ack */ + if (!q6v5->running) { + complete(&q6v5->stop_done); + return IRQ_HANDLED; + } + + msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, q6v5->crash_reason, &len); + if (!IS_ERR(msg) && len > 0 && msg[0]) + dev_err(q6v5->dev, "watchdog received: %s\n", msg); + else + dev_err(q6v5->dev, "watchdog without message\n"); + + rproc_report_crash(q6v5->rproc, RPROC_WATCHDOG); + + return IRQ_HANDLED; +} + +static irqreturn_t q6v5_fatal_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + size_t len; + char *msg; + + msg = qcom_smem_get(QCOM_SMEM_HOST_ANY, q6v5->crash_reason, &len); + if (!IS_ERR(msg) && len > 0 && msg[0]) + dev_err(q6v5->dev, "fatal error received: %s\n", msg); + else + dev_err(q6v5->dev, "fatal error without message\n"); + + rproc_report_crash(q6v5->rproc, RPROC_FATAL_ERROR); + + return IRQ_HANDLED; +} + +static irqreturn_t q6v5_ready_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + + complete(&q6v5->start_done); + + return IRQ_HANDLED; +} + +/** + * qcom_q6v5_wait_for_start() - wait for remote processor start signal + * @q6v5: reference to qcom_q6v5 context + * @timeout: timeout to wait for the event, in jiffies + * + * qcom_q6v5_unprepare() should not be called when this function fails. + * + * Return: 0 on success, -ETIMEDOUT on timeout + */ +int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout) +{ + int ret; + + ret = wait_for_completion_timeout(&q6v5->start_done, timeout); + if (!ret) + disable_irq(q6v5->handover_irq); + + return !ret ? -ETIMEDOUT : 0; +} + +static irqreturn_t q6v5_handover_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + + if (q6v5->handover) + q6v5->handover(q6v5); + + q6v5->handover_issued = true; + + return IRQ_HANDLED; +} + +static irqreturn_t q6v5_stop_interrupt(int irq, void *data) +{ + struct qcom_q6v5 *q6v5 = data; + + complete(&q6v5->stop_done); + + return IRQ_HANDLED; +} + +/** + * qcom_q6v5_request_stop() - request the remote processor to stop + * @q6v5: reference to qcom_q6v5 context + * + * Return: 0 on success, negative errno on failure + */ +int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5) +{ + int ret; + + q6v5->running = false; + + qcom_smem_state_update_bits(q6v5->state, + BIT(q6v5->stop_bit), BIT(q6v5->stop_bit)); + + ret = wait_for_completion_timeout(&q6v5->stop_done, 5 * HZ); + + qcom_smem_state_update_bits(q6v5->state, BIT(q6v5->stop_bit), 0); + + return ret == 0 ? -ETIMEDOUT : 0; +} + +/** + * qcom_q6v5_init() - initializer of the q6v5 common struct + * @q6v5: handle to be initialized + * @pdev: platform_device reference for acquiring resources + * @rproc: associated remoteproc instance + * @crash_reason: SMEM id for crash reason string, or 0 if none + * @handover: function to be called when proxy resources should be released + * + * Return: 0 on success, negative errno on failure + */ +int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, + struct rproc *rproc, int crash_reason, + void (*handover)(struct qcom_q6v5 *q6v5)) +{ + int ret; + + q6v5->rproc = rproc; + q6v5->dev = &pdev->dev; + q6v5->crash_reason = crash_reason; + q6v5->handover = handover; + + init_completion(&q6v5->start_done); + init_completion(&q6v5->stop_done); + + q6v5->wdog_irq = platform_get_irq_byname(pdev, "wdog"); + ret = devm_request_threaded_irq(&pdev->dev, q6v5->wdog_irq, + NULL, q6v5_wdog_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 wdog", q6v5); + if (ret) { + dev_err(&pdev->dev, "failed to acquire wdog IRQ\n"); + return ret; + } + + q6v5->fatal_irq = platform_get_irq_byname(pdev, "fatal"); + ret = devm_request_threaded_irq(&pdev->dev, q6v5->fatal_irq, + NULL, q6v5_fatal_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 fatal", q6v5); + if (ret) { + dev_err(&pdev->dev, "failed to acquire fatal IRQ\n"); + return ret; + } + + q6v5->ready_irq = platform_get_irq_byname(pdev, "ready"); + ret = devm_request_threaded_irq(&pdev->dev, q6v5->ready_irq, + NULL, q6v5_ready_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 ready", q6v5); + if (ret) { + dev_err(&pdev->dev, "failed to acquire ready IRQ\n"); + return ret; + } + + q6v5->handover_irq = platform_get_irq_byname(pdev, "handover"); + ret = devm_request_threaded_irq(&pdev->dev, q6v5->handover_irq, + NULL, q6v5_handover_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 handover", q6v5); + if (ret) { + dev_err(&pdev->dev, "failed to acquire handover IRQ\n"); + return ret; + } + disable_irq(q6v5->handover_irq); + + q6v5->stop_irq = platform_get_irq_byname(pdev, "stop-ack"); + ret = devm_request_threaded_irq(&pdev->dev, q6v5->stop_irq, + NULL, q6v5_stop_interrupt, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "q6v5 stop", q6v5); + if (ret) { + dev_err(&pdev->dev, "failed to acquire stop-ack IRQ\n"); + return ret; + } + + q6v5->state = qcom_smem_state_get(&pdev->dev, "stop", &q6v5->stop_bit); + if (IS_ERR(q6v5->state)) { + dev_err(&pdev->dev, "failed to acquire stop state\n"); + return PTR_ERR(q6v5->state); + } + + return 0; +} diff --git a/drivers/remoteproc/qcom_q6v5.h b/drivers/remoteproc/qcom_q6v5.h new file mode 100644 index 000000000000..7ac92c1e0f49 --- /dev/null +++ b/drivers/remoteproc/qcom_q6v5.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __QCOM_Q6V5_H__ +#define __QCOM_Q6V5_H__ + +#include +#include + +struct rproc; +struct qcom_smem_state; + +struct qcom_q6v5 { + struct device *dev; + struct rproc *rproc; + + struct qcom_smem_state *state; + unsigned stop_bit; + + int wdog_irq; + int fatal_irq; + int ready_irq; + int handover_irq; + int stop_irq; + + bool handover_issued; + + struct completion start_done; + struct completion stop_done; + + int crash_reason; + + bool running; + + void (*handover)(struct qcom_q6v5 *q6v5); +}; + +int qcom_q6v5_init(struct qcom_q6v5 *q6v5, struct platform_device *pdev, + struct rproc *rproc, int crash_reason, + void (*handover)(struct qcom_q6v5 *q6v5)); + +int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5); +int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5); +int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5); +int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout); + +#endif