From patchwork Fri Dec 11 14:29:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Grzegorz Jaszczyk X-Patchwork-Id: 341969 Delivered-To: patch@linaro.org Received: by 2002:a02:85a7:0:0:0:0:0 with SMTP id d36csp591598jai; Fri, 11 Dec 2020 06:33:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJwmNUaT4CQW61ARciEig2Z1I7dgoUx87kZN+LrcFpkojUfOGlNKGLEV4Ce5RzSBUfsFm410 X-Received: by 2002:a17:907:11ca:: with SMTP id va10mr144540ejb.78.1607697207739; Fri, 11 Dec 2020 06:33:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1607697207; cv=none; d=google.com; s=arc-20160816; b=suSgqu1NVFpKMvfWptxQOwdFVu0TsU5sZJbTdGxm1pmpV4nINk8HL4rwmCv5ZVvAya k1LyJeetqKxjN9KwQtFIIuLg2Zbe9SFa0sdMwIDYyDziqSW5QX+AyEw3QGR2cOlWFRtS +JwuMl8Udy/t/lsfURb/JTBY2Q04uo9IYUsMfek5Mfsx/PEdvnz2Rwng1lagRtfv1E23 +WZ6B8zZyAEAf0rr9OR3UtEcgFKewS5GREU1gjpzjcRBqasHW/8CwvGP3TLJfHcXXRvP dJeFrlG95H6z9+hN+7XOxA6LEu0+rLZMf3y+E0ISrAC5i1HZWBu9vaclIliBKD9fdQpt r45g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=C1SR8RrxOc74lsMmszdu5piQ6864h8pZBYqiJVBluj4=; b=h02kSNy3NgFvdmGEgoUVRmBLhIJ4jhI0uwr5QdKw/2fjlWh5fUNS0PvWIl2j3XplLq u0hwfNdswHU+ZUk3ezTkB5CmSQ0hwHxKooeax4Fix8AB39dyiL14zyGEgy8Crfa/YAEO NDJxy71HhpVgrDDhXcIolR76U+Qa1aKbiifSTOVj+zQk+iCL7KbU9YKFHOaOXl+ZRuLZ pZlKhAvzpthBzS48d4dio6+Qk3vJVA3Bga2tpr+8NZGHkK0qIcqiKq02FHDcN8qlhkjf 7VcTr+ooTh/kzeC9uhc9XDEHzBYgNp/ustL2X8VTBBx96XhTZqCHb60aIaQY6Vkgv/jt 29XQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=cP5FweuW; spf=pass (google.com: domain of devicetree-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=devicetree-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. [23.128.96.18]) by mx.google.com with ESMTP id l89si5784444ede.577.2020.12.11.06.33.27; Fri, 11 Dec 2020 06:33:27 -0800 (PST) Received-SPF: pass (google.com: domain of devicetree-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=cP5FweuW; spf=pass (google.com: domain of devicetree-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=devicetree-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 S2406249AbgLKOcJ (ORCPT + 7 others); Fri, 11 Dec 2020 09:32:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45002 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2406244AbgLKOcE (ORCPT ); Fri, 11 Dec 2020 09:32:04 -0500 Received: from mail-lf1-x142.google.com (mail-lf1-x142.google.com [IPv6:2a00:1450:4864:20::142]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 30D6FC061282 for ; Fri, 11 Dec 2020 06:30:46 -0800 (PST) Received: by mail-lf1-x142.google.com with SMTP id h19so13547006lfc.12 for ; Fri, 11 Dec 2020 06:30:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=C1SR8RrxOc74lsMmszdu5piQ6864h8pZBYqiJVBluj4=; b=cP5FweuWQW4jWJFUOEYzkaeaIE0uuS5uRoDi1M6DG/Z/A/wqXB1gW7LqwfjyH80kzN 8l3ZMTxA6w9CyZiFmP8lyTMWjMRpQ/GxtRFZP7F9C+YczNRJtrZV3+pea50FxiOwTEkW KReElXdk4kgKObNkx7TYTHxevsOx8krJyweDA49nbNvUoUWDJwwtFlQGRaxM5tB7/PMh 1o0vi/hbuR3oRIaDwUdIujKLzHLQBpjoYEhYUrkrgdeymoPrp3Bppf6MsAQm4Qv0qz/+ LoXyUHgdrZa2TN0VFZ5cIByUn9Scc8L2U+YRqWIS0N2oABi3ksfMl3wRkKlm54jRuVV+ ZucQ== 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=C1SR8RrxOc74lsMmszdu5piQ6864h8pZBYqiJVBluj4=; b=BERKXR0hC+Udih0XIZZUPoqrgEwmg5TgTQ1TCPsZIsDcOEGGhwDRWmqQWHSZ9gRk/w 6RoJjjidjgSSwde20ehhwRYFldyCBaXUWPmd+cuOQzHmEd7bRjEqtleuWfeKKAN0je6C blvMMQeZ5Th9ZASHcrS967SD6z3RmigYtxAIdV8h2Ajd28vDzWAsq3jha7imSjgT/Y+i Y23+Y6bdHDJQXeTQIswfAwb/W82S2ZVPctForh3cAML4c7z/2O/CX601Tcl6YBsygKsu m+JoOfUIp4GyJpSJmrmTbxAeHrtVdd6LiD5Zfc2SJ0eR7n1TMdUlrzEcAyadn39WPLcT 98KA== X-Gm-Message-State: AOAM5326OgJxpU+AUtiCphCpFrqXmx/MU7JmAQzNMj9BsLfwdmZtxdbA Xe2xVUur8aryGEy/Aa5Xs4WzhQ== X-Received: by 2002:a19:c8cc:: with SMTP id y195mr1120505lff.352.1607697044656; Fri, 11 Dec 2020 06:30:44 -0800 (PST) Received: from gilgamesh.semihalf.com (193-106-246-138.noc.fibertech.net.pl. [193.106.246.138]) by smtp.gmail.com with ESMTPSA id x26sm906491lfq.112.2020.12.11.06.30.43 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 11 Dec 2020 06:30:44 -0800 (PST) From: Grzegorz Jaszczyk To: ohad@wizery.com, bjorn.andersson@linaro.org, mathieu.poirier@linaro.org, robh+dt@kernel.org, s-anna@ti.com, ssantosh@kernel.org Cc: grzegorz.jaszczyk@linaro.org, linux-remoteproc@vger.kernel.org, lee.jones@linaro.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org, praneeth@ti.com, rogerq@ti.com Subject: [PATCH 2/5] remoteproc: pru: Add APIs to get and put the PRU cores Date: Fri, 11 Dec 2020 15:29:30 +0100 Message-Id: <20201211142933.25784-3-grzegorz.jaszczyk@linaro.org> X-Mailer: git-send-email 2.29.0 In-Reply-To: <20201211142933.25784-1-grzegorz.jaszczyk@linaro.org> References: <20201211142933.25784-1-grzegorz.jaszczyk@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Tero Kristo Add two new APIs, pru_rproc_get() and pru_rproc_put(), to the PRU driver to allow client drivers to acquire and release the remoteproc device associated with a PRU core. The PRU cores are treated as resources with only one client owning it at a time. The pru_rproc_get() function returns the rproc handle corresponding to a PRU core identified by the device tree "prus" property under the client node. The pru_rproc_put() is the complementary function to pru_rproc_get(). Co-developed-by: Suman Anna Signed-off-by: Suman Anna Signed-off-by: Tero Kristo Co-developed-by: Grzegorz Jaszczyk Signed-off-by: Grzegorz Jaszczyk --- drivers/remoteproc/pru_rproc.c | 125 ++++++++++++++++++++++++++++++++- include/linux/pruss.h | 56 +++++++++++++++ 2 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 include/linux/pruss.h -- 2.29.0 diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 2667919d76b3..cc2e585778b1 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -111,6 +112,8 @@ struct pru_private_data { * @rproc: remoteproc pointer for this PRU core * @data: PRU core specific data * @mem_regions: data for each of the PRU memory regions + * @client_np: client device node + * @lock: mutex to protect client usage * @fw_name: name of firmware image used during loading * @mapped_irq: virtual interrupt numbers of created fw specific mapping * @pru_interrupt_map: pointer to interrupt mapping description (firmware) @@ -126,6 +129,8 @@ struct pru_rproc { struct rproc *rproc; const struct pru_private_data *data; struct pruss_mem_region mem_regions[PRU_IOMEM_MAX]; + struct device_node *client_np; + struct mutex lock; /* client access lock */ const char *fw_name; unsigned int *mapped_irq; struct pru_irq_rsc *pru_interrupt_map; @@ -146,6 +151,119 @@ void pru_control_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val) writel_relaxed(val, pru->mem_regions[PRU_IOMEM_CTRL].va + reg); } +static struct rproc *__pru_rproc_get(struct device_node *np, int index) +{ + struct device_node *rproc_np = NULL; + struct platform_device *pdev; + struct rproc *rproc; + + rproc_np = of_parse_phandle(np, "prus", index); + if (!rproc_np || !of_device_is_available(rproc_np)) + return ERR_PTR(-ENODEV); + + pdev = of_find_device_by_node(rproc_np); + of_node_put(rproc_np); + + if (!pdev) + /* probably PRU not yet probed */ + return ERR_PTR(-EPROBE_DEFER); + + /* make sure it is PRU rproc */ + if (!is_pru_rproc(&pdev->dev)) { + put_device(&pdev->dev); + return ERR_PTR(-ENODEV); + } + + rproc = platform_get_drvdata(pdev); + put_device(&pdev->dev); + if (!rproc) + return ERR_PTR(-EPROBE_DEFER); + + get_device(&rproc->dev); + + return rproc; +} + +/** + * pru_rproc_get() - get the PRU rproc instance from a device node + * @np: the user/client device node + * @index: index to use for the prus property + * @pru_id: optional pointer to return the PRU remoteproc processor id + * + * This function looks through a client device node's "prus" property at index + * @index and returns the rproc handle for a valid PRU remote processor if + * found. The function allows only one user to own the PRU rproc resource at + * a time. Caller must call pru_rproc_put() when done with using the rproc, + * not required if the function returns a failure. + * + * When optional @pru_id pointer is passed the PRU remoteproc processor id is + * returned. + * + * Return: rproc handle on success, and an ERR_PTR on failure using one + * of the following error values + * -ENODEV if device is not found + * -EBUSY if PRU is already acquired by anyone + * -EPROBE_DEFER is PRU device is not probed yet + */ +struct rproc *pru_rproc_get(struct device_node *np, int index, + enum pruss_pru_id *pru_id) +{ + struct rproc *rproc; + struct pru_rproc *pru; + struct device *dev; + + rproc = __pru_rproc_get(np, index); + if (IS_ERR(rproc)) + return rproc; + + pru = rproc->priv; + dev = &rproc->dev; + + mutex_lock(&pru->lock); + + if (pru->client_np) { + mutex_unlock(&pru->lock); + put_device(dev); + return ERR_PTR(-EBUSY); + } + + pru->client_np = np; + + mutex_unlock(&pru->lock); + + if (pru_id) + *pru_id = pru->id; + + return rproc; +} +EXPORT_SYMBOL_GPL(pru_rproc_get); + +/** + * pru_rproc_put() - release the PRU rproc resource + * @rproc: the rproc resource to release + * + * Releases the PRU rproc resource and makes it available to other + * users. + */ +void pru_rproc_put(struct rproc *rproc) +{ + struct pru_rproc *pru; + + if (IS_ERR_OR_NULL(rproc) || !is_pru_rproc(rproc->dev.parent)) + return; + + pru = rproc->priv; + if (!pru->client_np) + return; + + mutex_lock(&pru->lock); + pru->client_np = NULL; + mutex_unlock(&pru->lock); + + put_device(&rproc->dev); +} +EXPORT_SYMBOL_GPL(pru_rproc_put); + static inline u32 pru_debug_read_reg(struct pru_rproc *pru, unsigned int reg) { return readl_relaxed(pru->mem_regions[PRU_IOMEM_DEBUG].va + reg); @@ -706,14 +824,14 @@ static int pru_rproc_set_id(struct pru_rproc *pru) case RTU0_IRAM_ADDR_MASK: fallthrough; case PRU0_IRAM_ADDR_MASK: - pru->id = 0; + pru->id = PRUSS_PRU0; break; case TX_PRU1_IRAM_ADDR_MASK: fallthrough; case RTU1_IRAM_ADDR_MASK: fallthrough; case PRU1_IRAM_ADDR_MASK: - pru->id = 1; + pru->id = PRUSS_PRU1; break; default: ret = -EINVAL; @@ -775,6 +893,7 @@ static int pru_rproc_probe(struct platform_device *pdev) pru->pruss = platform_get_drvdata(ppdev); pru->rproc = rproc; pru->fw_name = fw_name; + mutex_init(&pru->lock); for (i = 0; i < ARRAY_SIZE(mem_names); i++) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, @@ -859,7 +978,7 @@ MODULE_DEVICE_TABLE(of, pru_rproc_match); static struct platform_driver pru_rproc_driver = { .driver = { - .name = "pru-rproc", + .name = PRU_RPROC_DRVNAME, .of_match_table = pru_rproc_match, .suppress_bind_attrs = true, }, diff --git a/include/linux/pruss.h b/include/linux/pruss.h new file mode 100644 index 000000000000..43cb5c2eed08 --- /dev/null +++ b/include/linux/pruss.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/** + * PRU-ICSS Subsystem user interfaces + * + * Copyright (C) 2015-2020 Texas Instruments Incorporated - http://www.ti.com + * Suman Anna + */ + +#ifndef __LINUX_PRUSS_H +#define __LINUX_PRUSS_H + +#include +#include + +#define PRU_RPROC_DRVNAME "pru-rproc" + +/* + * enum pruss_pru_id - PRU core identifiers + */ +enum pruss_pru_id { + PRUSS_PRU0 = 0, + PRUSS_PRU1, + PRUSS_NUM_PRUS, +}; + +struct device_node; + +#if IS_ENABLED(CONFIG_PRU_REMOTEPROC) + +struct rproc *pru_rproc_get(struct device_node *np, int index, + enum pruss_pru_id *pru_id); +void pru_rproc_put(struct rproc *rproc); + +#else + +static inline struct rproc * +pru_rproc_get(struct device_node *np, int index, enum pruss_pru_id *pru_id) +{ + return ERR_PTR(-ENOTSUPP); +} + +static inline void pru_rproc_put(struct rproc *rproc) { } + +#endif /* CONFIG_PRU_REMOTEPROC */ + +static inline bool is_pru_rproc(struct device *dev) +{ + const char *drv_name = dev_driver_string(dev); + + if (strncmp(drv_name, PRU_RPROC_DRVNAME, sizeof(PRU_RPROC_DRVNAME))) + return false; + + return true; +} + +#endif /* __LINUX_PRUSS_H */