From patchwork Wed Sep 4 06:16:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pi-Hsun Shih X-Patchwork-Id: 11129403 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4C31E1920 for ; Wed, 4 Sep 2019 06:17:17 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 29DAB23697 for ; Wed, 4 Sep 2019 06:17:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="HSlpjFV1"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="lo30L7q4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 29DAB23697 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=4J+dYzE+l1z/Nq9eOK9wJAuf77Tfw0wGtMrQfop8nTs=; b=HSlpjFV1S2CnOn 7MM0MoVkiuiNqMKPXcfMnKddI0uijdRdsB77if/GTwfNS4hp6TSO563xquSd0GP2w3VwzMd+A2DEM gfHGV9LAAt6u8pufXtt4OHb0YT34ejMFJJmpAjiGpctQiPnJ+Lnwkk+IalTE109ZLkApzX3mrNmPU FwYOBBfuHN1IEYFMF5YJc7uHtpru+veG+ixigcPjawe/AUKLMnujpW3zGLbU1xIovFsjy0P+46luW LgJdg1P2K1GDSFUsFB+KkM4Gm9nypFUOK3TFdgnNxHEDfgFdTTPW0hrvIizyLVPiyXpcDPBnx1fLk JfbJw5A05/IUPMNuY9lQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1i5ObU-0001RP-HQ; Wed, 04 Sep 2019 06:17:16 +0000 Received: from mail-pf1-x444.google.com ([2607:f8b0:4864:20::444]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1i5ObF-0001C0-JQ for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2019 06:17:03 +0000 Received: by mail-pf1-x444.google.com with SMTP id b13so5916507pfo.8 for ; Tue, 03 Sep 2019 23:17:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Uzakui8viTETwW9jPht4pssIBM6YeQuIbX1083r5IEs=; b=lo30L7q4OAnqKuFHx/jfFe5LMFGNxW3a60tixFPIGjRHQJRbQOF23IYNpzJcMjRTVq 2Apa9i5yXzA4Qs8/cbW70m3UX/jMB/vlNiJh6rFB5wqTmb8p7s/pr83xMkFqHyj+6BwT OMDumxpyjObtXBCv9eHgDI1Mf+fIj/s/UJ1Mc= 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:mime-version:content-transfer-encoding; bh=Uzakui8viTETwW9jPht4pssIBM6YeQuIbX1083r5IEs=; b=XJkqKl7HgfQQmQLh8DemgCxUWPrze69JBorj/VTxW6HX/gaKk6no+KnxmpVd95HSEP Q1VdE8JLcUj/gEt0QjSXeysuzghV4EavX25vDITJLlpINVyHinjZARS5PgD8XE7WG1Fy Kx40cyhqxCG0zgrcSqDJhw2ihqnyEmAq6kMWK8tyGpD8/WtsbTHkFbUx3SnQor5i42Ab oKl1Y6RZCIc5mGVJZIBrgttsdO0XO5n26SC96MJhALiU1lNSwR793y4s44kMbg1Gv322 nYt6sWEU9PQZuG5P8TXfzJgvEyjSleKepqMpqP+C3cF+06gizT+12wKyh1J363Lgifc/ tnIQ== X-Gm-Message-State: APjAAAVr4BnqRmnDBWR9s5eOj5aiaLxZ5AkmL+z+R7HOKW0vO60fYHFn dgFu0fUrThgNBogKnAwCCXjpZg== X-Google-Smtp-Source: APXvYqznpx34k/PFtlLfTr2KZA144YWdk/hb9j75wdV4FzNEiNNRVy0S6ME9y3Lxmj4G5Tve2FO2Vw== X-Received: by 2002:a65:640d:: with SMTP id a13mr33335797pgv.256.1567577821026; Tue, 03 Sep 2019 23:17:01 -0700 (PDT) Received: from pihsun-z840.tpe.corp.google.com ([2401:fa00:1:10:7889:7a43:f899:134c]) by smtp.googlemail.com with ESMTPSA id r2sm27248750pfq.60.2019.09.03.23.16.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Sep 2019 23:17:00 -0700 (PDT) From: Pi-Hsun Shih To: Subject: [PATCH v17 1/5] dt-bindings: Add a binding for Mediatek SCP Date: Wed, 4 Sep 2019 14:16:39 +0800 Message-Id: <20190904061649.69099-2-pihsun@chromium.org> X-Mailer: git-send-email 2.23.0.187.g17f5b7556c-goog In-Reply-To: <20190904061649.69099-1-pihsun@chromium.org> References: <20190904061649.69099-1-pihsun@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190903_231701_724672_A91158A7 X-CRM114-Status: GOOD ( 14.25 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:444 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ohad Ben-Cohen , Rob Herring , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , Erin Lo , "open list:REMOTE PROCESSOR REMOTEPROC SUBSYSTEM" , open list , Bjorn Andersson , Rob Herring , "moderated list:ARM/Mediatek SoC support" , Pi-Hsun Shih , Matthias Brugger , Mark Rutland , "moderated list:ARM/Mediatek SoC support" Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org From: Erin Lo Add a DT binding documentation of SCP for the MT8183 SoC from Mediatek. Signed-off-by: Erin Lo Signed-off-by: Pi-Hsun Shih Reviewed-by: Rob Herring --- Changes from v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6: - No change. Changes from v5: - Remove dependency on CONFIG_RPMSG_MTK_SCP. Changes from v4: - Add detail of more properties. - Document the usage of mtk,rpmsg-name in subnode from the new design. Changes from v3: - No change. Changes from v2: - No change. I realized that for this patch series, there's no need to add anything under the mt8183-scp node (neither the mt8183-rpmsg or the cros-ec-rpmsg) for them to work, since mt8183-rpmsg is added directly as a rproc_subdev by code, and cros-ec-rpmsg is dynamically created by SCP name service. Changes from v1: - No change. --- .../bindings/remoteproc/mtk,scp.txt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 Documentation/devicetree/bindings/remoteproc/mtk,scp.txt diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt new file mode 100644 index 000000000000..3ba668bab14b --- /dev/null +++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt @@ -0,0 +1,36 @@ +Mediatek SCP Bindings +---------------------------------------- + +This binding provides support for ARM Cortex M4 Co-processor found on some +Mediatek SoCs. + +Required properties: +- compatible Should be "mediatek,mt8183-scp" +- reg Should contain the address ranges for the two memory + regions, SRAM and CFG. +- reg-names Contains the corresponding names for the two memory + regions. These should be named "sram" & "cfg". +- clocks Clock for co-processor (See: ../clock/clock-bindings.txt) +- clock-names Contains the corresponding name for the clock. This + should be named "main". + +Subnodes +-------- + +Subnodes of the SCP represent rpmsg devices. The names of the devices are not +important. The properties of these nodes are defined by the individual bindings +for the rpmsg devices - but must contain the following property: + +- mtk,rpmsg-name Contains the name for the rpmsg device. Used to match + the subnode to rpmsg device announced by SCP. + +Example: + + scp: scp@10500000 { + compatible = "mediatek,mt8183-scp"; + reg = <0 0x10500000 0 0x80000>, + <0 0x105c0000 0 0x5000>; + reg-names = "sram", "cfg"; + clocks = <&infracfg CLK_INFRA_SCPSYS>; + clock-names = "main"; + }; From patchwork Wed Sep 4 06:16:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pi-Hsun Shih X-Patchwork-Id: 11129409 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3225214DE for ; Wed, 4 Sep 2019 06:17:54 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0C978205ED for ; Wed, 4 Sep 2019 06:17:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="US0gfqU9"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="QtJkgiWK" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0C978205ED Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=DeurEN9NHM453JgdcekSvpBABS5HopBQhtHhEFfsYVA=; b=US0gfqU9d2kilQ Zj9XYgQHZRpDz03K+/JRT+ysIa//0Z3tzus2PpLof/w+pDq2O/7l6xVhXAvqlshxo/5p4755eNcW3 1JVILJGVrdPdMERLmopGebvTb7FrV/wiNyu0F+emZ4gh2JvqsoaLc56cg0pMpAw9/f0HXrkuhDzkO Pa+/IU4MwdL/Mp2MsDOkHAwx6fKS5pDsq11n2Vgdc9d4dRWEtlEioULUwWF8P44Dz5/nKBPshvTjj /fL0ErJS/iLc3IhPF0xz9Ogcxfv/wuv7iZJHYIjXQEMLrwoGUCu6jFVt5IEaEqb1BVe2ZOhumBF/E 8Y90gfoCLXdkPp4hzXwg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1i5Oc5-00020Y-D8; Wed, 04 Sep 2019 06:17:53 +0000 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1i5ObK-0001HW-W4 for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2019 06:17:10 +0000 Received: by mail-pg1-x541.google.com with SMTP id n9so10654263pgc.1 for ; Tue, 03 Sep 2019 23:17:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cTtO7WThbik6FePKOv8TbD+Iks5NKg2EmYu/imIAsAI=; b=QtJkgiWKCXWXVOhay29a9VhWiAL4cziiU8tTRimIgaW0eWRfpPWXzOpzXtLszM8AaW axMT8iIbpYqVgxoRsdB+lw7v/5TwaOxmW+KKWeISa6eHTv9yZRaEkNAGQ3g2ji/DguCp r75qKxEJzYiQe0fBYuGppxpdpKy5K7Nack8ww= 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:mime-version:content-transfer-encoding; bh=cTtO7WThbik6FePKOv8TbD+Iks5NKg2EmYu/imIAsAI=; b=P9r4bALFas5NSEfdtcDBcs+oXGb9hAt01oivRvPtOqwOybklQ+Z7eWsyCc+8yzRM6T RL2FlCOSUaIHzS4rPCxM6IESsb9zMnn/HsJ0RclQsJAx0rizyJJFZjcANH+wQ2fiaQW0 r7GbF8ilItuDy4svXvlLVstGEApJqADWYCA/lQVydh1RF7T+eP9a+8zi/ImEf5Sjfjal j6q30MPZljPwRROrk/sYctUxWHpeMYnrNSsvCAPrtV7iL2V9UFg1/6wabzbe7i+VWQTs vaBjCG003zJrJHPVVg1OVUrUmQSThwWoq16eIMJwD+u9seCGkbvFaIAniOxz4NkORQa5 tV+w== X-Gm-Message-State: APjAAAVI6wCxZswZjPZ3zi4pk/7ffT6qv6yyEnC/obq5XsRom8b09Yzd GtI/+9cPqCY1s4dpnedZHUAHxg== X-Google-Smtp-Source: APXvYqyTfX3pm7HxnOZcjLTWUpktGQg7Ar9ARGT73l+Or4g5GJ1LHKEz2JOiGUO3G4LemlEcepHhWw== X-Received: by 2002:a63:d64f:: with SMTP id d15mr18364474pgj.345.1567577825903; Tue, 03 Sep 2019 23:17:05 -0700 (PDT) Received: from pihsun-z840.tpe.corp.google.com ([2401:fa00:1:10:7889:7a43:f899:134c]) by smtp.googlemail.com with ESMTPSA id r2sm27248750pfq.60.2019.09.03.23.17.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Sep 2019 23:17:05 -0700 (PDT) From: Pi-Hsun Shih To: Subject: [PATCH v17 2/5] remoteproc/mediatek: add SCP support for mt8183 Date: Wed, 4 Sep 2019 14:16:40 +0800 Message-Id: <20190904061649.69099-3-pihsun@chromium.org> X-Mailer: git-send-email 2.23.0.187.g17f5b7556c-goog In-Reply-To: <20190904061649.69099-1-pihsun@chromium.org> References: <20190904061649.69099-1-pihsun@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190903_231707_068367_FC16C55F X-CRM114-Status: GOOD ( 23.02 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:541 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ohad Ben-Cohen , Nicolas Boichat , Erin Lo , "open list:REMOTE PROCESSOR REMOTEPROC SUBSYSTEM" , open list , Bjorn Andersson , "moderated list:ARM/Mediatek SoC support" , Pi-Hsun Shih , Matthias Brugger , "moderated list:ARM/Mediatek SoC support" Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org From: Erin Lo Provide a basic driver to control Cortex M4 co-processor Signed-off-by: Erin Lo Signed-off-by: Nicolas Boichat Signed-off-by: Pi-Hsun Shih --- Changes from v16: - Change the desc_lock mutex to be a per-id lock. - Put the execution of handler inside the per-id lock, to prevent race between scp_ipi_unregister and handler being run. - Move the initialization of mutex to before scp_ipi_register. Changes from v15: - Fix a bug on incorrect usage of wait_event_timeout return value. Changes from v14: - No change. Changes from v13: - Move include/linux/platform_data/mtk_scp.h to include/linux/remoteproc/mtk_scp.h. - Add lock for access of scp->ipi_desc. - Lock the whole ipi_send function. - Move more setting of cache size from SCP firmware to kernel driver, to prevent problem while loading firmware onto DRAM. - Cleanup and remove unused branch in scp_da_to_va. - Minor fixes addressing comment. Changes from v12: - Initialize cache before firmware load, to avoid problem while loading large firmware. - Disable watchdog before stopping SCP, to avoid extra warning message. - Use strscpy instead of strncpy. Changes from v11: - No change. Changes from v10: - Add a clock reset before loading firmware. Changes from v9: - No change. Changes from v8: - Add a missing space. Changes from v7: - Moved the location of shared SCP buffer. - Fix clock enable/disable sequence. - Add more IPI ID that would be used. Changes from v6: - No change. Changes from v5: - Changed some space to tab. Changes from v4: - Rename most function from mtk_scp_* to scp_*. - Change the irq to threaded handler. - Load ELF file instead of plain binary file as firmware by default (Squashed patch 6 in v4 into this patch). Changes from v3: - Fix some issue found by checkpatch. - Make writes aligned in scp_ipi_send. Changes from v2: - Squash patch 3 from v2 (separate the ipi interface) into this patch. - Remove unused name argument from scp_ipi_register. - Add scp_ipi_unregister for proper cleanup. - Move IPI ids in sync with firmware. - Add mb() in proper place, and correctly clear the run->signaled. Changes from v1: - Extract functions and rename variables in mtk_scp.c. --- drivers/remoteproc/Kconfig | 9 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/mtk_common.h | 92 +++++ drivers/remoteproc/mtk_scp.c | 547 +++++++++++++++++++++++++++++ drivers/remoteproc/mtk_scp_ipi.c | 176 ++++++++++ include/linux/remoteproc/mtk_scp.h | 141 ++++++++ 6 files changed, 966 insertions(+) create mode 100644 drivers/remoteproc/mtk_common.h create mode 100644 drivers/remoteproc/mtk_scp.c create mode 100644 drivers/remoteproc/mtk_scp_ipi.c create mode 100644 include/linux/remoteproc/mtk_scp.h diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 28ed306982f7..ea71cad399f7 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -23,6 +23,15 @@ config IMX_REMOTEPROC It's safe to say N here. +config MTK_SCP + tristate "Mediatek SCP support" + depends on ARCH_MEDIATEK + help + Say y here to support Mediatek's System Companion Processor (SCP) via + the remote processor framework. + + It's safe to say N here. + config OMAP_REMOTEPROC tristate "OMAP remoteproc support" depends on ARCH_OMAP4 || SOC_OMAP5 diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 00f09e658cb3..e30a1b15fbac 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -10,6 +10,7 @@ remoteproc-y += remoteproc_sysfs.o remoteproc-y += remoteproc_virtio.o remoteproc-y += remoteproc_elf_loader.o obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o +obj-$(CONFIG_MTK_SCP) += mtk_scp.o mtk_scp_ipi.o obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o obj-$(CONFIG_WKUP_M3_RPROC) += wkup_m3_rproc.o obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h new file mode 100644 index 000000000000..622e9aebe9ab --- /dev/null +++ b/drivers/remoteproc/mtk_common.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef __RPROC_MTK_COMMON_H +#define __RPROC_MTK_COMMON_H + +#include +#include +#include +#include + +#define MT8183_SW_RSTN 0x0 +#define MT8183_SW_RSTN_BIT BIT(0) +#define MT8183_SCP_TO_HOST 0x1C +#define MT8183_SCP_IPC_INT_BIT BIT(0) +#define MT8183_SCP_WDT_INT_BIT BIT(8) +#define MT8183_HOST_TO_SCP 0x28 +#define MT8183_HOST_IPC_INT_BIT BIT(0) +#define MT8183_WDT_CFG 0x84 +#define MT8183_SCP_CLK_SW_SEL 0x4000 +#define MT8183_SCP_CLK_DIV_SEL 0x4024 +#define MT8183_SCP_SRAM_PDN 0x402C +#define MT8183_SCP_L1_SRAM_PD 0x4080 +#define MT8183_SCP_TCM_TAIL_SRAM_PD 0x4094 + +#define MT8183_SCP_CACHE_SEL(x) (0x14000 + (x) * 0x3000) +#define MT8183_SCP_CACHE_CON MT8183_SCP_CACHE_SEL(0) +#define MT8183_SCP_DCACHE_CON MT8183_SCP_CACHE_SEL(1) +#define MT8183_SCP_CACHESIZE_8KB BIT(8) +#define MT8183_SCP_CACHE_CON_WAYEN BIT(10) + +#define SCP_FW_VER_LEN 32 +#define SCP_SHARE_BUFFER_SIZE 288 + +struct scp_run { + u32 signaled; + s8 fw_ver[SCP_FW_VER_LEN]; + u32 dec_capability; + u32 enc_capability; + wait_queue_head_t wq; +}; + +struct scp_ipi_desc { + /* For protecting handler. */ + struct mutex lock; + scp_ipi_handler_t handler; + void *priv; +}; + +struct mtk_scp { + struct device *dev; + struct rproc *rproc; + struct clk *clk; + void __iomem *reg_base; + void __iomem *sram_base; + size_t sram_size; + + struct share_obj *recv_buf; + struct share_obj *send_buf; + struct scp_run run; + /* To prevent multiple ipi_send run concurrently. */ + struct mutex send_lock; + struct scp_ipi_desc ipi_desc[SCP_IPI_MAX]; + bool ipi_id_ack[SCP_IPI_MAX]; + wait_queue_head_t ack_wq; + + void __iomem *cpu_addr; + phys_addr_t phys_addr; + size_t dram_size; +}; + +/** + * struct share_obj - SRAM buffer shared with + * AP and SCP + * + * @id: IPI id + * @len: share buffer length + * @share_buf: share buffer data + */ +struct share_obj { + u32 id; + u32 len; + u8 share_buf[SCP_SHARE_BUFFER_SIZE]; +}; + +void scp_memcpy_aligned(void *dst, const void *src, unsigned int len); +void scp_ipi_lock(struct mtk_scp *scp, u32 id); +void scp_ipi_unlock(struct mtk_scp *scp, u32 id); + +#endif diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c new file mode 100644 index 000000000000..99e226f38ca4 --- /dev/null +++ b/drivers/remoteproc/mtk_scp.c @@ -0,0 +1,547 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2019 MediaTek Inc. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtk_common.h" +#include "remoteproc_internal.h" + +#define MAX_CODE_SIZE 0x500000 +#define SCP_FW_END 0x7C000 + +struct platform_device *scp_get_pdev(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *scp_node; + struct platform_device *scp_pdev; + + scp_node = of_parse_phandle(dev->of_node, "mediatek,scp", 0); + if (!scp_node) { + dev_err(dev, "can't get SCP node\n"); + return NULL; + } + + scp_pdev = of_find_device_by_node(scp_node); + if (WARN_ON(!scp_pdev)) { + dev_err(dev, "SCP pdev failed\n"); + of_node_put(scp_node); + return NULL; + } + + return scp_pdev; +} +EXPORT_SYMBOL_GPL(scp_get_pdev); + +static void scp_wdt_handler(struct mtk_scp *scp, u32 scp_to_host) +{ + dev_err(scp->dev, "SCP watchdog timeout! 0x%x", scp_to_host); + rproc_report_crash(scp->rproc, RPROC_WATCHDOG); +} + +static void scp_init_ipi_handler(void *data, unsigned int len, void *priv) +{ + struct mtk_scp *scp = (struct mtk_scp *)priv; + struct scp_run *run = (struct scp_run *)data; + + scp->run.signaled = run->signaled; + strscpy(scp->run.fw_ver, run->fw_ver, SCP_FW_VER_LEN); + scp->run.dec_capability = run->dec_capability; + scp->run.enc_capability = run->enc_capability; + wake_up_interruptible(&scp->run.wq); +} + +static void scp_ipi_handler(struct mtk_scp *scp) +{ + struct share_obj *rcv_obj = scp->recv_buf; + struct scp_ipi_desc *ipi_desc = scp->ipi_desc; + u8 tmp_data[SCP_SHARE_BUFFER_SIZE]; + scp_ipi_handler_t handler; + u32 id = rcv_obj->id; + + if (rcv_obj->len > SCP_SHARE_BUFFER_SIZE) { + dev_err(scp->dev, "ipi message too long (len %d, max %d)", + rcv_obj->len, SCP_SHARE_BUFFER_SIZE); + return; + } + if (id >= SCP_IPI_MAX) { + dev_err(scp->dev, "No such ipi id = %d\n", id); + return; + } + + scp_ipi_lock(scp, id); + handler = ipi_desc[id].handler; + if (!handler) { + dev_err(scp->dev, "No such ipi id = %d\n", id); + scp_ipi_unlock(scp, id); + return; + } + + memcpy_fromio(tmp_data, &rcv_obj->share_buf, rcv_obj->len); + handler(tmp_data, rcv_obj->len, ipi_desc[id].priv); + scp_ipi_unlock(scp, id); + + scp->ipi_id_ack[id] = true; + wake_up(&scp->ack_wq); +} + +static int scp_ipi_init(struct mtk_scp *scp) +{ + size_t send_offset = SCP_FW_END - sizeof(struct share_obj); + size_t recv_offset = send_offset - sizeof(struct share_obj); + + /* Disable SCP to host interrupt */ + writel(MT8183_SCP_IPC_INT_BIT, scp->reg_base + MT8183_SCP_TO_HOST); + + /* shared buffer initialization */ + scp->recv_buf = (__force struct share_obj *)(scp->sram_base + + recv_offset); + scp->send_buf = (__force struct share_obj *)(scp->sram_base + + send_offset); + memset_io(scp->recv_buf, 0, sizeof(scp->recv_buf)); + memset_io(scp->send_buf, 0, sizeof(scp->send_buf)); + + return 0; +} + +static void scp_reset_assert(const struct mtk_scp *scp) +{ + u32 val; + + val = readl(scp->reg_base + MT8183_SW_RSTN); + val &= ~MT8183_SW_RSTN_BIT; + writel(val, scp->reg_base + MT8183_SW_RSTN); +} + +static void scp_reset_deassert(const struct mtk_scp *scp) +{ + u32 val; + + val = readl(scp->reg_base + MT8183_SW_RSTN); + val |= MT8183_SW_RSTN_BIT; + writel(val, scp->reg_base + MT8183_SW_RSTN); +} + +static irqreturn_t scp_irq_handler(int irq, void *priv) +{ + struct mtk_scp *scp = priv; + u32 scp_to_host; + int ret; + + ret = clk_prepare_enable(scp->clk); + if (ret) { + dev_err(scp->dev, "failed to enable clocks\n"); + return IRQ_NONE; + } + + scp_to_host = readl(scp->reg_base + MT8183_SCP_TO_HOST); + if (scp_to_host & MT8183_SCP_IPC_INT_BIT) + scp_ipi_handler(scp); + else + scp_wdt_handler(scp, scp_to_host); + + /* + * Ensure that all writes to SRAM are committed before another + * interrupt. + */ + mb(); + /* SCP won't send another interrupt until we set SCP_TO_HOST to 0. */ + writel(MT8183_SCP_IPC_INT_BIT | MT8183_SCP_WDT_INT_BIT, + scp->reg_base + MT8183_SCP_TO_HOST); + clk_disable_unprepare(scp->clk); + + return IRQ_HANDLED; +} + +static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw) +{ + struct device *dev = &rproc->dev; + struct elf32_hdr *ehdr; + struct elf32_phdr *phdr; + int i, ret = 0; + const u8 *elf_data = fw->data; + + ehdr = (struct elf32_hdr *)elf_data; + phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff); + + /* go through the available ELF segments */ + for (i = 0; i < ehdr->e_phnum; i++, phdr++) { + u32 da = phdr->p_paddr; + u32 memsz = phdr->p_memsz; + u32 filesz = phdr->p_filesz; + u32 offset = phdr->p_offset; + void __iomem *ptr; + + if (phdr->p_type != PT_LOAD) + continue; + + dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n", + phdr->p_type, da, memsz, filesz); + + if (filesz > memsz) { + dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n", + filesz, memsz); + ret = -EINVAL; + break; + } + + if (offset + filesz > fw->size) { + dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n", + offset + filesz, fw->size); + ret = -EINVAL; + break; + } + + /* grab the kernel address for this device address */ + ptr = rproc_da_to_va(rproc, da, memsz); + if (!ptr) { + dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz); + ret = -EINVAL; + break; + } + + /* put the segment where the remote processor expects it */ + if (phdr->p_filesz) + scp_memcpy_aligned(ptr, elf_data + phdr->p_offset, + filesz); + } + + return ret; +} + +static int scp_load(struct rproc *rproc, const struct firmware *fw) +{ + const struct mtk_scp *scp = rproc->priv; + struct device *dev = scp->dev; + int ret; + + ret = clk_prepare_enable(scp->clk); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + return ret; + } + + /* Hold SCP in reset while loading FW. */ + scp_reset_assert(scp); + + /* Reset clocks before loading FW */ + writel(0x0, scp->reg_base + MT8183_SCP_CLK_SW_SEL); + writel(0x0, scp->reg_base + MT8183_SCP_CLK_DIV_SEL); + + /* Initialize TCM before loading FW. */ + writel(0x0, scp->reg_base + MT8183_SCP_L1_SRAM_PD); + writel(0x0, scp->reg_base + MT8183_SCP_TCM_TAIL_SRAM_PD); + + /* Turn on the power of SCP's SRAM before using it. */ + writel(0x0, scp->reg_base + MT8183_SCP_SRAM_PDN); + + /* + * Set I-cache and D-cache size before loading SCP FW. + * SCP SRAM logical address may change when cache size setting differs. + */ + writel(MT8183_SCP_CACHE_CON_WAYEN | MT8183_SCP_CACHESIZE_8KB, + scp->reg_base + MT8183_SCP_CACHE_CON); + writel(MT8183_SCP_CACHESIZE_8KB, scp->reg_base + MT8183_SCP_DCACHE_CON); + + ret = scp_elf_load_segments(rproc, fw); + clk_disable_unprepare(scp->clk); + + return ret; +} + +static int scp_start(struct rproc *rproc) +{ + struct mtk_scp *scp = (struct mtk_scp *)rproc->priv; + struct device *dev = scp->dev; + struct scp_run *run = &scp->run; + int ret; + + ret = clk_prepare_enable(scp->clk); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + return ret; + } + + run->signaled = false; + + scp_reset_deassert(scp); + + ret = wait_event_interruptible_timeout( + run->wq, + run->signaled, + msecs_to_jiffies(2000)); + + if (ret == 0) { + dev_err(dev, "wait SCP initialization timeout!\n"); + ret = -ETIME; + goto stop; + } + if (ret == -ERESTARTSYS) { + dev_err(dev, "wait SCP interrupted by a signal!\n"); + goto stop; + } + clk_disable_unprepare(scp->clk); + dev_info(dev, "SCP is ready. FW version %s\n", run->fw_ver); + + return 0; + +stop: + scp_reset_assert(scp); + clk_disable_unprepare(scp->clk); + return ret; +} + +static void *scp_da_to_va(struct rproc *rproc, u64 da, int len) +{ + struct mtk_scp *scp = (struct mtk_scp *)rproc->priv; + int offset; + + if (da < scp->sram_size) { + offset = da; + if (offset >= 0 && (offset + len) < scp->sram_size) + return scp->sram_base + offset; + } else { + offset = da - scp->phys_addr; + if (offset >= 0 && (offset + len) < scp->dram_size) + return scp->cpu_addr + offset; + } + + return NULL; +} + +static int scp_stop(struct rproc *rproc) +{ + struct mtk_scp *scp = (struct mtk_scp *)rproc->priv; + int ret; + + ret = clk_prepare_enable(scp->clk); + if (ret) { + dev_err(scp->dev, "failed to enable clocks\n"); + return ret; + } + + scp_reset_assert(scp); + /* Disable SCP watchdog */ + writel(0, scp->reg_base + MT8183_WDT_CFG); + clk_disable_unprepare(scp->clk); + + return 0; +} + +static const struct rproc_ops scp_ops = { + .start = scp_start, + .stop = scp_stop, + .load = scp_load, + .da_to_va = scp_da_to_va, +}; + +unsigned int scp_get_vdec_hw_capa(struct platform_device *pdev) +{ + struct mtk_scp *scp = platform_get_drvdata(pdev); + + return scp->run.dec_capability; +} +EXPORT_SYMBOL_GPL(scp_get_vdec_hw_capa); + +unsigned int scp_get_venc_hw_capa(struct platform_device *pdev) +{ + struct mtk_scp *scp = platform_get_drvdata(pdev); + + return scp->run.enc_capability; +} +EXPORT_SYMBOL_GPL(scp_get_venc_hw_capa); + +void *scp_mapping_dm_addr(struct platform_device *pdev, u32 mem_addr) +{ + struct mtk_scp *scp = platform_get_drvdata(pdev); + void *ptr; + + ptr = scp_da_to_va(scp->rproc, mem_addr, 0); + if (!ptr) + return ERR_PTR(-EINVAL); + + return ptr; +} +EXPORT_SYMBOL_GPL(scp_mapping_dm_addr); + +static int scp_map_memory_region(struct mtk_scp *scp) +{ + struct device_node *node; + struct resource r; + int ret; + + node = of_parse_phandle(scp->dev->of_node, "memory-region", 0); + if (!node) { + dev_err(scp->dev, "no memory-region specified\n"); + return -EINVAL; + } + + ret = of_address_to_resource(node, 0, &r); + if (ret) + return ret; + + scp->phys_addr = r.start; + scp->dram_size = resource_size(&r); + scp->cpu_addr = + devm_ioremap_wc(scp->dev, scp->phys_addr, scp->dram_size); + + if (!scp->cpu_addr) { + dev_err(scp->dev, "unable to map memory region: %pa+%zx\n", + &r.start, scp->dram_size); + return -EBUSY; + } + + return 0; +} + +static int scp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct mtk_scp *scp; + struct rproc *rproc; + struct resource *res; + char *fw_name = "scp.img"; + int ret, i; + + rproc = rproc_alloc(dev, + np->name, + &scp_ops, + fw_name, + sizeof(*scp)); + if (!rproc) { + dev_err(dev, "unable to allocate remoteproc\n"); + return -ENOMEM; + } + + scp = (struct mtk_scp *)rproc->priv; + scp->rproc = rproc; + scp->dev = dev; + platform_set_drvdata(pdev, scp); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram"); + scp->sram_base = devm_ioremap_resource(dev, res); + if (IS_ERR((__force void *)scp->sram_base)) { + dev_err(dev, "Failed to parse and map sram memory\n"); + ret = PTR_ERR((__force void *)scp->sram_base); + goto free_rproc; + } + scp->sram_size = resource_size(res); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg"); + scp->reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR((__force void *)scp->reg_base)) { + dev_err(dev, "Failed to parse and map cfg memory\n"); + ret = PTR_ERR((__force void *)scp->reg_base); + goto free_rproc; + } + + ret = scp_map_memory_region(scp); + if (ret) + goto free_rproc; + + scp->clk = devm_clk_get(dev, "main"); + if (IS_ERR(scp->clk)) { + dev_err(dev, "Failed to get clock\n"); + ret = PTR_ERR(scp->clk); + goto free_rproc; + } + + ret = clk_prepare_enable(scp->clk); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + goto free_rproc; + } + + mutex_init(&scp->send_lock); + for (i = 0; i < SCP_IPI_MAX; i++) + mutex_init(&scp->ipi_desc[i].lock); + + ret = scp_ipi_init(scp); + clk_disable_unprepare(scp->clk); + if (ret) { + dev_err(dev, "Failed to init ipi\n"); + goto free_rproc; + } + + /* register SCP initialization IPI */ + ret = scp_ipi_register(pdev, + SCP_IPI_INIT, + scp_init_ipi_handler, + scp); + if (ret) { + dev_err(dev, "Failed to register IPI_SCP_INIT\n"); + goto free_rproc; + } + + init_waitqueue_head(&scp->run.wq); + init_waitqueue_head(&scp->ack_wq); + + ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), NULL, + scp_irq_handler, IRQF_ONESHOT, + pdev->name, scp); + + if (ret) { + dev_err(dev, "failed to request irq\n"); + goto destroy_mutex; + } + + ret = rproc_add(rproc); + if (ret) + goto destroy_mutex; + + return ret; + +destroy_mutex: + for (i = 0; i < SCP_IPI_MAX; i++) + mutex_destroy(&scp->ipi_desc[i].lock); + mutex_destroy(&scp->send_lock); +free_rproc: + rproc_free(rproc); + + return ret; +} + +static int scp_remove(struct platform_device *pdev) +{ + struct mtk_scp *scp = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < SCP_IPI_MAX; i++) + mutex_destroy(&scp->ipi_desc[i].lock); + mutex_destroy(&scp->send_lock); + rproc_del(scp->rproc); + rproc_free(scp->rproc); + + return 0; +} + +static const struct of_device_id mtk_scp_of_match[] = { + { .compatible = "mediatek,mt8183-scp"}, + {}, +}; +MODULE_DEVICE_TABLE(of, mtk_scp_of_match); + +static struct platform_driver mtk_scp_driver = { + .probe = scp_probe, + .remove = scp_remove, + .driver = { + .name = "mtk-scp", + .of_match_table = of_match_ptr(mtk_scp_of_match), + }, +}; + +module_platform_driver(mtk_scp_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MediaTek SCP control driver"); diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_ipi.c new file mode 100644 index 000000000000..f26fad007bd6 --- /dev/null +++ b/drivers/remoteproc/mtk_scp_ipi.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2019 MediaTek Inc. + +#include +#include +#include +#include +#include +#include +#include + +#include "mtk_common.h" + +int scp_ipi_register(struct platform_device *pdev, + enum scp_ipi_id id, + scp_ipi_handler_t handler, + void *priv) +{ + struct mtk_scp *scp = platform_get_drvdata(pdev); + + if (!scp) { + dev_err(&pdev->dev, "scp device is not ready\n"); + return -EPROBE_DEFER; + } + + if (WARN_ON(id < 0) || WARN_ON(id >= SCP_IPI_MAX) || + WARN_ON(handler == NULL)) + return -EINVAL; + + scp_ipi_lock(scp, id); + scp->ipi_desc[id].handler = handler; + scp->ipi_desc[id].priv = priv; + scp_ipi_unlock(scp, id); + + return 0; +} +EXPORT_SYMBOL_GPL(scp_ipi_register); + +void scp_ipi_unregister(struct platform_device *pdev, enum scp_ipi_id id) +{ + struct mtk_scp *scp = platform_get_drvdata(pdev); + + if (!scp) + return; + + if (WARN_ON(id < 0) || WARN_ON(id >= SCP_IPI_MAX)) + return; + + scp_ipi_lock(scp, id); + scp->ipi_desc[id].handler = NULL; + scp->ipi_desc[id].priv = NULL; + scp_ipi_unlock(scp, id); +} +EXPORT_SYMBOL_GPL(scp_ipi_unregister); + +/* + * Copy src to dst, where dst is in SCP SRAM region. + * Since AP access of SCP SRAM don't support byte write, this always write a + * full word at a time, and may cause some extra bytes to be written at the + * beginning & ending of dst. + */ +void scp_memcpy_aligned(void *dst, const void *src, unsigned int len) +{ + void *ptr; + u32 val; + unsigned int i = 0; + + if (!IS_ALIGNED((unsigned long)dst, 4)) { + ptr = (void *)ALIGN_DOWN((unsigned long)dst, 4); + i = 4 - (dst - ptr); + val = readl_relaxed(ptr); + memcpy((u8 *)&val + (4 - i), src, i); + writel_relaxed(val, ptr); + } + + while (i + 4 <= len) { + val = *((u32 *)(src + i)); + writel_relaxed(val, dst + i); + i += 4; + } + if (i < len) { + val = readl_relaxed(dst + i); + memcpy(&val, src + i, len - i); + writel_relaxed(val, dst + i); + } +} +EXPORT_SYMBOL_GPL(scp_memcpy_aligned); + +void scp_ipi_lock(struct mtk_scp *scp, u32 id) +{ + if (WARN_ON(id >= SCP_IPI_MAX)) + return; + mutex_lock(&scp->ipi_desc[id].lock); +} +EXPORT_SYMBOL_GPL(scp_ipi_lock); + +void scp_ipi_unlock(struct mtk_scp *scp, u32 id) +{ + if (WARN_ON(id >= SCP_IPI_MAX)) + return; + mutex_unlock(&scp->ipi_desc[id].lock); +} +EXPORT_SYMBOL_GPL(scp_ipi_unlock); + +int scp_ipi_send(struct platform_device *pdev, + enum scp_ipi_id id, + void *buf, + unsigned int len, + unsigned int wait) +{ + struct mtk_scp *scp = platform_get_drvdata(pdev); + struct share_obj *send_obj = scp->send_buf; + unsigned long timeout; + int ret; + + if (WARN_ON(id <= SCP_IPI_INIT) || WARN_ON(id >= SCP_IPI_MAX) || + WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf)) + return -EINVAL; + + mutex_lock(&scp->send_lock); + + ret = clk_prepare_enable(scp->clk); + if (ret) { + dev_err(scp->dev, "failed to enable clock\n"); + goto unlock_mutex; + } + + /* Wait until SCP receives the last command */ + timeout = jiffies + msecs_to_jiffies(2000); + do { + if (time_after(jiffies, timeout)) { + dev_err(scp->dev, "%s: IPI timeout!\n", __func__); + ret = -ETIMEDOUT; + goto clock_disable; + } + } while (readl(scp->reg_base + MT8183_HOST_TO_SCP)); + + scp_memcpy_aligned(send_obj->share_buf, buf, len); + + send_obj->len = len; + send_obj->id = id; + + scp->ipi_id_ack[id] = false; + /* + * Ensure that all writes to SRAM are committed before sending the + * interrupt to SCP. + */ + mb(); + /* send the command to SCP */ + writel(MT8183_HOST_IPC_INT_BIT, scp->reg_base + MT8183_HOST_TO_SCP); + + if (wait) { + /* wait for SCP's ACK */ + timeout = msecs_to_jiffies(wait); + ret = wait_event_timeout(scp->ack_wq, + scp->ipi_id_ack[id], + timeout); + scp->ipi_id_ack[id] = false; + if (WARN(!ret, "scp ipi %d ack time out !", id)) + ret = -EIO; + else + ret = 0; + } + +clock_disable: + clk_disable_unprepare(scp->clk); +unlock_mutex: + mutex_unlock(&scp->send_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(scp_ipi_send); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MediaTek scp IPI interface"); diff --git a/include/linux/remoteproc/mtk_scp.h b/include/linux/remoteproc/mtk_scp.h new file mode 100644 index 000000000000..b80d8e3f7959 --- /dev/null +++ b/include/linux/remoteproc/mtk_scp.h @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 MediaTek Inc. + */ + +#ifndef _MTK_SCP_H +#define _MTK_SCP_H + +#include + +typedef void (*scp_ipi_handler_t) (void *data, + unsigned int len, + void *priv); + +/** + * enum ipi_id - the id of inter-processor interrupt + * + * @SCP_IPI_INIT: The interrupt from scp is to notfiy kernel + * SCP initialization completed. + * IPI_SCP_INIT is sent from SCP when firmware is + * loaded. AP doesn't need to send IPI_SCP_INIT + * command to SCP. + * For other IPI below, AP should send the request + * to SCP to trigger the interrupt. + * @SCP_IPI_MAX: The maximum IPI number + */ + +enum scp_ipi_id { + SCP_IPI_INIT = 0, + SCP_IPI_VDEC_H264, + SCP_IPI_VDEC_VP8, + SCP_IPI_VDEC_VP9, + SCP_IPI_VENC_H264, + SCP_IPI_VENC_VP8, + SCP_IPI_MDP_INIT, + SCP_IPI_MDP_DEINIT, + SCP_IPI_MDP_FRAME, + SCP_IPI_DIP, + SCP_IPI_ISP_CMD, + SCP_IPI_ISP_FRAME, + SCP_IPI_FD_CMD, + SCP_IPI_CROS_HOST_CMD, + SCP_IPI_MAX, +}; + +/** + * scp_ipi_register - register an ipi function + * + * @pdev: SCP platform device + * @id: IPI ID + * @handler: IPI handler + * @priv: private data for IPI handler + * + * Register an ipi function to receive ipi interrupt from SCP. + * + * Return: Return 0 if ipi registers successfully, otherwise it is failed. + */ +int scp_ipi_register(struct platform_device *pdev, + enum scp_ipi_id id, + scp_ipi_handler_t handler, + void *priv); + +/** + * scp_ipi_unregister - unregister an ipi function + * + * @pdev: SCP platform device + * @id: IPI ID + * + * Unregister an ipi function to receive ipi interrupt from SCP. + */ +void scp_ipi_unregister(struct platform_device *pdev, enum scp_ipi_id id); + +/** + * scp_ipi_send - send data from AP to scp. + * + * @pdev: SCP platform device + * @id: IPI ID + * @buf: the data buffer + * @len: the data buffer length + * @wait: 1: need ack + * + * This function is thread-safe. When this function returns, + * SCP has received the data and starts the processing. + * When the processing completes, IPI handler registered + * by scp_ipi_register will be called in interrupt context. + * + * Return: Return 0 if sending data successfully, otherwise it is failed. + **/ +int scp_ipi_send(struct platform_device *pdev, + enum scp_ipi_id id, + void *buf, + unsigned int len, + unsigned int wait); + +/** + * scp_get_pdev - get SCP's platform device + * + * @pdev: the platform device of the module requesting SCP platform + * device for using SCP API. + * + * Return: Return NULL if it is failed. + * otherwise it is SCP's platform device + **/ +struct platform_device *scp_get_pdev(struct platform_device *pdev); + +/** + * scp_get_vdec_hw_capa - get video decoder hardware capability + * + * @pdev: SCP platform device + * + * Return: video decoder hardware capability + **/ +unsigned int scp_get_vdec_hw_capa(struct platform_device *pdev); + +/** + * scp_get_venc_hw_capa - get video encoder hardware capability + * + * @pdev: SCP platform device + * + * Return: video encoder hardware capability + **/ +unsigned int scp_get_venc_hw_capa(struct platform_device *pdev); + +/** + * scp_mapping_dm_addr - Mapping SRAM/DRAM to kernel virtual address + * + * @pdev: SCP platform device + * @mem_addr: SCP views memory address + * + * Mapping the SCP's SRAM address / + * DMEM (Data Extended Memory) memory address / + * Working buffer memory address to + * kernel virtual address. + * + * Return: Return ERR_PTR(-EINVAL) if mapping failed, + * otherwise the mapped kernel virtual address + **/ +void *scp_mapping_dm_addr(struct platform_device *pdev, + u32 mem_addr); + +#endif /* _MTK_SCP_H */ From patchwork Wed Sep 4 06:16:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pi-Hsun Shih X-Patchwork-Id: 11129413 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A077E14DE for ; Wed, 4 Sep 2019 06:18:31 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7DD332339D for ; Wed, 4 Sep 2019 06:18:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="kv1HdpK4"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="n5cwh721" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7DD332339D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=GqHFJ7MeQgSopZe9VQs3cZnBDWaLRK/DK7EGUXwOPOg=; b=kv1HdpK4jl2CSW 7OtSws3y8wvwkJofYTYuoaqIRfW0x10QkSyUDHhAV36BlBBqs1zzgI4jzC6hsHUQ188Q4y+4K95Vv caZdPl5kW7MANX12t6aJgdf807Sxc8zSdaKqf8ifvLrUWIsOdSOPGtWSKbK2EtqrDt7E5NmNX70vg NCAHpcML9uHBkyPxv3gju8ciQJgSACZc/ZEWkEtZ7vKCvGcI/LXIHxtgDAK5WwGFXj2hi0EG2MjXS A5a748BbjDxPrU6S3e/t44Hu1XOlXJs2OujjDEc44MHjq5tlcHcm3yEMBHbeeA47Clv+LwXD3LWZe jdjNf/cwpTTqPs3W/NyA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1i5Ocg-0002O4-WA; Wed, 04 Sep 2019 06:18:31 +0000 Received: from mail-pf1-x442.google.com ([2607:f8b0:4864:20::442]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1i5ObN-0001K8-Gw for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2019 06:17:12 +0000 Received: by mail-pf1-x442.google.com with SMTP id y22so6917738pfr.3 for ; Tue, 03 Sep 2019 23:17:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zH6rxHe/RfCiNo3P8Z82MRVb/Q/brp4tjzWfoelyxTg=; b=n5cwh721WmaLCF3EeyuQvzlbKk2Iafmyfa6zFyaRBVl9QQJg5ddwQiIG/EcC8LTDgA SUFoEtCoszIjC0rtsT5fQIt+2A7mjUuLd0Y4kpOkv6XqkshKQBtCwyxkZ5GrCHEVKRNI C7Ge228S6TnJWZ9PQ/Xf2Php3gumhwDIfKcOU= 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:mime-version:content-transfer-encoding; bh=zH6rxHe/RfCiNo3P8Z82MRVb/Q/brp4tjzWfoelyxTg=; b=TioHBjGqo5XIA2TzTE2Adjg8YVGpxkOA3ae4rSQxAFD7fZ111J5XDAykNOVlX23iZG CcvCu9jSAupfw8PIAMq8iMft3YV+/rXM6k/cSCzbqCzINFRdeThSFO+6s52mkVN2oRb/ bzHiDlB6a3026Yx0RB8Bb0EgRE4OneZuFzu4iOADwPxERJEmsdKYd5pcHFNA0hzsbwpx 5VOrEEhqZ/l/j5HzbJXfku3dN7rtoMYYqztAABL6PTW4v8YghKXNZf1cqY6ux3K4b1jM se6oI/5kg7EzqGvS7F/s9gTlXpBgMQhwLOdTNKsRJwGQkxlfsD2/xMOyva/TSf//5zoT S0Sg== X-Gm-Message-State: APjAAAUQJkJTs0q/+Qzk2WGZmO7E0O9WFc6UL3OduW4jvNyUWUCh+23X lizJGh4IUqiKErlUjsDUUy0gmw== X-Google-Smtp-Source: APXvYqy4Jq7EJKf9+aoMML3pJWOrIMJyJCzetbHtudu7VZ2MSBaQ7nudz3TCLnKuIQGxhUBlRyaNVw== X-Received: by 2002:a63:7887:: with SMTP id t129mr33938120pgc.309.1567577828759; Tue, 03 Sep 2019 23:17:08 -0700 (PDT) Received: from pihsun-z840.tpe.corp.google.com ([2401:fa00:1:10:7889:7a43:f899:134c]) by smtp.googlemail.com with ESMTPSA id r2sm27248750pfq.60.2019.09.03.23.17.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Sep 2019 23:17:08 -0700 (PDT) From: Pi-Hsun Shih To: Subject: [PATCH v17 3/5] remoteproc: mt8183: add reserved memory manager API Date: Wed, 4 Sep 2019 14:16:41 +0800 Message-Id: <20190904061649.69099-4-pihsun@chromium.org> X-Mailer: git-send-email 2.23.0.187.g17f5b7556c-goog In-Reply-To: <20190904061649.69099-1-pihsun@chromium.org> References: <20190904061649.69099-1-pihsun@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190903_231709_789405_DB023459 X-CRM114-Status: GOOD ( 12.58 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:442 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ohad Ben-Cohen , Erin Lo , "open list:REMOTE PROCESSOR REMOTEPROC SUBSYSTEM" , open list , Bjorn Andersson , "moderated list:ARM/Mediatek SoC support" , Pi-Hsun Shih , Matthias Brugger , "moderated list:ARM/Mediatek SoC support" Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org From: Erin Lo Add memory table mapping API for other driver to lookup reserved physical and virtual memory Signed-off-by: Erin Lo Signed-off-by: Pi-Hsun Shih --- Changes from v16, v15: - No change. Changes from v14: - Fix a typo in variable name in DEBUG section. Changes from v13: - Add one more reserved region. - Rename scp_get_reserve_* to scp_get_reserved_*. - Minor fixes addressing comment. Changes from v12: - Reformat a line to fit 80 character width. Changes from v11: - No change. Changes from v10: - Fix some type mismatch warnings when printing debug messages. Changes from v9: - No change. Changes from v8: - Add more reserved regions for camera ISP. Changes from v7, v6, v5: - No change. Changes from v4: - New patch. --- drivers/remoteproc/mtk_scp.c | 145 +++++++++++++++++++++++++++++ include/linux/remoteproc/mtk_scp.h | 25 +++++ 2 files changed, 170 insertions(+) diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index 99e226f38ca4..ce4acffbb115 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -374,11 +374,142 @@ void *scp_mapping_dm_addr(struct platform_device *pdev, u32 mem_addr) } EXPORT_SYMBOL_GPL(scp_mapping_dm_addr); +#if SCP_RESERVED_MEM +static phys_addr_t scp_mem_base_phys; +static phys_addr_t scp_mem_base_virt; +static size_t scp_mem_size; + +static struct scp_reserve_mblock scp_reserve_mblock[] = { + { + .num = SCP_ISP_MEM_ID, + .start_phys = 0x0, + .start_virt = 0x0, + .size = 0x200000, /*2MB*/ + }, + { + .num = SCP_ISP_MEM2_ID, + .start_phys = 0x0, + .start_virt = 0x0, + .size = 0x800000, /*8MB*/ + }, + { + .num = SCP_MDP_MEM_ID, + .start_phys = 0x0, + .start_virt = 0x0, + .size = 0x600000, /*6MB*/ + }, + { + .num = SCP_DIP_MEM_ID, + .start_phys = 0x0, + .start_virt = 0x0, + .size = 0x900000, /*9MB*/ + }, + { + .num = SCP_FD_MEM_ID, + .start_phys = 0x0, + .start_virt = 0x0, + .size = 0x100000, /*1MB*/ + }, + { + .num = SCP_FD_MEM2_ID, + .start_phys = 0x0, + .start_virt = 0x0, + .size = 0x100000, /*1MB*/ + }, +}; + +static int scp_reserve_mem_init(struct mtk_scp *scp) +{ + enum scp_reserve_mem_id_t id; + phys_addr_t accumlate_memory_size = 0; + + scp_mem_base_phys = (phys_addr_t) (scp->phys_addr + MAX_CODE_SIZE); + scp_mem_size = scp->dram_size - MAX_CODE_SIZE; + + dev_info(scp->dev, + "phys:0x%llx - 0x%llx (0x%llx)\n", + (unsigned long long)scp_mem_base_phys, + (unsigned long long)(scp_mem_base_phys + scp_mem_size), + (unsigned long long)scp_mem_size); + accumlate_memory_size = 0; + for (id = 0; id < SCP_NUMS_MEM_ID; id++) { + scp_reserve_mblock[id].start_phys = + scp_mem_base_phys + accumlate_memory_size; + accumlate_memory_size += scp_reserve_mblock[id].size; + dev_info( + scp->dev, + "[reserve_mem:%d]: phys:0x%llx - 0x%llx (0x%llx)\n", id, + (unsigned long long)scp_reserve_mblock[id].start_phys, + (unsigned long long)(scp_reserve_mblock[id].start_phys + + scp_reserve_mblock[id].size), + (unsigned long long)scp_reserve_mblock[id].size); + } + return 0; +} + +static int scp_reserve_memory_ioremap(struct mtk_scp *scp) +{ + enum scp_reserve_mem_id_t id; + phys_addr_t accumlate_memory_size = 0; + + scp_mem_base_virt = (phys_addr_t)(size_t)ioremap_wc(scp_mem_base_phys, + scp_mem_size); + + dev_info(scp->dev, + "virt:0x%llx - 0x%llx (0x%llx)\n", + (unsigned long long)scp_mem_base_virt, + (unsigned long long)(scp_mem_base_virt + scp_mem_size), + (unsigned long long)scp_mem_size); + for (id = 0; id < SCP_NUMS_MEM_ID; id++) { + scp_reserve_mblock[id].start_virt = + scp_mem_base_virt + accumlate_memory_size; + accumlate_memory_size += scp_reserve_mblock[id].size; + } + /* the reserved memory should be larger then expected memory + * or scp_reserve_mblock does not match dts + */ + WARN_ON(accumlate_memory_size > scp_mem_size); + return 0; +} +phys_addr_t scp_get_reserved_mem_phys(enum scp_reserve_mem_id_t id) +{ + if (id >= SCP_NUMS_MEM_ID) { + pr_err("[SCP] no reserve memory for %d", id); + return 0; + } + return scp_reserve_mblock[id].start_phys; +} +EXPORT_SYMBOL_GPL(scp_get_reserved_mem_phys); + +phys_addr_t scp_get_reserved_mem_virt(enum scp_reserve_mem_id_t id) +{ + if (id >= SCP_NUMS_MEM_ID) { + pr_err("[SCP] no reserve memory for %d", id); + return 0; + } + return scp_reserve_mblock[id].start_virt; +} +EXPORT_SYMBOL_GPL(scp_get_reserved_mem_virt); + +size_t scp_get_reserved_mem_size(enum scp_reserve_mem_id_t id) +{ + if (id >= SCP_NUMS_MEM_ID) { + pr_err("[SCP] no reserve memory for %d", id); + return 0; + } + return scp_reserve_mblock[id].size; +} +EXPORT_SYMBOL_GPL(scp_get_reserved_mem_size); +#endif + static int scp_map_memory_region(struct mtk_scp *scp) { struct device_node *node; struct resource r; int ret; +#ifdef DEBUG + enum scp_reserve_mem_id_t id; +#endif node = of_parse_phandle(scp->dev->of_node, "memory-region", 0); if (!node) { @@ -401,6 +532,20 @@ static int scp_map_memory_region(struct mtk_scp *scp) return -EBUSY; } +#if SCP_RESERVED_MEM + scp_reserve_mem_init(scp); + scp_reserve_memory_ioremap(scp); +#ifdef DEBUG + for (id = 0; id < SCP_NUMS_MEM_ID; id++) { + dev_info(scp->dev, + "[mem_reserve-%d] phys:0x%llx,virt:0x%llx,size:0x%llx\n", + id, + scp_get_reserved_mem_phys(id), + scp_get_reserved_mem_virt(id), + scp_get_reserved_mem_size(id)); + } +#endif +#endif return 0; } diff --git a/include/linux/remoteproc/mtk_scp.h b/include/linux/remoteproc/mtk_scp.h index b80d8e3f7959..707556f6b899 100644 --- a/include/linux/remoteproc/mtk_scp.h +++ b/include/linux/remoteproc/mtk_scp.h @@ -138,4 +138,29 @@ unsigned int scp_get_venc_hw_capa(struct platform_device *pdev); void *scp_mapping_dm_addr(struct platform_device *pdev, u32 mem_addr); +#define SCP_RESERVED_MEM (1) +#if SCP_RESERVED_MEM +/* scp reserve memory ID definition*/ +enum scp_reserve_mem_id_t { + SCP_ISP_MEM_ID, + SCP_ISP_MEM2_ID, + SCP_MDP_MEM_ID, + SCP_DIP_MEM_ID, + SCP_FD_MEM_ID, + SCP_FD_MEM2_ID, + SCP_NUMS_MEM_ID, +}; + +struct scp_reserve_mblock { + enum scp_reserve_mem_id_t num; + u64 start_phys; + u64 start_virt; + u64 size; +}; + +extern phys_addr_t scp_get_reserved_mem_phys(enum scp_reserve_mem_id_t id); +extern phys_addr_t scp_get_reserved_mem_virt(enum scp_reserve_mem_id_t id); +extern size_t scp_get_reserved_mem_size(enum scp_reserve_mem_id_t id); +#endif + #endif /* _MTK_SCP_H */ From patchwork Wed Sep 4 06:16:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pi-Hsun Shih X-Patchwork-Id: 11129417 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7DA3714DE for ; Wed, 4 Sep 2019 06:19:56 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 57D562339D for ; Wed, 4 Sep 2019 06:19:56 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="RKFEMgRB"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="IjbNu1LW" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 57D562339D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=N3dq7IU7XhPyaKgmrScNpuYMYzSMlWn1eDuLXlpTYLA=; b=RKFEMgRBmgq5Gp 3fzwm2YFIXDEh6yiqHyrWmMRewmwqekeHxP57xePrThYWrRX0n6hqIlvZFwU4ypMCsqgcqo5j0W27 cByQbSzJlh2WFy5t6/jyeE6Knk4QT3HT5VdIFgXknnS1tghYti8r7lHWFjFtPFXRBbn3wUW+bS5Yh VJelWd5/Y3j/jL+y0UGG3ZimbnhwLMZqdg10eFyYsEjFJue41SfPUC+Q903fKn6sybOXgFCBjG+PI WMzfZeezAayM7tXL7aiGKJHy3GmxVU1hWILrCTUagSa9J6ltEk0XWsSh+cftA2cpH+oqksmrZWjYW Qf2vjX77WOgJ9122EMkg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1i5Oe2-0002mA-P9; Wed, 04 Sep 2019 06:19:55 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1i5ObS-0001OL-DZ for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2019 06:17:17 +0000 Received: by mail-pl1-x644.google.com with SMTP id y1so9063764plp.9 for ; Tue, 03 Sep 2019 23:17:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DiEdwT/DZTgHFY5UStGKiqT3gKBdHh6DxEaUf5rzHKU=; b=IjbNu1LWTllQuedkn+5IvsEDZyTsKp/kOPW+dG6MCLxXDwsst8oC1lbDKPU8GqXwkK GdD+ro+PUbi0bZrhKVlacRx7/+nEGMiwkPniWcAQVz5Go9fzeqG1XS42C289h4O5mvy6 TKKjxMdsdZo0jVm4w0Mo84/G8YHpkSmdglV4g= 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:mime-version:content-transfer-encoding; bh=DiEdwT/DZTgHFY5UStGKiqT3gKBdHh6DxEaUf5rzHKU=; b=KqOOjZdjYjUzXVLS98CU/afoLV+hwK/3SUqIT91lbaD/sn/8lY0xRMTd2DMO0jZp52 42bI4YN4nRdcrniiBDdNysjMRWg6i68VwMGdOEeoDRU3SAugWerFyMxOLs2N3lV14rVS R75ii26I/4e+1a27Dhzp4mlgEFX2Wcsf2fiEW2EdCP6a5cb/iWOv1FbUtzMqAZ7lUgma s1Au69JniQ/9095bd6IQhpR6sf7fy4ceLuslJO5SBXTll4xS6RhpyKFYzS7NeNiriGWw au5hOgFxPpDT75Dfam83ZAVZo+rJcNSmfVCqyFD/WBW4C6DzoaLvXjvR0SXO3Z3RIq7U t5/w== X-Gm-Message-State: APjAAAV6MuoJpXibJM1jDHlwwaOBSd3XZZtE2I3cvd2+ployTSCLYz0H pDcrsTzXwCCQuOk51PyGilmwfA== X-Google-Smtp-Source: APXvYqxuWEytr1a+eYj4IH8Av626yc2hCC0jDrVYZJ3ZJQh10dvBen9kC2Q2Sq91cvZ/+NXWoX6Azw== X-Received: by 2002:a17:902:6906:: with SMTP id j6mr3054713plk.162.1567577833227; Tue, 03 Sep 2019 23:17:13 -0700 (PDT) Received: from pihsun-z840.tpe.corp.google.com ([2401:fa00:1:10:7889:7a43:f899:134c]) by smtp.googlemail.com with ESMTPSA id r2sm27248750pfq.60.2019.09.03.23.17.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Sep 2019 23:17:12 -0700 (PDT) From: Pi-Hsun Shih To: Subject: [PATCH v17 4/5] rpmsg: add rpmsg support for mt8183 SCP. Date: Wed, 4 Sep 2019 14:16:42 +0800 Message-Id: <20190904061649.69099-5-pihsun@chromium.org> X-Mailer: git-send-email 2.23.0.187.g17f5b7556c-goog In-Reply-To: <20190904061649.69099-1-pihsun@chromium.org> References: <20190904061649.69099-1-pihsun@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190903_231714_674561_988486D0 X-CRM114-Status: GOOD ( 27.94 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ohad Ben-Cohen , "open list:REMOTE PROCESSOR REMOTEPROC SUBSYSTEM" , open list , Bjorn Andersson , "moderated list:ARM/Mediatek SoC support" , Pi-Hsun Shih , Matthias Brugger , "moderated list:ARM/Mediatek SoC support" Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org Add a simple rpmsg support for mt8183 SCP, that use IPI / IPC directly. Signed-off-by: Pi-Hsun Shih --- Changes from v16: - Change year on another Copyright header to 2019. Changes from v15: - No change. Changes from v14: - Change year on Copyright header to 2019. Changes from v13: - No change. Changes from v12: - Use strscpy instead of strncpy. Changes from v11: - Fix a bug that when rproc_boot fails, the ns_ept won't be properly destroyed, causing memory leak. - Add documentation for mtk_rpmsg_info. Changes from v10, v9, v8, v7: - No change. Changes from v6: - Decouple mtk_rpmsg from mtk_scp by putting all necessary informations (name service IPI id, register/unregister/send functions) into a struct, and pass it to the mtk_rpmsg_create_rproc_subdev function. Changes from v5: - CONFIG_MTK_SCP now selects CONFIG_RPMSG_MTK_SCP, and the dummy implementation for mtk_rpmsg_{create,destroy}_rproc_subdev when CONFIG_RPMSG_MTK_SCP is not defined is removed. Changes from v4: - Match and fill the device tree node to the created rpmsg subdevice, so the rpmsg subdevice can utilize the properties and subnodes on device tree (This is similar to what drivers/rpmsg/qcom_smd.c does). Changes from v3: - Change from unprepare to stop, to stop the rpmsg driver before the rproc is stopped, avoiding problem that some rpmsg would fail after rproc is stopped. - Add missing spin_lock_init, and use destroy_ept instead of kref_put. Changes from v2: - Unregiser IPI handler on unprepare. - Lock the channel list on operations. - Move SCP_IPI_NS_SERVICE to 0xFF. Changes from v1: - Do cleanup properly in mtk_rpmsg.c, which also removes the problem of short-lived work items. - Fix several issues checkpatch found. --- drivers/remoteproc/Kconfig | 1 + drivers/remoteproc/mtk_common.h | 2 + drivers/remoteproc/mtk_scp.c | 38 ++- drivers/remoteproc/mtk_scp_ipi.c | 1 + drivers/rpmsg/Kconfig | 9 + drivers/rpmsg/Makefile | 1 + drivers/rpmsg/mtk_rpmsg.c | 414 +++++++++++++++++++++++++++++ include/linux/remoteproc/mtk_scp.h | 4 +- include/linux/rpmsg/mtk_rpmsg.h | 38 +++ 9 files changed, 503 insertions(+), 5 deletions(-) create mode 100644 drivers/rpmsg/mtk_rpmsg.c create mode 100644 include/linux/rpmsg/mtk_rpmsg.h diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index ea71cad399f7..cff3a9fa817b 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -26,6 +26,7 @@ config IMX_REMOTEPROC config MTK_SCP tristate "Mediatek SCP support" depends on ARCH_MEDIATEK + select RPMSG_MTK_SCP help Say y here to support Mediatek's System Companion Processor (SCP) via the remote processor framework. diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h index 622e9aebe9ab..40fa890e6d60 100644 --- a/drivers/remoteproc/mtk_common.h +++ b/drivers/remoteproc/mtk_common.h @@ -69,6 +69,8 @@ struct mtk_scp { void __iomem *cpu_addr; phys_addr_t phys_addr; size_t dram_size; + + struct rproc_subdev *rpmsg_subdev; }; /** diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c index ce4acffbb115..92657acc5e70 100644 --- a/drivers/remoteproc/mtk_scp.c +++ b/drivers/remoteproc/mtk_scp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "mtk_common.h" #include "remoteproc_internal.h" @@ -549,6 +550,31 @@ static int scp_map_memory_region(struct mtk_scp *scp) return 0; } +static struct mtk_rpmsg_info mtk_scp_rpmsg_info = { + .send_ipi = scp_ipi_send, + .register_ipi = scp_ipi_register, + .unregister_ipi = scp_ipi_unregister, + .ns_ipi_id = SCP_IPI_NS_SERVICE, +}; + +static void scp_add_rpmsg_subdev(struct mtk_scp *scp) +{ + scp->rpmsg_subdev = + mtk_rpmsg_create_rproc_subdev(to_platform_device(scp->dev), + &mtk_scp_rpmsg_info); + if (scp->rpmsg_subdev) + rproc_add_subdev(scp->rproc, scp->rpmsg_subdev); +} + +static void scp_remove_rpmsg_subdev(struct mtk_scp *scp) +{ + if (scp->rpmsg_subdev) { + rproc_remove_subdev(scp->rproc, scp->rpmsg_subdev); + mtk_rpmsg_destroy_rproc_subdev(scp->rpmsg_subdev); + scp->rpmsg_subdev = NULL; + } +} + static int scp_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -632,22 +658,25 @@ static int scp_probe(struct platform_device *pdev) init_waitqueue_head(&scp->run.wq); init_waitqueue_head(&scp->ack_wq); + scp_add_rpmsg_subdev(scp); + ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), NULL, scp_irq_handler, IRQF_ONESHOT, pdev->name, scp); if (ret) { dev_err(dev, "failed to request irq\n"); - goto destroy_mutex; + goto remove_subdev; } ret = rproc_add(rproc); if (ret) - goto destroy_mutex; + goto remove_subdev; - return ret; + return 0; -destroy_mutex: +remove_subdev: + scp_remove_rpmsg_subdev(scp); for (i = 0; i < SCP_IPI_MAX; i++) mutex_destroy(&scp->ipi_desc[i].lock); mutex_destroy(&scp->send_lock); @@ -662,6 +691,7 @@ static int scp_remove(struct platform_device *pdev) struct mtk_scp *scp = platform_get_drvdata(pdev); int i; + scp_remove_rpmsg_subdev(scp); for (i = 0; i < SCP_IPI_MAX; i++) mutex_destroy(&scp->ipi_desc[i].lock); mutex_destroy(&scp->send_lock); diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_ipi.c index f26fad007bd6..2c8cbf3c7eae 100644 --- a/drivers/remoteproc/mtk_scp_ipi.c +++ b/drivers/remoteproc/mtk_scp_ipi.c @@ -115,6 +115,7 @@ int scp_ipi_send(struct platform_device *pdev, int ret; if (WARN_ON(id <= SCP_IPI_INIT) || WARN_ON(id >= SCP_IPI_MAX) || + WARN_ON(id == SCP_IPI_NS_SERVICE) || WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf)) return -EINVAL; diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index d0322b41eca5..85e3cc075cb4 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -15,6 +15,15 @@ config RPMSG_CHAR in /dev. They make it possible for user-space programs to send and receive rpmsg packets. +config RPMSG_MTK_SCP + tristate "MediaTek SCP" + depends on MTK_SCP + select RPMSG + help + Say y here to enable support providing communication channels to + remote processors in MediaTek platforms. + This use IPI and IPC to communicate with remote processors. + config RPMSG_QCOM_GLINK_NATIVE tristate select RPMSG diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile index 9aa859502d27..ae92a7fb08f6 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_RPMSG) += rpmsg_core.o obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o +obj-$(CONFIG_RPMSG_MTK_SCP) += mtk_rpmsg.o obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o diff --git a/drivers/rpmsg/mtk_rpmsg.c b/drivers/rpmsg/mtk_rpmsg.c new file mode 100644 index 000000000000..ebe52c302734 --- /dev/null +++ b/drivers/rpmsg/mtk_rpmsg.c @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright 2019 Google LLC. + +#include +#include +#include +#include +#include +#include +#include + +#include "rpmsg_internal.h" + +struct mtk_rpmsg_rproc_subdev { + struct platform_device *pdev; + struct mtk_rpmsg_info *info; + struct rpmsg_endpoint *ns_ept; + struct rproc_subdev subdev; + + struct work_struct register_work; + struct list_head channels; + struct mutex channels_lock; +}; + +#define to_mtk_subdev(d) container_of(d, struct mtk_rpmsg_rproc_subdev, subdev) + +struct mtk_rpmsg_channel_info { + struct rpmsg_channel_info info; + bool registered; + struct list_head list; +}; + +/** + * struct rpmsg_ns_msg - dynamic name service announcement message + * @name: name of remote service that is published + * @addr: address of remote service that is published + * + * This message is sent across to publish a new service. When we receive these + * messages, an appropriate rpmsg channel (i.e device) is created. In turn, the + * ->probe() handler of the appropriate rpmsg driver will be invoked + * (if/as-soon-as one is registered). + */ +struct rpmsg_ns_msg { + char name[RPMSG_NAME_SIZE]; + u32 addr; +} __packed; + +struct mtk_rpmsg_device { + struct rpmsg_device rpdev; + struct mtk_rpmsg_rproc_subdev *mtk_subdev; +}; + +struct mtk_rpmsg_endpoint { + struct rpmsg_endpoint ept; + struct mtk_rpmsg_rproc_subdev *mtk_subdev; +}; + +#define to_mtk_rpmsg_device(r) container_of(r, struct mtk_rpmsg_device, rpdev) +#define to_mtk_rpmsg_endpoint(r) container_of(r, struct mtk_rpmsg_endpoint, ept) + +static const struct rpmsg_endpoint_ops mtk_rpmsg_endpoint_ops; + +static void __ept_release(struct kref *kref) +{ + struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint, + refcount); + kfree(to_mtk_rpmsg_endpoint(ept)); +} + +static void mtk_rpmsg_ipi_handler(void *data, unsigned int len, void *priv) +{ + struct mtk_rpmsg_endpoint *mept = priv; + struct rpmsg_endpoint *ept = &mept->ept; + int ret; + + ret = (*ept->cb)(ept->rpdev, data, len, ept->priv, ept->addr); + if (ret) + dev_warn(&ept->rpdev->dev, "rpmsg handler return error = %d", + ret); +} + +static struct rpmsg_endpoint * +__rpmsg_create_ept(struct mtk_rpmsg_rproc_subdev *mtk_subdev, + struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv, + u32 id) +{ + struct mtk_rpmsg_endpoint *mept; + struct rpmsg_endpoint *ept; + struct platform_device *pdev = mtk_subdev->pdev; + int ret; + + mept = kzalloc(sizeof(*mept), GFP_KERNEL); + if (!mept) + return NULL; + mept->mtk_subdev = mtk_subdev; + + ept = &mept->ept; + kref_init(&ept->refcount); + + ept->rpdev = rpdev; + ept->cb = cb; + ept->priv = priv; + ept->ops = &mtk_rpmsg_endpoint_ops; + ept->addr = id; + + ret = mtk_subdev->info->register_ipi(pdev, id, mtk_rpmsg_ipi_handler, + mept); + if (ret) { + dev_err(&pdev->dev, "IPI register failed, id = %d", id); + kref_put(&ept->refcount, __ept_release); + return NULL; + } + + return ept; +} + +static struct rpmsg_endpoint * +mtk_rpmsg_create_ept(struct rpmsg_device *rpdev, rpmsg_rx_cb_t cb, void *priv, + struct rpmsg_channel_info chinfo) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev = + to_mtk_rpmsg_device(rpdev)->mtk_subdev; + + return __rpmsg_create_ept(mtk_subdev, rpdev, cb, priv, chinfo.src); +} + +static void mtk_rpmsg_destroy_ept(struct rpmsg_endpoint *ept) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev = + to_mtk_rpmsg_endpoint(ept)->mtk_subdev; + + mtk_subdev->info->unregister_ipi(mtk_subdev->pdev, ept->addr); + kref_put(&ept->refcount, __ept_release); +} + +static int mtk_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev = + to_mtk_rpmsg_endpoint(ept)->mtk_subdev; + + return mtk_subdev->info->send_ipi(mtk_subdev->pdev, ept->addr, data, + len, 0); +} + +static int mtk_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev = + to_mtk_rpmsg_endpoint(ept)->mtk_subdev; + + /* + * TODO: This currently is same as mtk_rpmsg_send, and wait until SCP + * received the last command. + */ + return mtk_subdev->info->send_ipi(mtk_subdev->pdev, ept->addr, data, + len, 0); +} + +static const struct rpmsg_endpoint_ops mtk_rpmsg_endpoint_ops = { + .destroy_ept = mtk_rpmsg_destroy_ept, + .send = mtk_rpmsg_send, + .trysend = mtk_rpmsg_trysend, +}; + +static void mtk_rpmsg_release_device(struct device *dev) +{ + struct rpmsg_device *rpdev = to_rpmsg_device(dev); + struct mtk_rpmsg_device *mdev = to_mtk_rpmsg_device(rpdev); + + kfree(mdev); +} + +static const struct rpmsg_device_ops mtk_rpmsg_device_ops = { + .create_ept = mtk_rpmsg_create_ept, +}; + +static struct device_node * +mtk_rpmsg_match_device_subnode(struct device_node *node, const char *channel) +{ + struct device_node *child; + const char *name; + int ret; + + for_each_available_child_of_node(node, child) { + ret = of_property_read_string(child, "mtk,rpmsg-name", &name); + if (ret) + continue; + + if (strcmp(name, channel) == 0) + return child; + } + + return NULL; +} + +static int mtk_rpmsg_register_device(struct mtk_rpmsg_rproc_subdev *mtk_subdev, + struct rpmsg_channel_info *info) +{ + struct rpmsg_device *rpdev; + struct mtk_rpmsg_device *mdev; + struct platform_device *pdev = mtk_subdev->pdev; + int ret; + + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mdev->mtk_subdev = mtk_subdev; + + rpdev = &mdev->rpdev; + rpdev->ops = &mtk_rpmsg_device_ops; + rpdev->src = info->src; + rpdev->dst = info->dst; + strscpy(rpdev->id.name, info->name, RPMSG_NAME_SIZE); + + rpdev->dev.of_node = + mtk_rpmsg_match_device_subnode(pdev->dev.of_node, info->name); + rpdev->dev.parent = &pdev->dev; + rpdev->dev.release = mtk_rpmsg_release_device; + + ret = rpmsg_register_device(rpdev); + if (ret) { + kfree(mdev); + return ret; + } + + return 0; +} + +static void mtk_register_device_work_function(struct work_struct *register_work) +{ + struct mtk_rpmsg_rproc_subdev *subdev = container_of( + register_work, struct mtk_rpmsg_rproc_subdev, register_work); + struct platform_device *pdev = subdev->pdev; + struct mtk_rpmsg_channel_info *info; + int ret; + + mutex_lock(&subdev->channels_lock); + list_for_each_entry(info, &subdev->channels, list) { + if (info->registered) + continue; + + ret = mtk_rpmsg_register_device(subdev, &info->info); + if (ret) { + dev_err(&pdev->dev, "Can't create rpmsg_device\n"); + continue; + } + + info->registered = true; + } + mutex_unlock(&subdev->channels_lock); +} + +static int mtk_rpmsg_create_device(struct mtk_rpmsg_rproc_subdev *mtk_subdev, + char *name, u32 addr) +{ + struct mtk_rpmsg_channel_info *info; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + strscpy(info->info.name, name, RPMSG_NAME_SIZE); + info->info.src = addr; + info->info.dst = RPMSG_ADDR_ANY; + mutex_lock(&mtk_subdev->channels_lock); + list_add(&info->list, &mtk_subdev->channels); + mutex_unlock(&mtk_subdev->channels_lock); + + schedule_work(&mtk_subdev->register_work); + return 0; +} + +static int mtk_rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len, + void *priv, u32 src) +{ + struct rpmsg_ns_msg *msg = data; + struct mtk_rpmsg_rproc_subdev *mtk_subdev = priv; + struct device *dev = &mtk_subdev->pdev->dev; + + int ret; + + if (len != sizeof(*msg)) { + dev_err(dev, "malformed ns msg (%d)\n", len); + return -EINVAL; + } + + /* + * the name service ept does _not_ belong to a real rpmsg channel, + * and is handled by the rpmsg bus itself. + * for sanity reasons, make sure a valid rpdev has _not_ sneaked + * in somehow. + */ + if (rpdev) { + dev_err(dev, "anomaly: ns ept has an rpdev handle\n"); + return -EINVAL; + } + + /* don't trust the remote processor for null terminating the name */ + msg->name[RPMSG_NAME_SIZE - 1] = '\0'; + + dev_info(dev, "creating channel %s addr 0x%x\n", msg->name, msg->addr); + + ret = mtk_rpmsg_create_device(mtk_subdev, msg->name, msg->addr); + if (ret) { + dev_err(dev, "create rpmsg device failed\n"); + return ret; + } + + return 0; +} + +int mtk_rpmsg_prepare(struct rproc_subdev *subdev) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev = to_mtk_subdev(subdev); + + /* a dedicated endpoint handles the name service msgs */ + if (mtk_subdev->info->ns_ipi_id >= 0) { + mtk_subdev->ns_ept = + __rpmsg_create_ept(mtk_subdev, NULL, mtk_rpmsg_ns_cb, + mtk_subdev, + mtk_subdev->info->ns_ipi_id); + if (!mtk_subdev->ns_ept) { + dev_err(&mtk_subdev->pdev->dev, + "failed to create name service endpoint\n"); + return -ENOMEM; + } + } + + return 0; +} + +void mtk_rpmsg_unprepare(struct rproc_subdev *subdev) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev = to_mtk_subdev(subdev); + + if (mtk_subdev->ns_ept) { + mtk_rpmsg_destroy_ept(mtk_subdev->ns_ept); + mtk_subdev->ns_ept = NULL; + } +} + +void mtk_rpmsg_stop(struct rproc_subdev *subdev, bool crashed) +{ + struct mtk_rpmsg_channel_info *info, *next; + struct mtk_rpmsg_rproc_subdev *mtk_subdev = to_mtk_subdev(subdev); + struct device *dev = &mtk_subdev->pdev->dev; + + /* + * Destroy the name service endpoint here, to avoid new channel being + * created after the rpmsg_unregister_device loop below. + */ + if (mtk_subdev->ns_ept) { + mtk_rpmsg_destroy_ept(mtk_subdev->ns_ept); + mtk_subdev->ns_ept = NULL; + } + + cancel_work_sync(&mtk_subdev->register_work); + + mutex_lock(&mtk_subdev->channels_lock); + list_for_each_entry(info, &mtk_subdev->channels, list) { + if (!info->registered) + continue; + if (rpmsg_unregister_device(dev, &info->info)) { + dev_warn( + dev, + "rpmsg_unregister_device failed for %s.%d.%d\n", + info->info.name, info->info.src, + info->info.dst); + } + } + + list_for_each_entry_safe(info, next, + &mtk_subdev->channels, list) { + list_del(&info->list); + kfree(info); + } + mutex_unlock(&mtk_subdev->channels_lock); +} + +struct rproc_subdev * +mtk_rpmsg_create_rproc_subdev(struct platform_device *pdev, + struct mtk_rpmsg_info *info) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev; + + mtk_subdev = kzalloc(sizeof(*mtk_subdev), GFP_KERNEL); + if (!mtk_subdev) + return NULL; + + mtk_subdev->pdev = pdev; + mtk_subdev->subdev.prepare = mtk_rpmsg_prepare; + mtk_subdev->subdev.stop = mtk_rpmsg_stop; + mtk_subdev->subdev.unprepare = mtk_rpmsg_unprepare; + mtk_subdev->info = info; + INIT_LIST_HEAD(&mtk_subdev->channels); + INIT_WORK(&mtk_subdev->register_work, + mtk_register_device_work_function); + mutex_init(&mtk_subdev->channels_lock); + + return &mtk_subdev->subdev; +} +EXPORT_SYMBOL_GPL(mtk_rpmsg_create_rproc_subdev); + +void mtk_rpmsg_destroy_rproc_subdev(struct rproc_subdev *subdev) +{ + struct mtk_rpmsg_rproc_subdev *mtk_subdev = to_mtk_subdev(subdev); + + kfree(mtk_subdev); +} +EXPORT_SYMBOL_GPL(mtk_rpmsg_destroy_rproc_subdev); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MediaTek scp rpmsg driver"); diff --git a/include/linux/remoteproc/mtk_scp.h b/include/linux/remoteproc/mtk_scp.h index 707556f6b899..67ae6674397b 100644 --- a/include/linux/remoteproc/mtk_scp.h +++ b/include/linux/remoteproc/mtk_scp.h @@ -40,9 +40,11 @@ enum scp_ipi_id { SCP_IPI_ISP_FRAME, SCP_IPI_FD_CMD, SCP_IPI_CROS_HOST_CMD, - SCP_IPI_MAX, + SCP_IPI_NS_SERVICE = 0xFF, + SCP_IPI_MAX = 0x100, }; + /** * scp_ipi_register - register an ipi function * diff --git a/include/linux/rpmsg/mtk_rpmsg.h b/include/linux/rpmsg/mtk_rpmsg.h new file mode 100644 index 000000000000..5aa2d84ac0e2 --- /dev/null +++ b/include/linux/rpmsg/mtk_rpmsg.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC. + */ + +#ifndef __LINUX_RPMSG_MTK_RPMSG_H +#define __LINUX_RPMSG_MTK_RPMSG_H + +#include +#include + +typedef void (*ipi_handler_t)(void *data, unsigned int len, void *priv); + +/* + * struct mtk_rpmsg_info - IPI functions tied to the rpmsg device. + * @register_ipi: register IPI handler for an IPI id. + * @unregister_ipi: unregister IPI handler for a registered IPI id. + * @send_ipi: send IPI to an IPI id. wait is the timeout (in msecs) to wait + * until response, or 0 if there's no timeout. + * @ns_ipi_id: the IPI id used for name service, or -1 if name service isn't + * supported. + */ +struct mtk_rpmsg_info { + int (*register_ipi)(struct platform_device *pdev, u32 id, + ipi_handler_t handler, void *priv); + void (*unregister_ipi)(struct platform_device *pdev, u32 id); + int (*send_ipi)(struct platform_device *pdev, u32 id, + void *buf, unsigned int len, unsigned int wait); + int ns_ipi_id; +}; + +struct rproc_subdev * +mtk_rpmsg_create_rproc_subdev(struct platform_device *pdev, + struct mtk_rpmsg_info *info); + +void mtk_rpmsg_destroy_rproc_subdev(struct rproc_subdev *subdev); + +#endif From patchwork Wed Sep 4 06:16:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pi-Hsun Shih X-Patchwork-Id: 11129419 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5076616B1 for ; Wed, 4 Sep 2019 06:20:06 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2D24C2339D for ; Wed, 4 Sep 2019 06:20:06 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="mZw0hRNI"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="hwQ0ejc7" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 2D24C2339D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=HmRi2ypbAima1AmjqfumiTEKpxQIE3gff65pVtUhDx0=; b=mZw0hRNIsPZr3v xIHzeiwIbr5ig6W6qw0Dj3ebt3nOxAPCJ6xJxGNyhh82OHWKfqHZVqvswIsSRaACBn9N7CcfiyJAO OCX3kLYZyuO0tpPggzxlkkQQUnlCT2dttP57s9tslANUCRIooI3qLPF+6hK54RgwabX0Er2b7JvD/ VKzAHxiiiD0Tfl1OCgY5uSyiL1PBrsfP5xDE7ibQw4cmUX9x6nNP2i1IfDYDEOugGHr6F8f9ouxYp 2TQ7dVJIKACZCY+525DhkoRKY+9n7WZaARrgcJeLjIkcF1wW/spi6xlylgv7jpDLEkLVskniwqoMN kS2SKR+dTTvC7WA1Q3lA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1i5OeD-00038D-BS; Wed, 04 Sep 2019 06:20:05 +0000 Received: from mail-pl1-x642.google.com ([2607:f8b0:4864:20::642]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1i5ObU-0001RC-IW for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2019 06:17:18 +0000 Received: by mail-pl1-x642.google.com with SMTP id m9so9099265pls.8 for ; Tue, 03 Sep 2019 23:17:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=oal3IaO/tErsls7uIk50scCx56FqEWZJT9dcXkh2oYs=; b=hwQ0ejc7gawIBUqdMX1cbLVlApO4fA4Mriygvn96fnvODntwLTrFDhyto/By1coVfL rKsVdgKTo7+0OCayATD3gwspix/ktFDP/Ut/HGTin9J74PdE4wCQqx5wNFFQ7nrAeAZl cMYTk8cN20mzzMHGRVDsRphub4z4ZeDAISZO0= 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:mime-version:content-transfer-encoding; bh=oal3IaO/tErsls7uIk50scCx56FqEWZJT9dcXkh2oYs=; b=n5/Im1I0XUyrjv6hD4niHlr3B5Zffnounzp923eXJCxBT+zTlW0hXhdbmQeBy1PGdy FMKIi9tq89D1atvWNQZBj0Naz2QP9iGVlyJUFGRRchiC5YgP3w8aPAqdhx/892xJvEOO lCY4N+uPrW2lBJd7D60jnzhjuD73YczvoEo2oZMhmOCfumQprkJMdgBv+arFWYbdLvIB bZ1m3BFJ4BMOlDafFL2nbxPWdevnL5i2p+z4ansChRRTyS2KYFS0fvv9f7YVXjxlqego H2+Pa/oxBsXzhq+xI0wKq5cJsPxAgdfTUlxPipXIf7l+TRq+6hPr9ixSRWZX+I7iKx6X M95Q== X-Gm-Message-State: APjAAAXQo4QCr6ezoT/NELvWAxNRZ2WZRZHI0DbhO37elYd41OnkZuWU +DOHClemg5ZTV2xxTKOSG3dryQ== X-Google-Smtp-Source: APXvYqxrOY+4WKbKVfDkYMJaSzR20/rot1ZjReA7xzONnTysPAGS6CaTgjER2YlWbqyDmzQvGoq6Pw== X-Received: by 2002:a17:902:e407:: with SMTP id ci7mr39693277plb.326.1567577835907; Tue, 03 Sep 2019 23:17:15 -0700 (PDT) Received: from pihsun-z840.tpe.corp.google.com ([2401:fa00:1:10:7889:7a43:f899:134c]) by smtp.googlemail.com with ESMTPSA id r2sm27248750pfq.60.2019.09.03.23.17.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Sep 2019 23:17:15 -0700 (PDT) From: Pi-Hsun Shih To: Subject: [PATCH v17 5/5] arm64: dts: mt8183: add scp node Date: Wed, 4 Sep 2019 14:16:43 +0800 Message-Id: <20190904061649.69099-6-pihsun@chromium.org> X-Mailer: git-send-email 2.23.0.187.g17f5b7556c-goog In-Reply-To: <20190904061649.69099-1-pihsun@chromium.org> References: <20190904061649.69099-1-pihsun@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190903_231716_738196_212A584E X-CRM114-Status: GOOD ( 10.72 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:642 listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 DKIMWL_WL_HIGH DKIMwl.org - Whitelisted High sender X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , Erin Lo , open list , Rob Herring , "moderated list:ARM/Mediatek SoC support" , Pi-Hsun Shih , Matthias Brugger , Eddie Huang , "moderated list:ARM/Mediatek SoC support" Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org From: Eddie Huang Add scp node to mt8183 and mt8183-evb Signed-off-by: Erin Lo Signed-off-by: Pi-Hsun Shih Signed-off-by: Eddie Huang --- Changes from v16, v15, v14: - No change. Changes from v13: - Change the size of the cfg register region. Changes from v12, v11, v10: - No change. Changes from v9: - Remove extra reserve-memory-vpu_share node. Changes from v8: - New patch. --- arch/arm64/boot/dts/mediatek/mt8183-evb.dts | 11 +++++++++++ arch/arm64/boot/dts/mediatek/mt8183.dtsi | 12 ++++++++++++ 2 files changed, 23 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts index 1fb195c683c3..ddb7a7ac9655 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8183-evb.dts @@ -24,6 +24,17 @@ chosen { stdout-path = "serial0:921600n8"; }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + scp_mem_reserved: scp_mem_region { + compatible = "shared-dma-pool"; + reg = <0 0x50000000 0 0x2900000>; + no-map; + }; + }; }; &auxadc { diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 97f84aa9fc6e..3dd1b76bbaf5 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -269,6 +269,18 @@ clock-names = "spi", "wrap"; }; + scp: scp@10500000 { + compatible = "mediatek,mt8183-scp"; + reg = <0 0x10500000 0 0x80000>, + <0 0x105c0000 0 0x19080>; + reg-names = "sram", "cfg"; + interrupts = ; + clocks = <&infracfg CLK_INFRA_SCPSYS>; + clock-names = "main"; + memory-region = <&scp_mem_reserved>; + status = "disabled"; + }; + auxadc: auxadc@11001000 { compatible = "mediatek,mt8183-auxadc", "mediatek,mt8173-auxadc";