From patchwork Tue Jun 22 06:34:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lokesh Vutla X-Patchwork-Id: 1495462 X-Patchwork-Delegate: lokeshvutla@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.a=rsa-sha256 header.s=ti-com-17Q1 header.b=vejxe6As; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4G8Gpq32sRz9srX for ; Tue, 22 Jun 2021 16:34:59 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0553B829B7; Tue, 22 Jun 2021 08:34:46 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=ti.com header.i=@ti.com header.b="vejxe6As"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 62460829B5; Tue, 22 Jun 2021 08:34:43 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from fllv0015.ext.ti.com (fllv0015.ext.ti.com [198.47.19.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id BAE8A828EB for ; Tue, 22 Jun 2021 08:34:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=ti.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=lokeshvutla@ti.com Received: from lelv0266.itg.ti.com ([10.180.67.225]) by fllv0015.ext.ti.com (8.15.2/8.15.2) with ESMTP id 15M6YaQB005959 for ; Tue, 22 Jun 2021 01:34:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1624343676; bh=eoaRoMPdBRfjm/KiVbce/M5DAhp6+aybQSqOAfAspAQ=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=vejxe6AsvEDGNPFHvslkWhRPUirsqxR+K77jHieUDeB32UPgYNrL+6fDbVpBANLbG JCFpa+uPVAvIMQ16Hn2qhEsPU/qWGRX2xzNJAEPFKKZHj6MTAzWelT8/fUj4n3eQnx bifWJnYe4NZNTMthgUBLQE8H0EsI/BmDhDtEEf4M= Received: from DLEE114.ent.ti.com (dlee114.ent.ti.com [157.170.170.25]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id 15M6YatZ063125 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Tue, 22 Jun 2021 01:34:36 -0500 Received: from DLEE100.ent.ti.com (157.170.170.30) by DLEE114.ent.ti.com (157.170.170.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2176.2; Tue, 22 Jun 2021 01:34:35 -0500 Received: from fllv0039.itg.ti.com (10.64.41.19) by DLEE100.ent.ti.com (157.170.170.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2176.2 via Frontend Transport; Tue, 22 Jun 2021 01:34:36 -0500 Received: from lokesh-ssd.dhcp.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by fllv0039.itg.ti.com (8.15.2/8.15.2) with ESMTP id 15M6YVGA066559; Tue, 22 Jun 2021 01:34:34 -0500 From: Lokesh Vutla To: CC: Lokesh Vutla , Keerthy , Suman Anna Subject: [PATCH v2 1/5] soc: ti: pruss: Add a platform driver for PRUSS in TI SoCs Date: Tue, 22 Jun 2021 12:04:27 +0530 Message-ID: <20210622063431.3151-2-lokeshvutla@ti.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210622063431.3151-1-lokeshvutla@ti.com> References: <20210622063431.3151-1-lokeshvutla@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean From: Keerthy The Programmable Real-Time Unit - Industrial Communication Subsystem (PRU-ICSS) is present of various TI SoCs such as AM335x or AM437x or the AM654x family. Each SoC can have one or more PRUSS instances that may or may not be identical. The PRUSS consists of dual 32-bit RISC cores called the Programmable Real-Time Units (PRUs), some shared, data and instruction memories, some internal peripheral modules, and an interrupt controller. The programmable nature of the PRUs provide flexibility to implement custom peripheral interfaces, fast real-time responses, or specialized data handling. Add support for pruss driver. Currently am654x family is supported. Signed-off-by: Keerthy Signed-off-by: Roger Quadros Signed-off-by: Lokesh Vutla --- MAINTAINERS | 1 + drivers/soc/ti/Kconfig | 11 ++ drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pruss.c | 217 +++++++++++++++++++++++++++++++++ include/linux/pruss_driver.h | 227 +++++++++++++++++++++++++++++++++++ 5 files changed, 457 insertions(+) create mode 100644 drivers/soc/ti/pruss.c create mode 100644 include/linux/pruss_driver.h diff --git a/MAINTAINERS b/MAINTAINERS index 86ff5e04a6..b85a968ac3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -522,6 +522,7 @@ F: drivers/sysreset/sysreset-ti-sci.c F: drivers/thermal/ti-bandgap.c F: drivers/timer/omap-timer.c F: drivers/watchdog/omap_wdt.c +F: include/linux/pruss_driver.h F: include/linux/soc/ti/ ARM U8500 diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index e4f8834448..0ee21f9904 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -23,4 +23,15 @@ config TI_KEYSTONE_SERDES SerDes driver for Keystone SoC used for ethernet support on TI K2 platforms. +config TI_PRUSS + bool "Support for TI's K3 based Pruss driver" + depends on DM + depends on ARCH_K3 + depends on OF_CONTROL + depends on SYSCON + help + Support for TI PRU-ICSSG subsystem. + Currently supported on AM65xx SoCs Say Y here to support the + Programmable Realtime Unit (PRU). + endif # SOC_TI diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index 4ec04ee125..34f80aad29 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_TI_K3_NAVSS_RINGACC) += k3-navss-ringacc.o obj-$(CONFIG_TI_KEYSTONE_SERDES) += keystone_serdes.o +obj-$(CONFIG_TI_PRUSS) += pruss.o diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c new file mode 100644 index 0000000000..461390925d --- /dev/null +++ b/drivers/soc/ti/pruss.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PRU-ICSS platform driver for various TI SoCs + * + * Copyright (C) 2020-2021 Texas Instruments Incorporated - https://www.ti.com/ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PRUSS_CFG_IEPCLK 0x30 +#define ICSSG_CFG_CORE_SYNC 0x3c + +#define ICSSG_TASK_MGR_OFFSET 0x2a000 + +/* PRUSS_IEPCLK register bits */ +#define PRUSS_IEPCLK_IEP_OCP_CLK_EN BIT(0) + +/* ICSSG CORE_SYNC register bits */ +#define ICSSG_CORE_VBUSP_SYNC_EN BIT(0) + +/* + * pruss_request_tm_region() - Request pruss for task manager region + * @dev: corresponding k3 device + * @loc: the task manager physical address + * + * Return: 0 if all goes good, else appropriate error message. + */ +int pruss_request_tm_region(struct udevice *dev, phys_addr_t *loc) +{ + struct pruss *priv; + + priv = dev_get_priv(dev); + if (!priv || !priv->mem_regions[PRUSS_MEM_DRAM0].pa) + return -EINVAL; + + *loc = priv->mem_regions[PRUSS_MEM_DRAM0].pa + ICSSG_TASK_MGR_OFFSET; + + return 0; +} + +/** + * pruss_request_mem_region() - request a memory resource + * @dev: the pruss device + * @mem_id: the memory resource id + * @region: pointer to memory region structure to be filled in + * + * This function allows a client driver to request a memory resource, + * and if successful, will let the client driver own the particular + * memory region until released using the pruss_release_mem_region() + * API. + * + * Returns the memory region if requested resource is available, an + * error otherwise + */ +int pruss_request_mem_region(struct udevice *dev, enum pruss_mem mem_id, + struct pruss_mem_region *region) +{ + struct pruss *pruss; + + pruss = dev_get_priv(dev); + if (!pruss || !region) + return -EINVAL; + + if (mem_id >= PRUSS_MEM_MAX) + return -EINVAL; + + if (pruss->mem_in_use[mem_id]) + return -EBUSY; + + *region = pruss->mem_regions[mem_id]; + pruss->mem_in_use[mem_id] = region; + + return 0; +} + +/** + * pruss_release_mem_region() - release a memory resource + * @dev: the pruss device + * @region: the memory region to release + * + * This function is the complimentary function to + * pruss_request_mem_region(), and allows the client drivers to + * release back a memory resource. + * + * Returns 0 on success, an error code otherwise + */ +int pruss_release_mem_region(struct udevice *dev, + struct pruss_mem_region *region) +{ + struct pruss *pruss; + int id; + + pruss = dev_get_priv(dev); + if (!pruss || !region) + return -EINVAL; + + /* find out the memory region being released */ + for (id = 0; id < PRUSS_MEM_MAX; id++) { + if (pruss->mem_in_use[id] == region) + break; + } + + if (id == PRUSS_MEM_MAX) + return -EINVAL; + + pruss->mem_in_use[id] = NULL; + + return 0; +} + +/** + * pruss_cfg_update() - configure a PRUSS CFG sub-module register + * @dev: the pruss device + * @reg: register offset within the CFG sub-module + * @mask: bit mask to use for programming the @val + * @val: value to write + * + * Programs a given register within the PRUSS CFG sub-module + * + * Returns 0 on success, or an error code otherwise + */ +int pruss_cfg_update(struct udevice *dev, unsigned int reg, + unsigned int mask, unsigned int val) +{ + struct pruss *pruss; + + pruss = dev_get_priv(dev); + if (IS_ERR_OR_NULL(pruss)) + return -EINVAL; + + return regmap_update_bits(pruss->cfg, reg, mask, val); +} + +/** + * pruss_probe() - Basic probe + * @dev: corresponding k3 device + * + * Return: 0 if all goes good, else appropriate error message. + */ +static int pruss_probe(struct udevice *dev) +{ + const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" }; + ofnode sub_node, node, memories; + struct udevice *syscon; + struct pruss *priv; + int ret, idx, i; + + priv = dev_get_priv(dev); + node = dev_ofnode(dev); + priv->dev = dev; + memories = ofnode_find_subnode(node, "memories"); + + for (i = 0; i < ARRAY_SIZE(mem_names); i++) { + idx = ofnode_stringlist_search(memories, "reg-names", mem_names[i]); + priv->mem_regions[i].pa = ofnode_get_addr_size_index(memories, idx, + (u64 *)&priv->mem_regions[i].size); + } + + sub_node = ofnode_find_subnode(node, "cfg"); + ret = uclass_get_device_by_ofnode(UCLASS_SYSCON, sub_node, + &syscon); + + priv->cfg = syscon_get_regmap(syscon); + if (IS_ERR(priv->cfg)) { + dev_err(dev, "unable to get cfg regmap (%ld)\n", + PTR_ERR(priv->cfg)); + return -ENODEV; + } + + /* + * ToDo: To be modelled as clocks. + * The CORE block uses two multiplexers to allow software to + * select one of three source clocks (ICSSGn_CORE_CLK, ICSSGn_ICLK or + * ICSSGn_IEP_CLK) for the final clock source of the CORE block. + * The user needs to configure ICSSG_CORE_SYNC_REG[0] CORE_VBUSP_SYNC_EN + * bit & ICSSG_IEPCLK_REG[0] IEP_OCP_CLK_EN bit in order to select the + * clock source to the CORE block. + */ + ret = regmap_update_bits(priv->cfg, ICSSG_CFG_CORE_SYNC, + ICSSG_CORE_VBUSP_SYNC_EN, + ICSSG_CORE_VBUSP_SYNC_EN); + if (ret) + return ret; + ret = regmap_update_bits(priv->cfg, PRUSS_CFG_IEPCLK, + PRUSS_IEPCLK_IEP_OCP_CLK_EN, + PRUSS_IEPCLK_IEP_OCP_CLK_EN); + if (ret) + return ret; + + dev_dbg(dev, "pruss successfully probed %s\n", dev->name); + + return 0; +} + +static const struct udevice_id pruss_ids[] = { + { .compatible = "ti,am654-icssg"}, + {} +}; + +U_BOOT_DRIVER(pruss) = { + .name = "pruss", + .of_match = pruss_ids, + .id = UCLASS_MISC, + .probe = pruss_probe, + .priv_auto = sizeof(struct pruss), +}; diff --git a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h new file mode 100644 index 0000000000..1408111118 --- /dev/null +++ b/include/linux/pruss_driver.h @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __TI_PRUSS_H +#define __TI_PRUSS_H + +/* + * PRU_ICSS_CFG registers + * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only + */ +#define PRUSS_CFG_REVID 0x00 +#define PRUSS_CFG_SYSCFG 0x04 +#define PRUSS_CFG_GPCFG(x) (0x08 + (x) * 4) +#define PRUSS_CFG_CGR 0x10 +#define PRUSS_CFG_ISRP 0x14 +#define PRUSS_CFG_ISP 0x18 +#define PRUSS_CFG_IESP 0x1C +#define PRUSS_CFG_IECP 0x20 +#define PRUSS_CFG_SCRP 0x24 +#define PRUSS_CFG_PMAO 0x28 +#define PRUSS_CFG_MII_RT 0x2C +#define PRUSS_CFG_IEPCLK 0x30 +#define PRUSS_CFG_SPP 0x34 +#define PRUSS_CFG_PIN_MX 0x40 + +/* PRUSS_GPCFG register bits */ +#define PRUSS_GPCFG_PRU_GPO_SH_SEL BIT(25) + +#define PRUSS_GPCFG_PRU_DIV1_SHIFT 20 +#define PRUSS_GPCFG_PRU_DIV1_MASK GENMASK(24, 20) + +#define PRUSS_GPCFG_PRU_DIV0_SHIFT 15 +#define PRUSS_GPCFG_PRU_DIV0_MASK GENMASK(15, 19) + +#define PRUSS_GPCFG_PRU_GPO_MODE BIT(14) +#define PRUSS_GPCFG_PRU_GPO_MODE_DIRECT 0 +#define PRUSS_GPCFG_PRU_GPO_MODE_SERIAL BIT(14) + +#define PRUSS_GPCFG_PRU_GPI_SB BIT(13) + +#define PRUSS_GPCFG_PRU_GPI_DIV1_SHIFT 8 +#define PRUSS_GPCFG_PRU_GPI_DIV1_MASK GENMASK(12, 8) + +#define PRUSS_GPCFG_PRU_GPI_DIV0_SHIFT 3 +#define PRUSS_GPCFG_PRU_GPI_DIV0_MASK GENMASK(7, 3) + +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_POSITIVE 0 +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE_NEGATIVE BIT(2) +#define PRUSS_GPCFG_PRU_GPI_CLK_MODE BIT(2) + +#define PRUSS_GPCFG_PRU_GPI_MODE_MASK GENMASK(1, 0) +#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT 0 + +#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT 26 +#define PRUSS_GPCFG_PRU_MUX_SEL_MASK GENMASK(29, 26) + +/* PRUSS_MII_RT register bits */ +#define PRUSS_MII_RT_EVENT_EN BIT(0) + +/* PRUSS_SPP register bits */ +#define PRUSS_SPP_PRU1_PAD_HP_EN BIT(0) +#define PRUSS_SPP_XFER_SHIFT_EN BIT(1) +#define PRUSS_SPP_XFR_BYTE_SHIFT_EN BIT(2) +#define PRUSS_SPP_RTU_XFR_SHIFT_EN BIT(3) + +/** + * enum pruss_gp_mux_sel - PRUSS GPI/O Mux modes for the + * PRUSS_GPCFG0/1 registers + * + * NOTE: The below defines are the most common values, but there + * are some exceptions like on 66AK2G, where the RESERVED and MII2 + * values are interchanged. Also, this bit-field does not exist on + * AM335x SoCs + */ +enum pruss_gp_mux_sel { + PRUSS_GP_MUX_SEL_GP = 0, + PRUSS_GP_MUX_SEL_ENDAT, + PRUSS_GP_MUX_SEL_RESERVED, + PRUSS_GP_MUX_SEL_SD, + PRUSS_GP_MUX_SEL_MII2, + PRUSS_GP_MUX_SEL_MAX, +}; + +/** + * enum pruss_gpi_mode - PRUSS GPI configuration modes, used + * to program the PRUSS_GPCFG0/1 registers + */ +enum pruss_gpi_mode { + PRUSS_GPI_MODE_DIRECT = 0, + PRUSS_GPI_MODE_PARALLEL, + PRUSS_GPI_MODE_28BIT_SHIFT, + PRUSS_GPI_MODE_MII, +}; + +/** + * enum pruss_pru_id - PRU core identifiers + */ +enum pruss_pru_id { + PRUSS_PRU0 = 0, + PRUSS_PRU1, + PRUSS_NUM_PRUS, +}; + +/** + * enum pru_ctable_idx - Configurable Constant table index identifiers + */ +enum pru_ctable_idx { + PRU_C24 = 0, + PRU_C25, + PRU_C26, + PRU_C27, + PRU_C28, + PRU_C29, + PRU_C30, + PRU_C31, +}; + +/** + * enum pruss_mem - PRUSS memory range identifiers + */ +enum pruss_mem { + PRUSS_MEM_DRAM0 = 0, + PRUSS_MEM_DRAM1, + PRUSS_MEM_SHRD_RAM2, + PRUSS_MEM_MAX, +}; + +/** + * struct pruss_mem_region - PRUSS memory region structure + * @va: kernel virtual address of the PRUSS memory region + * @pa: physical (bus) address of the PRUSS memory region + * @size: size of the PRUSS memory region + */ +struct pruss_mem_region { + void __iomem *va; + phys_addr_t pa; + size_t size; +}; + +/** + * struct pruss - PRUSS parent structure + * @dev: pruss device pointer + * @cfg: regmap for config region + * @mem_regions: data for each of the PRUSS memory regions + * @mem_in_use: to indicate if memory resource is in use + */ +struct pruss { + struct udevice *dev; + struct regmap *cfg; + struct pruss_mem_region mem_regions[PRUSS_MEM_MAX]; + struct pruss_mem_region *mem_in_use[PRUSS_MEM_MAX]; +}; + +int pruss_request_tm_region(struct udevice *dev, phys_addr_t *loc); +int pruss_request_mem_region(struct udevice *dev, enum pruss_mem mem_id, + struct pruss_mem_region *region); +int pruss_release_mem_region(struct udevice *dev, struct pruss_mem_region *region); +int pruss_cfg_update(struct udevice *dev, unsigned int reg, + unsigned int mask, unsigned int val); + +/** + * pruss_cfg_gpimode() - set the GPI mode of the PRU + * @dev: the pruss device + * @pru_id: the rproc instance handle of the PRU + * @mode: GPI mode to set + * + * Sets the GPI mode for a given PRU by programming the + * corresponding PRUSS_CFG_GPCFGx register + * + * Returns 0 on success, or an error code otherwise + */ +static inline int pruss_cfg_gpimode(struct udevice *dev, enum pruss_pru_id id, + enum pruss_gpi_mode mode) +{ + if (id < 0) + return -EINVAL; + + return pruss_cfg_update(dev, PRUSS_CFG_GPCFG(id), + PRUSS_GPCFG_PRU_GPI_MODE_MASK, + mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT); +} + +/** + * pruss_cfg_miirt_enable() - Enable/disable MII RT Events + * @dev: the pruss device + * @enable: enable/disable + * + * Enable/disable the MII RT Events for the PRUSS. + */ +static inline int pruss_cfg_miirt_enable(struct udevice *dev, bool enable) +{ + u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0; + + return pruss_cfg_update(dev, PRUSS_CFG_MII_RT, + PRUSS_MII_RT_EVENT_EN, set); +} + +/** + * pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality + * @dev: the pruss device + * @enable: enable/disable + */ +static inline int pruss_cfg_xfr_enable(struct udevice *dev, bool enable) +{ + u32 set = enable ? PRUSS_SPP_XFER_SHIFT_EN : 0; + + return pruss_cfg_update(dev, PRUSS_CFG_SPP, + PRUSS_SPP_XFER_SHIFT_EN, set); +} + +/** + * pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device + * @pruss: pruss device + * @pru_id: PRU identifier (0-1) + * @mux: new mux value for PRU + */ +static inline int pruss_cfg_set_gpmux(struct udevice *dev, + enum pruss_pru_id id, u8 mux) +{ + if (mux >= PRUSS_GP_MUX_SEL_MAX) + return -EINVAL; + + return pruss_cfg_update(dev, PRUSS_CFG_GPCFG(id), + PRUSS_GPCFG_PRU_MUX_SEL_MASK, + (u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT); +} + +#endif /* __TI_PRUSS_H */