From patchwork Fri Aug 11 15:42:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 109905 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1081445qge; Fri, 11 Aug 2017 08:43:56 -0700 (PDT) X-Received: by 10.84.196.1 with SMTP id k1mr18085705pld.137.1502466235977; Fri, 11 Aug 2017 08:43:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502466235; cv=none; d=google.com; s=arc-20160816; b=YLgsVOM64ughMlacECP2Wlf0yf9B1t31xD5phwRMD5A5NmZRy3kzX5gvi9nGPN4nzY ExcTrjfWdA/DWViwfkvPZbBVCgZx5JA4frRR+XhNxsw2Xdk9L4td3m7MIp4gHHLtojas hHvB8+zXZIG4EFuUXPOBbnNTd+FJKNLLv7HxzLHRFJTdgwdvyRSjI3owqR3/MFmbw2Qs aV+LZDYhuG30JKj/0vxgy3R98TK1KeMMjnBfPuRZRP2Kh+N+bFTlESH4PpWXR8V4AHMV zPCKnJuek8PuRK7vesejLFROvdG5Q3U9ZPtPl4YrDuxWtR/G4ktmMlP2aiBJQkSPgavM Cfyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=AB8am0REOkhfntEGal1rjAOunxPU744WX2yPer7FEFM=; b=UKDYzuA1HmelY45lZVDiEZj+Myunjt95/tk1AOj8Jiphdf9unxkqtw5ejZL/HGeApp RjWvdeOMQjBZ3tPctgVhL3IDMHtBTyHsCZPzCptiU6l1cWZGg+Ja/WY/FAw+WIvxfHUL BcA8A2AaKKtV7Rln6TM4XMNFRiEISwJwwDkCyLXAIDyOJ1Go/JEB421rKpwGp5QR44Qu O8uoy75CtzN6OduyGir7UnceG5mZ08cMhWeGCUB1GFtmzfjKFchdsLm9z2CWTnKcLkBO 8GywCiEFaMesBcPSMQdPB9VsXoqnvIAl7TVJXISu7Uz6cKZMuVujjNBNLmSbVQvWIOtH //aQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=jFOAB8FF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s187si653148pfs.647.2017.08.11.08.43.55; Fri, 11 Aug 2017 08:43:55 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=jFOAB8FF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753514AbdHKPnw (ORCPT + 25 others); Fri, 11 Aug 2017 11:43:52 -0400 Received: from mail-pg0-f47.google.com ([74.125.83.47]:33707 "EHLO mail-pg0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753175AbdHKPmk (ORCPT ); Fri, 11 Aug 2017 11:42:40 -0400 Received: by mail-pg0-f47.google.com with SMTP id u5so17065462pgn.0 for ; Fri, 11 Aug 2017 08:42:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AB8am0REOkhfntEGal1rjAOunxPU744WX2yPer7FEFM=; b=jFOAB8FFDx2/fd4SWYkF3DQmoCqn9j++ZEfI5LL26qvFVigvvZevYsGU1fICZ7rc5l Dbx18mHy7VG/e3cE/KydUTi9k1zGuV3RityY0rWUQuBXLRqCy4n5EVd9ZRCZ6FYHlWsd BxiqUOGvh+yMv2aURmInVQ7+yNUZNIYjrVqkc= 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=AB8am0REOkhfntEGal1rjAOunxPU744WX2yPer7FEFM=; b=ihM8yBqAiknziyRXbROj/2HdSM1f+ohFuJxGh0ZSkM0P3Vja7BcNydt7H05t5qgaAT jDeM9UujvT4BNXSvUXfjp7NeMEdjmsNInsjIwQhD2xgMf0ZnCzFpUmuY2cEin3lwG4QQ lkb3bhKkv+j5gOKuzh39QZPkq2YB5QXcJKfiSB29BxylAejoZ8rUJXWBNTspFZh2G9Sr Ke0oDs5vM+TJjB6ZWyhWzd0Wo2gZ2e2qIdL3TnXg+ndxA7+sAD68NGj4UAAvid1HWHA/ LmR3m2GuRjccPODTohoSnf093ZDmjI7HXNBWOyV7AsTgKtDkLGg5ZzuW7GfldCCh9DIs Ui8g== X-Gm-Message-State: AHYfb5ivEoqmzeuBcIK8p2khVbxCTSQuDFmzwAVmr5SJjpResjKWHfge d5NHDSCqguU7NSid X-Received: by 10.101.91.66 with SMTP id y2mr10450011pgr.88.1502466159427; Fri, 11 Aug 2017 08:42:39 -0700 (PDT) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id a63sm2351071pfc.165.2017.08.11.08.42.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Aug 2017 08:42:38 -0700 (PDT) From: Stephen Boyd To: Rob Herring , Frank Rowand Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Russell King - ARM Linux , devicetree-spec@vger.kernel.org Subject: [RFC/PATCH v4 1/4] Document nexus nodes/specifier remapping Date: Fri, 11 Aug 2017 08:42:33 -0700 Message-Id: <20170811154236.12891-2-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.14.GIT In-Reply-To: <20170811154236.12891-1-stephen.boyd@linaro.org> References: <20170811154236.12891-1-stephen.boyd@linaro.org> MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Document the generic nexus node properties. This can be used by any specifier that conforms to #-cells where they want to support remapping phandle lists through nexus nodes. This is similar to interrupt remapping, but slightly different because we don't consider unit addresses when doing mappings. This is mostly a copy/paste of the interrupt specification, with the unit address parts removed and generalized to any specifier. There's also the addition of a pass through mechanism to make things more compact if desired in the mapping table. Signed-off-by: Stephen Boyd --- I still need to write the blurb about what this is all about, but I wanted to send this out now to get early feedback. Some starting points: 1) Replace child/parent with incoming/outgoing everywhere? 2) Make a pretty picture to describe remapping phandle+specifiers similar to the interrupt hierarchy diagram? 3) Come up with some better name than ? Kernel-doc uses but I'm not sure that's any better. source/devicetree-basics.rst | 208 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) -- 2.7.4 diff --git a/source/devicetree-basics.rst b/source/devicetree-basics.rst index 02696bac15c7..b0571145ee40 100644 --- a/source/devicetree-basics.rst +++ b/source/devicetree-basics.rst @@ -1280,3 +1280,211 @@ performed: * That result is looked up in the *interrupt-map* table, which maps to the parent interrupt specifier ``<4 1>``. +.. _sect-nexus: + +Nexus Nodes and Specifier Mapping +--------------------------------- + +TODO: Write blurb here about nexus nodes and remapping them + +Nexus Node Properties +~~~~~~~~~~~~~~~~~~~~~ + +A nexus node shall have a *#-cells* property, where is +some specifier space like 'gpio', 'clock', 'reset', etc. + +-map +^^^^^^^^^^^^^^^ + +Property: ``-map`` + +Value type: ```` encoded as an arbitrary number of +specifier mapping entries. + +Description: + + A *-map* is a property in a nexus node that bridges one + specifier domain with a set of parent specifier domains and describes + how specifiers in the child domain are mapped to their respective parent + domains. + + The map is a table where each row is a mapping entry + consisting of three components: *child specifier*, *specifier parent*, and + *parent specifier*. + + child specifier + The specifier of the child node being mapped. The number + of 32-bit cells required to specify this component is described by + the *#-cells* property of this nodeā€”the nexus node + containing the *-map* property. + + specifier parent + A single ** value that points to the specifier parent to + which the child domain is being mapped. + + parent specifier + The specifier in the parent domain. The number of 32-bit + cells required to specify this component is described by the + *#-cells* property of the specifier parent node. + + Lookups are performed on the mapping table by matching a specifier against + the child specifier in the map. Because some fields in the specifier may + not be relevant or need to be modified, a mask is applied before the lookup + is done. This mask is defined in the *-map-mask* property (see + section :ref:`sect-specifier-map-mask`). + + Similarly, when the specifier is mapped some fields in the unit specifier + may need to be kept unmodified and passed through from the child node to the + parent node. In this case, a *-map-pass-thru* property (see + section :ref:`sect-specifier-map-pass-thru`) may be specified to apply + a mask to the incoming specifier and copy any bits that match to the outgoing + unit specifier. + +.. _sect-specifier-map-mask: + +-map-mask +^^^^^^^^^^^^^^^^^^^^ + +Property: ``-map-mask`` + +Value type: ```` encoded as a bit mask + +Description: + + A *-map-mask* property may be specified for a nexus node. + This property specifies a mask that is applied to the incoming unit + specifier being looked up in the table specified in the *-map* + property. If this property is not specified, the mask is assumed to be + a mask with all bits set. + +.. _sect-specifier-map-pass-thru: + +-map-pass-thru +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Property: ``-map-pass-thru`` + +Value type: ```` encoded as a bit mask + +Description: + + A *-map-pass-thru* property may be specified for a nexus node. + This property specifies a mask that is applied to the incoming unit + specifier being looked up in the table specified in the *-map* + property. Any matching bits in the incoming unit specifier are copied over + to the outgoing specifier. If this property is not specified, the mask is + assumed to be a mask with no bits set. + +#-cells +^^^^^^^^^^^^^^^^^^ + +Property: ``#-cells`` + +Value type: ```` + +Description: + + The *#-cells* property defines the number of cells required to + encode a specifier for a domain. + +Specifier Mapping Example +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following shows the representation of a fragment of a devicetree with +two GPIO controllers and a sample specifier map for describing the +GPIO routing of a few gpios on both of the controllers through a connector +on a board to a device. The expansion device node is one one side of the +connector node and the SoC with the two GPIO controllers is on the other +side of the connector. + +.. _example-specifier-mapping: + +.. code-block:: dts + + soc { + soc_gpio1: gpio-controller1 { + #gpio-cells = <2>; + }; + + soc_gpio2: gpio-controller2 { + #gpio-cells = <2>; + }; + }; + + connector: connector { + #gpio-cells = <2>; + gpio-map = <0 0 &soc_gpio1 1 0>, + <1 0 &soc_gpio2 4 0>, + <2 0 &soc_gpio1 3 0>, + <3 0 &soc_gpio2 2 0>; + gpio-map-mask = <0xf 0x0>; + gpio-map-pass-thru = <0x0 0x1>; + }; + + expansion_device { + reset-gpios = <&connector 2 GPIO_ACTIVE_LOW>; + }; + + +Each row in the gpio-map table consists of three parts: a child unit +specifier, which is mapped to a *gpio-controller* +node with a parent specifier. + +* For example, the first row of the specifier-map table specifies the + mapping for GPIO 0 of the connector. The components of that row are shown + here + + | child specifier: ``0 0`` + | specifier parent: ``&soc_gpio1`` + | parent specifier: ``1 0`` + + * The child specifier is ``<0 0>``, which specifies GPIO 0 in the connector + with a *flags* field of ``0``. This takes two 32-bit cells as specified + by the *#gpio-cells* property of the connector node, which is the + child specifier domian. + + * The specifier parent is specified by a phandle which points to the + specifier parent of the connector, the first GPIO controller in the SoC. + + * The parent specifier is ``<1 0>``. The number of cells to + represent the gpio specifier (two cells) is determined by the + *#gpio-cells* property on the specifier parent, the soc_gpio1 + node. + + * The value ``<1 0>`` is a value specified by the device binding for + the GPIO controller. The value ``<1>`` specifies the + GPIO pin number on the GPIO controller to which GPIO 0 on the connector + is wired. The value ``<0>`` specifies the flags (active low, + active high, etc.). + +In this example, the *gpio-map-mask* property has a value of ``<0xf 0>``. +This mask is applied to a child unit specifier before performing a lookup in +the *gpio-map* table. Similarly, the *gpio-map-pass-thru* property has a value +of ``<0x0 0x1>``. This mask is applied to a child unit specifier when mapping +it to the parent unit specifier. Any bits set in the mask are cleared out of +the parent unit specifier and copied over from the child unit specifier +to the parent unit specifier. + +To perform a lookup of the connector's specifier source number for GPIO 2 +from the expansion device's reset-gpios property, the following steps would be +performed: + +* The child specifier forms the value + ``<2 GPIO_ACTIVE_LOW>``. + + * The specifier is encoding GPIO 2 with active low flags per the GPIO + binding. + +* The *gpio-map-mask* value ``<0xf 0x0>`` is applied, giving a + result of ``<0x2 0>``. + +* That result is looked up in the *gpio-map* table, which maps to + the parent specifier ``<3 0>`` and &soc_gpio1 *phandle*. + +* That *gpio-map-pass-thru* value ``<0x0 0x1>`` is applied to child specifier, + forming ``<0 GPIO_ACTIVE_LOW>`` which is then ORed with the parent + specifier ``<3 0>`` ANDed with the inverse of the pass-thru mask + ``<0xffffffff 0xffffffe>`` resulting in ``<3 GPIO_ACTIVE_LOW>``. + +* That specifier is combined with the mapped *phandle* &soc_gpio1 resulting + in ``<&soc_gpio1 3 GPIO_ACTIVE_LOW>``. From patchwork Fri Aug 11 15:42:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 109904 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1080553qge; Fri, 11 Aug 2017 08:43:12 -0700 (PDT) X-Received: by 10.98.89.22 with SMTP id n22mr16713523pfb.326.1502466192122; Fri, 11 Aug 2017 08:43:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502466192; cv=none; d=google.com; s=arc-20160816; b=r3PirYiQN/0hoQqffY7aDI2NCC0d1GcMz6l1O2xaNrjcJQmONR0wgnXNxuucpa1TII 8V2EG3F8sp1nxFUjpVC1aCeiwL8D4WrDIWwIr7OGJ91JAKd3lMqvRBkze7llF5S9IVmO n4ojopUsMxPTmIZ4I8pEe4M/WGykpLIbE9HU7ivQCv5yPjqw5K0PES963O2F96Qx7Usf zZNd0VOwBV696DHKCuf0GIw/veDCIOt9mcQdNgC+WRBEKbOHAUlKuWlo5xf5Lcaaa88F CmHm7+h6NubZnlihzIC5h77z8lhTYAhagQF5Vmh6l8s6dhrFlC6865HHRKVPapsDdHCP MR/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=YOKjLWkBn9ODrACp8poGDTiim6PDv8/YEoUb/jG9CUA=; b=r8RxZpKmBuHLbsK8bz4vbUGwLM3fX4cnsKZgDmMX27SC+nXTR3A4938kGeJHP1SmUn QoktjVB0Q6N9yMzL+2q050G+0/bbbcjt0cVIntOWysQUo+e5jGiUVZGdfU/NHNQgAZhB RKWAopW822w6uUkCMMcXec4z2Sl5GRjMWq8Kon0XNHiECncKVF1vqLhW3z2HPyo/5AG7 TU+8rlqo7lPiQtGdCB8z6BhMDyeC/jUzXSF+iiLl9gQE+RFA0mL6vuAi79GgDuucl16v UDVpZeNlGEv9nDVLJFZK1eeFxDEaQcXqyAhyFToPxebzmAPj1Rh3fCxDuubu+Tic4OwB a6zw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=gRlAi9cQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q75si675796pfq.132.2017.08.11.08.43.11; Fri, 11 Aug 2017 08:43:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=gRlAi9cQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753471AbdHKPnI (ORCPT + 25 others); Fri, 11 Aug 2017 11:43:08 -0400 Received: from mail-pf0-f174.google.com ([209.85.192.174]:36416 "EHLO mail-pf0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753267AbdHKPml (ORCPT ); Fri, 11 Aug 2017 11:42:41 -0400 Received: by mail-pf0-f174.google.com with SMTP id c28so17263288pfe.3 for ; Fri, 11 Aug 2017 08:42:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YOKjLWkBn9ODrACp8poGDTiim6PDv8/YEoUb/jG9CUA=; b=gRlAi9cQI+2AYD7Tv0O+lumqB1GcQZaCFhqwbekcoXgJB2jDI+zk5glR/dHwNFyfxC yO0nPGSG+HaqhI5MrTFnyDTPdbYgybYZT+nx7a/jsd3rf7AqtZDZ7j2OWeTgsS49/lqN VtQ7k4ZyOA6aoqmKz2ke3XVpRfHhkdFrLHAIE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YOKjLWkBn9ODrACp8poGDTiim6PDv8/YEoUb/jG9CUA=; b=jAFw5QJQUdoJsSW32lEQ7rnrJlSfpYvqECcHlMJK6WcWrL+e2XIXoGi0RLH7pdnblL l4t6noo1lsbcbKlfbJTmRiyHh2Zpc79wUNyM/2UPTY9KpONapX31v5Q+bYmO1rMlyprl gH6VfnoWC+3bAxOVDEx+xoyR4VwYgrpBrBTeXXVeGL6L/dKKd3bGGUJB+EYMb6lQQHVW IcjRGWcNwjk4WevTVCU0eqIGrloOz1Ada1z4AXamAtvztEHsQKiCncKBrsJ7CuG/41vg Osxqx2XD5T5EMcEIDCQ+TbULMWUuMvFneq8wWjOpepPAJghiIYY0GK2qaBKl/mmBr7X+ 1TFw== X-Gm-Message-State: AHYfb5gTQqhq84PiLwhcMrcwXobOFCV6X/us5SS5PjhZTc2w2Vw4Icp3 Q+cIyKzHjkLC1MhM X-Received: by 10.99.167.11 with SMTP id d11mr16252895pgf.182.1502466160632; Fri, 11 Aug 2017 08:42:40 -0700 (PDT) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id a63sm2351071pfc.165.2017.08.11.08.42.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Aug 2017 08:42:40 -0700 (PDT) From: Stephen Boyd To: Rob Herring , Frank Rowand Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Russell King - ARM Linux , devicetree-spec@vger.kernel.org, Pantelis Antoniou , Linus Walleij , Mark Brown Subject: [PATCH v4 2/4] of: Support parsing phandle argument lists through a nexus node Date: Fri, 11 Aug 2017 08:42:34 -0700 Message-Id: <20170811154236.12891-3-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.14.GIT In-Reply-To: <20170811154236.12891-1-stephen.boyd@linaro.org> References: <20170811154236.12891-1-stephen.boyd@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Platforms like 96boards have a standardized connector/expansion slot that exposes signals like GPIOs to expansion boards in an SoC agnostic way. We'd like the DT overlays for the expansion boards to be written once without knowledge of the SoC on the other side of the connector. This avoids the unscalable combinatorial explosion of a different DT overlay for each expansion board and SoC pair. We need a way to describe the GPIOs routed through the connector in an SoC agnostic way. Let's introduce nexus property parsing into the OF core to do this. This is largely based on the interrupt nexus support we already have. This allows us to remap a phandle list in a consumer node (e.g. reset-gpios) through a connector in a generic way (e.g. via gpio-map). Do this in a generic routine so that we can remap any sort of variable length phandle list. Taking GPIOs as an example, the connector would be a GPIO nexus, supporting the remapping of a GPIO specifier space to multiple GPIO providers on the SoC. DT would look as shown below, where 'soc_gpio1' and 'soc_gpio2' are inside the SoC, 'connector' is an expansion port where boards can be plugged in, and 'expansion_device' is a device on the expansion board. soc { soc_gpio1: gpio-controller1 { #gpio-cells = <2>; }; soc_gpio2: gpio-controller2 { #gpio-cells = <2>; }; }; connector: connector { #gpio-cells = <2>; gpio-map = <0 0 &soc_gpio1 1 0>, <1 0 &soc_gpio2 4 0>, <2 0 &soc_gpio1 3 0>, <3 0 &soc_gpio2 2 0>; gpio-map-mask = <0xf 0x0>; gpio-map-pass-thru = <0x0 0x1> }; expansion_device { reset-gpios = <&connector 2 GPIO_ACTIVE_LOW>; }; The GPIO core would use of_parse_phandle_with_args_map() instead of of_parse_phandle_with_args() and arrive at the same type of result, a phandle and argument list. The difference is that the phandle and arguments will be remapped through the nexus node to the underlying SoC GPIO controller node. In the example above, we would remap 'reset-gpios' from <&connector 2 GPIO_ACTIVE_LOW> to <&soc_gpio1 3 GPIO_ACTIVE_LOW>. Cc: Pantelis Antoniou Cc: Linus Walleij Cc: Mark Brown Signed-off-by: Stephen Boyd --- drivers/of/base.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of.h | 12 ++++ 2 files changed, 196 insertions(+) -- 2.7.4 diff --git a/drivers/of/base.c b/drivers/of/base.c index 686628d1dfa6..60f15bf56534 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1366,6 +1366,190 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na EXPORT_SYMBOL(of_parse_phandle_with_args); /** + * of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it + * @np: pointer to a device tree node containing a list + * @list_name: property name that contains a list + * @stem_name: stem of property names that specify phandles' arguments count + * @index: index of a phandle to parse out + * @out_args: optional pointer to output arguments structure (will be filled) + * + * This function is useful to parse lists of phandles and their arguments. + * Returns 0 on success and fills out_args, on error returns appropriate errno + * value. The difference between this function and of_parse_phandle_with_args() + * is that this API remaps a phandle if the node the phandle points to has + * a <@stem_name>-map property. + * + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * + * Example: + * + * phandle1: node1 { + * #list-cells = <2>; + * } + * + * phandle2: node2 { + * #list-cells = <1>; + * } + * + * phandle3: node3 { + * #list-cells = <1>; + * list-map = <0 &phandle2 3>, + * <1 &phandle2 2>, + * <2 &phandle1 5 1>; + * list-map-mask = <0x3>; + * }; + * + * node4 { + * list = <&phandle1 1 2 &phandle3 0>; + * } + * + * To get a device_node of the `node2' node you may call this: + * of_parse_phandle_with_args(node4, "list", "list", 1, &args); + */ +int of_parse_phandle_with_args_map(const struct device_node *np, + const char *list_name, + const char *stem_name, + int index, struct of_phandle_args *out_args) +{ + char *cells_name, *map_name = NULL, *mask_name = NULL; + char *pass_name = NULL; + struct device_node *cur, *new = NULL; + const __be32 *map, *mask, *pass; + static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 }; + static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 }; + __be32 initial_match_array[MAX_PHANDLE_ARGS]; + const __be32 *match_array = initial_match_array; + int i, ret, map_len, match; + u32 list_size, new_size; + + if (index < 0) + return -EINVAL; + + cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name); + if (!cells_name) + return -ENOMEM; + + ret = -ENOMEM; + map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name); + if (!map_name) + goto free; + + mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name); + if (!mask_name) + goto free; + + pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name); + if (!pass_name) + goto free; + + ret = __of_parse_phandle_with_args(np, list_name, cells_name, 0, index, + out_args); + if (ret) + goto free; + + /* Get the #-cells property */ + cur = out_args->np; + ret = of_property_read_u32(cur, cells_name, &list_size); + if (ret < 0) + goto put; + + /* Precalculate the match array - this simplifies match loop */ + for (i = 0; i < list_size; i++) + initial_match_array[i] = cpu_to_be32(out_args->args[i]); + + ret = -EINVAL; + while (cur) { + /* Get the -map property */ + map = of_get_property(cur, map_name, &map_len); + if (!map) { + ret = 0; + goto free; + } + map_len /= sizeof(u32); + + /* Get the -map-mask property (optional) */ + mask = of_get_property(cur, mask_name, NULL); + if (!mask) + mask = dummy_mask; + /* Iterate through -map property */ + match = 0; + while (map_len > (list_size + 1) && !match) { + /* Compare specifiers */ + match = 1; + for (i = 0; i < list_size; i++, map_len--) + match &= !((match_array[i] ^ *map++) & mask[i]); + + of_node_put(new); + new = of_find_node_by_phandle(be32_to_cpup(map)); + map++; + map_len--; + + /* Check if not found */ + if (!new) + goto put; + + if (!of_device_is_available(new)) + match = 0; + + ret = of_property_read_u32(new, cells_name, &new_size); + if (ret) + goto put; + + /* Check for malformed properties */ + if (WARN_ON(new_size > MAX_PHANDLE_ARGS)) + goto put; + if (map_len < new_size) + goto put; + + /* Move forward by new node's #-cells amount */ + map += new_size; + map_len -= new_size; + } + if (!match) + goto put; + + /* Get the -map-pass-thru property (optional) */ + pass = of_get_property(cur, pass_name, NULL); + if (!pass) + pass = dummy_pass; + + /* + * Successfully parsed a -map translation; copy new + * specifier into the out_args structure, keeping the + * bits specified in -map-pass-thru. + */ + match_array = map - new_size; + for (i = 0; i < new_size; i++) { + __be32 val = *(map - new_size + i); + + if (i < list_size) { + val &= ~pass[i]; + val |= cpu_to_be32(out_args->args[i]) & pass[i]; + } + + out_args->args[i] = be32_to_cpu(val); + } + out_args->args_count = list_size = new_size; + /* Iterate again with new provider */ + out_args->np = new; + of_node_put(cur); + cur = new; + } +put: + of_node_put(cur); + of_node_put(new); +free: + kfree(mask_name); + kfree(map_name); + kfree(cells_name); + kfree(pass_name); + + return ret; +} +EXPORT_SYMBOL(of_parse_phandle_with_args_map); + +/** * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list * @np: pointer to a device tree node containing a list * @list_name: property name that contains a list diff --git a/include/linux/of.h b/include/linux/of.h index 23bf46ee8686..92fd032b76c7 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -362,6 +362,9 @@ extern struct device_node *of_parse_phandle(const struct device_node *np, extern int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name, int index, struct of_phandle_args *out_args); +extern int of_parse_phandle_with_args_map(const struct device_node *np, + const char *list_name, const char *stem_name, int index, + struct of_phandle_args *out_args); extern int of_parse_phandle_with_fixed_args(const struct device_node *np, const char *list_name, int cells_count, int index, struct of_phandle_args *out_args); @@ -764,6 +767,15 @@ static inline int of_parse_phandle_with_args(const struct device_node *np, return -ENOSYS; } +static inline int of_parse_phandle_with_args_map(const struct device_node *np, + const char *list_name, + const char *stem_name, + int index, + struct of_phandle_args *out_args) +{ + return -ENOSYS; +} + static inline int of_parse_phandle_with_fixed_args(const struct device_node *np, const char *list_name, int cells_count, int index, struct of_phandle_args *out_args) From patchwork Fri Aug 11 15:42:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 109902 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1080034qge; Fri, 11 Aug 2017 08:42:48 -0700 (PDT) X-Received: by 10.84.137.129 with SMTP id 1mr18175836pln.251.1502466168499; Fri, 11 Aug 2017 08:42:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502466168; cv=none; d=google.com; s=arc-20160816; b=yMuiZkpy6eyKSNF7yJY82PYfW8k3y5gL3K6yAKxifAIWBGYkAuznmY1kOOq4qGdnGZ ys390p4hZECkaCshyleAOqpax6ZvzcThFsG/NVo7z9QSzg2dK5/xqy4JW5nG3Ofzf87S 7bhDcKFG+Swdx9QObe/RJZegJnJ2J5ZD5F3CEJWMF5zSnmfrPL9p0jmd/P35EmSYSvft Ex2Q6BOm2XXA78QAjMGfl5cdQzB20KCT+O5MsESec5O14GBdH9KWnjqmccHIG8ZM3DTO H8VElHix223bePFllIDiV/nmwxQ31mNqhsGd/lKXsoAwZheRFzn1lfi++KpTnEtVokdV KRsQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=KUxhc8bIg8uaGWXkFQ0N7RCA4kcR3JQmucJTMyg81rM=; b=PBFS9eKFtpqGHY1oHcPVYWhFTx1KDM4XoFs2sSJtk8NoCsrstFyz3lNtRgJq/k3wPd ppTsYXCqN5afPqCjZcotuTz4HOF2DRLGptGSre8ieCIiIBF15YAAkMKxc4EBPrcGFfkj qJCCzZA+KKCreah1CFsmSvNBW19eBEo+waS1bmUIj+tmK4xnBFwFSTyemx3DWLOiDk6y 9Pwr+a+N4OvmKsIKRC1Im1Ybyl0EgsZ67Y9wUKLGKj9t3SeQFb2tDDkQG7t7dnN6FAAD 88Zm2EQHvSZqSa+Yx2iDuP4VgYidNjYR5BMVMRJnNIvS77UlmdkEk2kt8hJkZPXXJCLs P8jQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kec54pTF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g6si636516pgf.799.2017.08.11.08.42.48; Fri, 11 Aug 2017 08:42:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kec54pTF; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752949AbdHKPmp (ORCPT + 25 others); Fri, 11 Aug 2017 11:42:45 -0400 Received: from mail-pf0-f169.google.com ([209.85.192.169]:36422 "EHLO mail-pf0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752631AbdHKPmm (ORCPT ); Fri, 11 Aug 2017 11:42:42 -0400 Received: by mail-pf0-f169.google.com with SMTP id c28so17263507pfe.3 for ; Fri, 11 Aug 2017 08:42:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=KUxhc8bIg8uaGWXkFQ0N7RCA4kcR3JQmucJTMyg81rM=; b=kec54pTFWeMw4kBcPIBEFl2w8XX3RSOWcnhp7Zd6TsWFKi/RBRG27Fxo8By35To8nd mWwdSAc/hMugWaRtBhyGJl3vvcTeR0Bf1Pj8wsKU65c8vuYoPPWHiATLbYdxR5OMpRwH vTppOUHVLRcUzBvFv3ACCSMFX2bRgBktmcoME= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=KUxhc8bIg8uaGWXkFQ0N7RCA4kcR3JQmucJTMyg81rM=; b=Nqt4EhXGKZVWMbqDt1TV5rNHoPt8/aCdeFKUPJbMLjXjRUy0stKfc20Hn+Sn0KQvBO lU6oGRdc1/uaiVvoNpi+VLGeIp2UFTe/Fvok6GA+5EkRBPVA1kRhVci3OOFoZnu3rCdi ICCuDT1kg9EDngFx9ViNnKGn5uCGfcd7yNpR4Qw2ylLzM2aBguzKUhFgyaS/iVMExV0v d8GuUDQoa4zalba+jkYaYl0q53xmLXiVV+swkcLqw/9jzYAl1iLEEyUZed4vDNHEvJE5 n/uiUzwtNM/7lNPgUThLG2TgsyX+4+aOGqB1vKxMiTnDKGNS0B+WE/DN2b19e7HZDO1r RZlw== X-Gm-Message-State: AHYfb5gyqp64dnJ905bbu3xciBNBN9MWrOLWSFRZAbfAi5O0VMyUoaAq NUIiTKeaOQ078GYF X-Received: by 10.99.109.207 with SMTP id i198mr15600515pgc.375.1502466162057; Fri, 11 Aug 2017 08:42:42 -0700 (PDT) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id a63sm2351071pfc.165.2017.08.11.08.42.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Aug 2017 08:42:41 -0700 (PDT) From: Stephen Boyd To: Rob Herring , Frank Rowand Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Russell King - ARM Linux , devicetree-spec@vger.kernel.org, Pantelis Antoniou , Linus Walleij , Mark Brown Subject: [PATCH v4 3/4] of: unittest: Add phandle remapping test Date: Fri, 11 Aug 2017 08:42:35 -0700 Message-Id: <20170811154236.12891-4-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.14.GIT In-Reply-To: <20170811154236.12891-1-stephen.boyd@linaro.org> References: <20170811154236.12891-1-stephen.boyd@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Test the functionality of of_parse_phandle_with_args_map(). Cc: Pantelis Antoniou Cc: Linus Walleij Cc: Mark Brown Signed-off-by: Stephen Boyd --- drivers/of/unittest-data/testcases.dts | 11 +++ drivers/of/unittest-data/tests-phandle.dtsi | 25 ++++++ drivers/of/unittest.c | 120 ++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) -- 2.7.4 diff --git a/drivers/of/unittest-data/testcases.dts b/drivers/of/unittest-data/testcases.dts index 12f7c3d649c8..173b96f39cd0 100644 --- a/drivers/of/unittest-data/testcases.dts +++ b/drivers/of/unittest-data/testcases.dts @@ -26,12 +26,23 @@ / { __local_fixups__ { testcase-data { phandle-tests { + provider4 { + phandle-map = <0x00000008 0x00000018 + 0x00000024 0x0000003c + 0x00000050 0x00000064>; + }; consumer-a { phandle-list = <0x00000000 0x00000008 0x00000018 0x00000028 0x00000034 0x00000038>; phandle-list-bad-args = <0x00000000 0x0000000c>; }; + consumer-b { + phandle-list = <0x00000000 0x00000008 + 0x00000018 0x00000024 + 0x00000030 0x00000034>; + phandle-list-bad-args = <0x00000000 0x0000000c>; + }; }; interrupts { intmap0 { diff --git a/drivers/of/unittest-data/tests-phandle.dtsi b/drivers/of/unittest-data/tests-phandle.dtsi index 5b1527e8a7fb..59e297f497d1 100644 --- a/drivers/of/unittest-data/tests-phandle.dtsi +++ b/drivers/of/unittest-data/tests-phandle.dtsi @@ -25,6 +25,18 @@ #phandle-cells = <3>; }; + provider4: provider4 { + #phandle-cells = <2>; + phandle-map = <0 1 &provider1 3>, + <4 0 &provider0>, + <16 5 &provider3 3 5 0>, + <200 8 &provider2 23 6>, + <19 0 &provider2 15 0>, + <2 3 &provider3 2 5 3>; + phandle-map-mask = <0xff 0xf>; + phandle-map-pass-thru = <0x0 0xf0>; + }; + consumer-a { phandle-list = <&provider1 1>, <&provider2 2 0>, @@ -43,6 +55,19 @@ unterminated-string = [40 41 42 43]; unterminated-string-list = "first", "second", [40 41 42 43]; }; + + consumer-b { + phandle-list = <&provider1 1>, + <&provider4 2 3>, + <0>, + <&provider4 4 0x100>, + <&provider4 0 0x61>, + <&provider0>, + <&provider4 19 0x20>; + phandle-list-bad-phandle = <12345678 0 0>; + phandle-list-bad-args = <&provider2 1 0>, + <&provider4 0>; + }; }; }; }; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 0107fc680335..c6091d1e55de 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -443,6 +443,125 @@ static void __init of_unittest_parse_phandle_with_args(void) unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); } +static void __init of_unittest_parse_phandle_with_args_map(void) +{ + struct device_node *np, *p0, *p1, *p2, *p3; + struct of_phandle_args args; + int i, rc; + + np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-b"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + p0 = of_find_node_by_path("/testcase-data/phandle-tests/provider0"); + if (!p0) { + pr_err("missing testcase data\n"); + return; + } + + p1 = of_find_node_by_path("/testcase-data/phandle-tests/provider1"); + if (!p1) { + pr_err("missing testcase data\n"); + return; + } + + p2 = of_find_node_by_path("/testcase-data/phandle-tests/provider2"); + if (!p2) { + pr_err("missing testcase data\n"); + return; + } + + p3 = of_find_node_by_path("/testcase-data/phandle-tests/provider3"); + if (!p3) { + pr_err("missing testcase data\n"); + return; + } + + rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells"); + unittest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc); + + for (i = 0; i < 8; i++) { + bool passed = true; + + rc = of_parse_phandle_with_args_map(np, "phandle-list", + "phandle", i, &args); + + /* Test the values from tests-phandle.dtsi */ + switch (i) { + case 0: + passed &= !rc; + passed &= (args.np == p1); + passed &= (args.args_count == 1); + passed &= (args.args[0] == 1); + break; + case 1: + passed &= !rc; + passed &= (args.np == p3); + passed &= (args.args_count == 3); + passed &= (args.args[0] == 2); + passed &= (args.args[1] == 5); + passed &= (args.args[2] == 3); + break; + case 2: + passed &= (rc == -ENOENT); + break; + case 3: + passed &= !rc; + passed &= (args.np == p0); + passed &= (args.args_count == 0); + break; + case 4: + passed &= !rc; + passed &= (args.np == p1); + passed &= (args.args_count == 1); + passed &= (args.args[0] == 3); + break; + case 5: + passed &= !rc; + passed &= (args.np == p0); + passed &= (args.args_count == 0); + break; + case 6: + passed &= !rc; + passed &= (args.np == p2); + passed &= (args.args_count == 2); + passed &= (args.args[0] == 15); + passed &= (args.args[1] == 0x20); + break; + case 7: + passed &= (rc == -ENOENT); + break; + default: + passed = false; + } + + unittest(passed, "index %i - data error on node %s rc=%i\n", + i, args.np->full_name, rc); + } + + /* Check for missing list property */ + rc = of_parse_phandle_with_args_map(np, "phandle-list-missing", + "phandle", 0, &args); + unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc); + + /* Check for missing cells,map,mask property */ + rc = of_parse_phandle_with_args_map(np, "phandle-list", + "phandle-missing", 0, &args); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + + /* Check for bad phandle in list */ + rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle", + "phandle", 0, &args); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); + + /* Check for incorrectly formed argument list */ + rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args", + "phandle", 1, &args); + unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc); +} + static void __init of_unittest_property_string(void) { const char *strings[4]; @@ -2326,6 +2445,7 @@ static int __init of_unittest(void) of_unittest_find_node_by_name(); of_unittest_dynamic(); of_unittest_parse_phandle_with_args(); + of_unittest_parse_phandle_with_args_map(); of_unittest_printf(); of_unittest_property_string(); of_unittest_property_copy();