From patchwork Fri May 3 14:20:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652950 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A910153BCB; Fri, 3 May 2024 14:21:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746080; cv=none; b=Tysru9FD+8nTetfX2HovI9QC4NZ12EEk6eOHg5hNsCpKrVFyLS+C48gwaesu9dE7KPL5a3kMwF77OpNrp9frVZQycPTxBtLpmDcwenvKBNYYwuO04h4f/5f6vdl+Tp+NDacjZ95VSxZjKneZZmQe1DVjPsaGIpUTNcv0vWHvHMw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746080; c=relaxed/simple; bh=gXnfQAgrZrJmKu4c7d9//TfZQIsdHFJrk0CW6RdsEbo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UY1IfoqeplASERUy4q/9tPMfg/shF7lJywSx4hrNSvOfz6V+13OeR2OwC1lrSeB6Ggga2R1eT7vEMsdugceFY/XfW94/j7esrQHlJ2lHL+Y82gdDjqqRgnqJhuxiocXwIAfFUbWtQlRGWU6hl7jhKJcXjF9aD/DKz5N6DyI3x8k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=auFdrfyc; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="auFdrfyc" Received: by mail.gandi.net (Postfix) with ESMTPSA id 4ACD2E0011; Fri, 3 May 2024 14:21:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746070; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YSit5l5HNYYTyzvi3BDpZSbmAXfYnPnJDQ+PPWXph2M=; b=auFdrfycfJlDBfQJRT7H48CB+saPXuS6J8hrJ1OWU5Q8N6RVx3dQROly6uFI6Id6j/nCEu BEQuFyl2ftXapbylh9aAQe63F6kQJmcAOYS084cMNI3581UvJFu03DRSEHg+cmS60xWVe+ q0YCMaROy0G9crzAhmb+hTZ0T8cTBk9pc30y06eKs/aq6/iRHFnObPeu/EZQng3JypPU7A Mi6/NAM5AFEQg3JVirSb+OtCICz4fwx/8XgOWMfODD1tmgxOZzsJg4NllT2QrqHcLE/wcK NN6lMp97LG+tfghLUK0b7gafQDh+Fq3XbGRMM88vKo8leVZM5neTUC/0T+CL/g== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:46 +0200 Subject: [PATCH v2 01/11] dt-bindings: clock: mobileye,eyeq5-clk: drop bindings Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-1-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Switch from sub-nodes in system-controller for each functionality to a single node representing the entire OLB instance. dt-bindings is unnecessary and soc/mobileye/mobileye,eyeq5-olb.yaml will inherit all properties. Signed-off-by: Théo Lebrun --- .../bindings/clock/mobileye,eyeq5-clk.yaml | 51 ---------------------- 1 file changed, 51 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml b/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml deleted file mode 100644 index 2d4f2cde1e58..000000000000 --- a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml +++ /dev/null @@ -1,51 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/clock/mobileye,eyeq5-clk.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Mobileye EyeQ5 clock controller - -description: - The EyeQ5 clock controller handles 10 read-only PLLs derived from the main - crystal clock. It also exposes one divider clock, a child of one of the PLLs. - Its registers live in a shared region called OLB. - -maintainers: - - Grégory Clement - - Théo Lebrun - - Vladimir Kondratiev - -properties: - compatible: - const: mobileye,eyeq5-clk - - reg: - maxItems: 2 - - reg-names: - items: - - const: plls - - const: ospi - - "#clock-cells": - const: 1 - - clocks: - maxItems: 1 - description: - Input parent clock to all PLLs. Expected to be the main crystal. - - clock-names: - items: - - const: ref - -required: - - compatible - - reg - - reg-names - - "#clock-cells" - - clocks - - clock-names - -additionalProperties: false From patchwork Fri May 3 14:20:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652952 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 85C4D154BF3; Fri, 3 May 2024 14:21:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746082; cv=none; b=p8nIPv2rpo9GYj1i/s+S0PDhvWteq6d7aX1p9zVL2MI0/PMnjiJ11z2JNPLBsEj2PmjOsosWTdLZfszDBVHSmUXhgPDr8lfaOWYO6LF+Se4xe2yjME95Zwm0q6mE9JFN8ThXFGcpUnReQrJc1RVZQabyrNT0zOsGmcdTdJRAyiI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746082; c=relaxed/simple; bh=/8WKSj8z+PwGRoB7v9CKzRHvu5T8bI/rz8wOFPwwC9Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=F8qWryE8rt6PizehNBnslBowcfgR/cSLsV+pTBM9RQU/Cpk7p9jGdqaZUJQQbzvrJgLWmX6/abpERWo14sfEGZlhgphOzv8NTWNwY/JQLdfXgymW9jreeKyexyGwsEOAsokDQ4Sy31jFkSNxx3tCKe7O1epKoWH0TTBJREeNTSA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=hi5Rgki0; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="hi5Rgki0" Received: by mail.gandi.net (Postfix) with ESMTPSA id 2752AE0008; Fri, 3 May 2024 14:21:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746071; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AxYpvnPVBmTt3NbX4kfm6Echib8luItPMHNWvwB5PdM=; b=hi5Rgki0kjWKWubEKXyaPKioINsk1mPjF6oFXi7CO28GP82RL2pVkYlspOxnGRKD8kjQAS TmpifjNV4e5zrR0EROYtkg+NnmtWfpwRUhw254DkN1QERqp+6h5FFzM/GAyvBrULvQIk16 aYj9dr7LuAEN8WZ9UHHerUldNCAtU7CFuhweO1Y//OcPHUiYDA6Dl2g9yB45ZfeuJRFf9h QHW6/WK6lHueVY/0YDSZJe/WDOSV6aulMHFdC1Ek//AUDXYHiulXjm/NOcLSR3itSB7ckx MWcSq4mpPgJCe5Qjyn8qW6XLfk4ggwGPh3QM6htr/oMi9nq/QdfCrKRtFGePCw== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:47 +0200 Subject: [PATCH v2 02/11] dt-bindings: clock: mobileye,eyeq5-reset: drop bindings Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-2-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Switch from sub-nodes in system-controller for each functionality to a single node representing the entire OLB instance. dt-bindings is unnecessary and soc/mobileye/mobileye,eyeq5-olb.yaml will inherit all properties. Signed-off-by: Théo Lebrun --- .../bindings/reset/mobileye,eyeq5-reset.yaml | 43 ---------------------- 1 file changed, 43 deletions(-) diff --git a/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml b/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml deleted file mode 100644 index 062b4518347b..000000000000 --- a/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/reset/mobileye,eyeq5-reset.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Mobileye EyeQ5 reset controller - -description: - The EyeQ5 reset driver handles three reset domains. Its registers live in a - shared region called OLB. - -maintainers: - - Grégory Clement - - Théo Lebrun - - Vladimir Kondratiev - -properties: - compatible: - const: mobileye,eyeq5-reset - - reg: - maxItems: 3 - - reg-names: - items: - - const: d0 - - const: d1 - - const: d2 - - "#reset-cells": - const: 2 - description: - The first cell is the domain (0 to 2 inclusive) and the second one is the - reset index inside that domain. - -required: - - compatible - - reg - - reg-names - - "#reset-cells" - -additionalProperties: false From patchwork Fri May 3 14:20:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652954 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 33D171552ED; Fri, 3 May 2024 14:21:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746083; cv=none; b=YWLxQJ9W9zqUDiRgx56QDrSGJozfLu/3jCpYXHT6uaB2bCADIapelMILzZ7Xcw1M58akIxiz9Yq6bbel1eV97FyWBcK7LyNraHs886p6w6wJx4AeV/47B7I3f2ghgWvV4+STuVUMT4SV3H4sYYg8WiyT+hKbOjbMCGWqcAhOQXc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746083; c=relaxed/simple; bh=YjbWlqN7MZ0jAzt3BcPRtlF5vCkg+Oj6MdEgyNmmhMo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EsoaHcfDLUcTtT9PV1tvDMw+F/3tVaP4bryYFWQgjF6eS+BLPa6YRTfzsmCwLi8CKjOEkckeVWywUXUUon63Zk65+mgPhIau9BxQIAYwtcnkvJh5fGUhs+h0EsbfCZ+0qZNq38lc3RqjrcvGFVsy4+PX53V64O43vqp7VJI/tXg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=meO235jW; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="meO235jW" Received: by mail.gandi.net (Postfix) with ESMTPSA id 11ADCE0016; Fri, 3 May 2024 14:21:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746071; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=8o8TsLYJjK8/HyhFOEmPWrSGUV0TlbVKMYvkZs9m9MI=; b=meO235jW1IBB7PsnF8SE5rba0mLtPqmIn9PJrz0t4Iz1IVeqIlPDQpiOo7nGVpBUk4obwZ pfBzYtid/qVTaxHXCMZroO6z/N1yJcYpeUB/xG46O4N4kfY3N1KjTBYAWh8YeqIbBROtF2 ptLL0hvsoz8i7bb+WrH66Ova1JaqxQIQmh1oFVzjttg9icWTP+AFLsKPWnoOrC2R7bwHjc bg/aoRZLiHTIavOfxy5oM4lTZIDbBSgvASjJ4dd4DnzRbWaWjIUSZylqUP9aqf/b2olyYo qdS84Azy0TBI6VCsFroqhm/syKaWmOVyZ2i+6adpwfJOxJwNK5d+g+4JPuV6Dg== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:48 +0200 Subject: [PATCH v2 03/11] dt-bindings: soc: mobileye: add EyeQ OLB system controller Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-3-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Add documentation to describe the "Other Logic Block" system-controller. It deals with three platforms: EyeQ5, EyeQ6L and EyeQ6H. First two have a single instance, whereas EyeQ6H has seven named instances. Features provided are: - Clocks, children to main crystal. Some PLLs and divider clocks. - Resets. EyeQ6H central, south, DDR0 and DDR1 do not have resets. - Pinctrl. Only EyeQ5 has such feature. Those are NOT the only registers exposed in OLB system-controllers! Many individual registers, related to IP block integration, can be found. We simplify devicetree references to OLB in two ways: - Compatibles exposing a single clock do not ask for a index argument. - Compatibles exposing a single reset domain do not ask for a domain index, only a reset index. About pinctrl subnodes: all pins have two functionality, either GPIO or something-else. The latter is pin dependent, we express constraints using many if-then. Signed-off-by: Théo Lebrun --- .../bindings/soc/mobileye/mobileye,eyeq5-olb.yaml | 375 +++++++++++++++++++++ MAINTAINERS | 2 + include/dt-bindings/clock/mobileye,eyeq5-clk.h | 21 ++ 3 files changed, 398 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml new file mode 100644 index 000000000000..bbd75b81166e --- /dev/null +++ b/Documentation/devicetree/bindings/soc/mobileye/mobileye,eyeq5-olb.yaml @@ -0,0 +1,375 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/mobileye/mobileye,eyeq5-olb.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mobileye EyeQ SoC system controller + +maintainers: + - Grégory Clement + - Théo Lebrun + - Vladimir Kondratiev + +description: + OLB ("Other Logic Block") is a hardware block grouping smaller blocks. Clocks, + resets, pinctrl are being handled from here. EyeQ5 and EyeQ6L host a single + instance. EyeQ6H hosts seven instances. + +properties: + compatible: + items: + - enum: + - mobileye,eyeq5-olb + - mobileye,eyeq6l-olb + - mobileye,eyeq6h-acc-olb + - mobileye,eyeq6h-central-olb + - mobileye,eyeq6h-east-olb + - mobileye,eyeq6h-west-olb + - mobileye,eyeq6h-south-olb + - mobileye,eyeq6h-ddr0-olb + - mobileye,eyeq6h-ddr1-olb + - const: syscon + - const: simple-mfd + + reg: + maxItems: 1 + + '#reset-cells': + description: + First cell is domain and optional if compatible has a single reset domain. + Second cell is reset index inside that domain. + enum: [ 1, 2 ] + + '#clock-cells': + description: + Cell is clock index. Optional if compatible has a single clock. + enum: [ 0, 1 ] + + clocks: + maxItems: 1 + description: + Input parent clock to all PLLs. Expected to be the main crystal. + + clock-names: + const: ref + +patternProperties: + '-pins?$': + type: object + description: Pin muxing configuration. + $ref: /schemas/pinctrl/pinmux-node.yaml# + additionalProperties: false + properties: + pins: true + function: + enum: [gpio, + # Bank A + timer0, timer1, timer2, timer5, uart0, uart1, can0, can1, spi0, + spi1, refclk0, + # Bank B + timer3, timer4, timer6, uart2, can2, spi2, spi3, mclk0] + bias-disable: true + bias-pull-down: true + bias-pull-up: true + drive-strength: true + required: + - pins + - function + allOf: + - if: + properties: + function: + const: gpio + then: + properties: + pins: + items: # PA0 - PA28, PB0 - PB22 + pattern: '^(P(A|B)1?[0-9]|PA2[0-8]|PB2[0-2])$' + - if: + properties: + function: + const: timer0 + then: + properties: + pins: + items: + enum: [PA0, PA1] + - if: + properties: + function: + const: timer1 + then: + properties: + pins: + items: + enum: [PA2, PA3] + - if: + properties: + function: + const: timer2 + then: + properties: + pins: + items: + enum: [PA4, PA5] + - if: + properties: + function: + const: timer5 + then: + properties: + pins: + items: + enum: [PA6, PA7, PA8, PA9] + - if: + properties: + function: + const: uart0 + then: + properties: + pins: + items: + enum: [PA10, PA11] + - if: + properties: + function: + const: uart1 + then: + properties: + pins: + items: + enum: [PA12, PA13] + - if: + properties: + function: + const: can0 + then: + properties: + pins: + items: + enum: [PA14, PA15] + - if: + properties: + function: + const: can1 + then: + properties: + pins: + items: + enum: [PA16, PA17] + - if: + properties: + function: + const: spi0 + then: + properties: + pins: + items: + enum: [PA18, PA19, PA20, PA21, PA22] + - if: + properties: + function: + const: spi1 + then: + properties: + pins: + items: + enum: [PA23, PA24, PA25, PA26, PA27] + - if: + properties: + function: + const: refclk0 + then: + properties: + pins: + items: + enum: [PA28] + - if: + properties: + function: + const: timer3 + then: + properties: + pins: + items: + enum: [PB0, PB1] + - if: + properties: + function: + const: timer4 + then: + properties: + pins: + items: + enum: [PB2, PB3] + - if: + properties: + function: + const: timer6 + then: + properties: + pins: + items: + enum: [PB4, PB5, PB6, PB7] + - if: + properties: + function: + const: uart2 + then: + properties: + pins: + items: + enum: [PB8, PB9] + - if: + properties: + function: + const: can2 + then: + properties: + pins: + items: + enum: [PB10, PB11] + - if: + properties: + function: + const: spi2 + then: + properties: + pins: + items: + enum: [PB12, PB13, PB14, PB15, PB16] + - if: + properties: + function: + const: spi3 + then: + properties: + pins: + items: + enum: [PB17, PB18, PB19, PB20, PB21] + - if: + properties: + function: + const: mclk0 + then: + properties: + pins: + items: + enum: [PB22] + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + +additionalProperties: false + +allOf: + # Compatibles exposing a single reset domain. + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq6h-acc-olb + - mobileye,eyeq6h-east-olb + - mobileye,eyeq6h-west-olb + then: + properties: + '#reset-cells': + const: 1 + required: + - '#reset-cells' + + # Compatibles exposing two reset domains. + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq5-olb + - mobileye,eyeq6l-olb + then: + properties: + '#reset-cells': + const: 2 + required: + - '#reset-cells' + + # Compatibles not exposing resets. + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq6h-central-olb + - mobileye,eyeq6h-south-olb + - mobileye,eyeq6h-ddr0-olb + - mobileye,eyeq6h-ddr1-olb + then: + properties: + '#reset-cells': false + + # Compatibles exposing a single clock. + - if: + properties: + compatible: + contains: + enum: + - mobileye,eyeq6h-central-olb + - mobileye,eyeq6h-east-olb + - mobileye,eyeq6h-west-olb + - mobileye,eyeq6h-ddr0-olb + - mobileye,eyeq6h-ddr1-olb + then: + properties: + '#clock-cells': + const: 0 + else: + properties: + '#clock-cells': + const: 1 + + # Only EyeQ5 has pinctrl in OLB. + - if: + not: + properties: + compatible: + contains: + const: mobileye,eyeq5-olb + then: + patternProperties: + '-pins?$': false + +examples: + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + + system-controller@e00000 { + compatible = "mobileye,eyeq5-olb", "syscon", "simple-mfd"; + reg = <0 0xe00000 0x0 0x400>; + #reset-cells = <2>; + #clock-cells = <1>; + clocks = <&xtal>; + clock-names = "ref"; + }; + }; + - | + soc { + #address-cells = <2>; + #size-cells = <2>; + + system-controller@d2003000 { + compatible = "mobileye,eyeq6h-acc-olb", "syscon", "simple-mfd"; + reg = <0x0 0xd2003000 0x0 0x1000>; + #reset-cells = <1>; + #clock-cells = <1>; + clocks = <&xtal>; + clock-names = "ref"; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index aa3b947fb080..fcc9f4364a5d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14926,9 +14926,11 @@ M: Théo Lebrun L: linux-mips@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/mips/mobileye.yaml +F: Documentation/devicetree/bindings/soc/mobileye/ F: arch/mips/boot/dts/mobileye/ F: arch/mips/configs/eyeq5_defconfig F: arch/mips/mobileye/board-epm5.its.S +F: include/dt-bindings/clock/mobileye,eyeq5-clk.h MODULE SUPPORT M: Luis Chamberlain diff --git a/include/dt-bindings/clock/mobileye,eyeq5-clk.h b/include/dt-bindings/clock/mobileye,eyeq5-clk.h index 26d8930335e4..b433c1772c28 100644 --- a/include/dt-bindings/clock/mobileye,eyeq5-clk.h +++ b/include/dt-bindings/clock/mobileye,eyeq5-clk.h @@ -19,4 +19,25 @@ #define EQ5C_DIV_OSPI 10 +#define EQ6LC_PLL_DDR 0 +#define EQ6LC_PLL_CPU 1 +#define EQ6LC_PLL_PER 2 +#define EQ6LC_PLL_VDI 3 + +#define EQ6HC_SOUTH_PLL_VDI 0 +#define EQ6HC_SOUTH_PLL_PCIE 1 +#define EQ6HC_SOUTH_PLL_PER 2 +#define EQ6HC_SOUTH_PLL_ISP 3 + +#define EQ6HC_SOUTH_DIV_EMMC 4 +#define EQ6HC_SOUTH_DIV_OSPI_REF 5 +#define EQ6HC_SOUTH_DIV_OSPI_SYS 6 +#define EQ6HC_SOUTH_DIV_TSU 7 + +#define EQ6HC_ACC_PLL_XNN 0 +#define EQ6HC_ACC_PLL_VMP 1 +#define EQ6HC_ACC_PLL_PMA 2 +#define EQ6HC_ACC_PLL_MPC 3 +#define EQ6HC_ACC_PLL_NOC 4 + #endif From patchwork Fri May 3 14:20:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652955 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 922321552FC; Fri, 3 May 2024 14:21:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746083; cv=none; b=BJYhbm3xxXYKj5N79zhY2s+WE05F7zkzSnuHhmvx3UdQ9LFyd1N/mZzyWwI1El7lk9/Nz/0ux0McucxKOYCS2oIAj56KxtAwnCmLnnppZNMmEyXJSVjmFNm2KY+P/Esz+ZVV6ZT7HL7VQmyx9WQpNJ5dVhTDY42gb2v6iS5tR5w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746083; c=relaxed/simple; bh=3/3CibSLjnE7Z2tUb3XhZmdn0m09V6Wb8mUSh7tSTtg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YhmedSHXaWIqad6AtFoXfWZXv0kunjqgdCuistV9syvh85oLhcQmFqYWZnjFY5GBAqB1RtKfDwDrgG4Ysjtv2m8R/mh/iszXt/6xQKbuez9tNEATsFxa39cXLh6pcJC8QQtG+x6+4YnxomjSqfffc+b1lWCZNGTz/aiAnIvhdaM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=KSyGTDk2; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="KSyGTDk2" Received: by mail.gandi.net (Postfix) with ESMTPSA id 00C5EE0007; Fri, 3 May 2024 14:21:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746072; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VhCxOhm2wL8IBQ2UHqwouQlBmqxgQGndTJ7ExI+Ljes=; b=KSyGTDk2Ze0sA+Xr3CMjqq69hhUODAFh7KrVLI+BwthMp0mz9iItW7Evzw5ZfJRoNcoPnU OeNuNt4VaIb6OVgVFH4ElemZuPFdg4lf58kozOqEyZl4usKuKbzmxzPHx90DqNSc3H6Xak 2sDh76IWcOqKMZ4d44pza9aTR09/dKBYlK3r17iGq/ONpRqfBQRyzMy7h8Y+NpKoex1NG4 IlABmkbPIi2DrZjTwA0f2A7kGCupj/i0YDBQ4zaSW3gnbfMS8mB+WZQrdw23B6jItCHDCV 4mYAtOpSZJxKbaySA37tLD+rjZMjf68gkybHapHNAFR0VOWFe/fb3cmM9RXS7g== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:49 +0200 Subject: [PATCH v2 04/11] driver core: platform: Introduce platform_device_add_with_name() Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-4-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Public function platform_device_add() does three things: - Name device using pdev->name and pdev->id; - Insert resources into resource tree; - device_add(). This implies device name must be based upon pdev->name. Add platform_device_add_with_name() to allow caller to pick device name. pdev->name cannot be picked freely: it might be used to match platform driver id_table or name. This applies to MFD cells for example. In header file, avoid breakage by aliasing platform_device_add(pdev) to platform_device_add_with_name(pdev, NULL). Signed-off-by: Théo Lebrun --- drivers/base/platform.c | 17 +++++++++++------ include/linux/platform_device.h | 12 +++++++++++- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 10c577963418..dce282cb2e50 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -648,13 +648,15 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, EXPORT_SYMBOL_GPL(platform_device_add_data); /** - * platform_device_add - add a platform device to device hierarchy + * platform_device_add_with_name - add a platform device to device hierarchy * @pdev: platform device we're adding + * @devname: optional device name to assign, fallback to platform device name * * This is part 2 of platform_device_register(), though may be called * separately _iff_ pdev was allocated by platform_device_alloc(). */ -int platform_device_add(struct platform_device *pdev) +int platform_device_add_with_name(struct platform_device *pdev, + const char *devname) { struct device *dev = &pdev->dev; u32 i; @@ -665,12 +667,15 @@ int platform_device_add(struct platform_device *pdev) dev->bus = &platform_bus_type; + if (!devname) + devname = pdev->name; + switch (pdev->id) { default: - dev_set_name(dev, "%s.%d", pdev->name, pdev->id); + dev_set_name(dev, "%s.%d", devname, pdev->id); break; case PLATFORM_DEVID_NONE: - dev_set_name(dev, "%s", pdev->name); + dev_set_name(dev, "%s", devname); break; case PLATFORM_DEVID_AUTO: /* @@ -683,7 +688,7 @@ int platform_device_add(struct platform_device *pdev) return ret; pdev->id = ret; pdev->id_auto = true; - dev_set_name(dev, "%s.%d.auto", pdev->name, pdev->id); + dev_set_name(dev, "%s.%d.auto", devname, pdev->id); break; } @@ -733,7 +738,7 @@ int platform_device_add(struct platform_device *pdev) return ret; } -EXPORT_SYMBOL_GPL(platform_device_add); +EXPORT_SYMBOL_GPL(platform_device_add_with_name); /** * platform_device_del - remove a platform-level device diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 7a41c72c1959..bc1463c83f69 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -229,10 +229,20 @@ extern int platform_device_add_resources(struct platform_device *pdev, unsigned int num); extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); -extern int platform_device_add(struct platform_device *pdev); +extern int platform_device_add_with_name(struct platform_device *pdev, + const char *devname); extern void platform_device_del(struct platform_device *pdev); extern void platform_device_put(struct platform_device *pdev); +/** + * platform_device_add - add a platform device to device hierarchy + * @pdev: platform device we're adding + */ +static inline int platform_device_add(struct platform_device *pdev) +{ + return platform_device_add_with_name(pdev, NULL); +} + struct platform_driver { int (*probe)(struct platform_device *); From patchwork Fri May 3 14:20:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652957 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5F51215533F; Fri, 3 May 2024 14:21:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746084; cv=none; b=kZUyrxAgahzppY4S/d6q7/eXg97X6pMVCPL8H+WMQFybxXdRIpQcf0VFSyaff6TJ13r7oCOj5DxIGjFD74XLbc6Olo9gxtu6Hvd6iDR6TNx7cxk99KoKX8rl9Z49oiHxKo9sGb/cBndUTQ5922UQluvik5ZlgP/yWcu2C/wPga8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746084; c=relaxed/simple; bh=GKyULpFQ8XdXBuxIrhlYdZanY0FdS+QQ7EcrusQWFb8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cZQC1T1sQJFxLn+uQZSF/w1G8XLX2b7E4qDK5MEqBYX2dGhl5WMyoKlAiSr+zobUo5jbgKQpTYNCY8EBWqDPUgpsC0YRNXqDF99S5sZ2ReH+PiuelPUf1sZ2lRb3lHVzkrOfMTG6pVlLAgb2pRI6ACehi25DM8GizBAluVBDFys= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=pIR7mFhE; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="pIR7mFhE" Received: by mail.gandi.net (Postfix) with ESMTPSA id E08FCE0015; Fri, 3 May 2024 14:21:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746073; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OzhF3QerqK8gGgB0VM7veINqFbrG/m5c23SAtCZCPxg=; b=pIR7mFhEN2TsFj6ass3sIkF8Ho+HSimoByULbPGQJWQIR14DrB6ySpVVNbUrmXK9IDvtJB 2rVGfkDT+08jPH8Rf5/CMJBsV2vUhFqt9lnnbpqe9HM9sjX9LHR4AxIE/NZZm0YrA8nlyd H2Se5M1jhq2mHGOjzCBNkB+8Ww817RiMB7Ef+f3v7wICO9ASh4c7KvrCImSHUAppCbb5Hw 93ftOr1R9zZs3fypr66M+Ko6gzFZ2rawNBUZGwdEKKp/I3GtD+53o0nMlY9+hWdSjLkqh/ UZieEy/zbyA4u28OWeZMRBMswmZFO2VzmDEoxLiOuaQfyR5xK+l0D7Ya4MxOyQ== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:50 +0200 Subject: [PATCH v2 05/11] mfd: Add cell device name Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-5-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Current device name is picked from pdev->name, coming from cell->name. pdev->name is sometimes used to match driver so cannot be changed. Add cell->devname field to let MFDs configure their sub-devices names using newly introduced platform_device_add_with_name(). This comes in handy when MFDs instantiate the same platform driver. First solution is to use auto IDs: // MFD device A generates sub-device named "foo.0.auto" struct mfd_cell cell = { .name = "foo" }; mfd_add_devices(dev, PLATFORM_DEVID_AUTO, &cell, 1, ...); // MFD device B generates sub-device named "foo.1.auto" struct mfd_cell cell = { .name = "foo" }; mfd_add_devices(dev, PLATFORM_DEVID_AUTO, &cell, 1, ...); An alternative is to manually pick IDs using cell->id: // MFD device A generates sub-device named "foo.0" struct mfd_cell cell = { .name = "foo", .id = 0 }; mfd_add_devices(dev, 0, &cell, 1, ...); // MFD device B generates sub-device named "foo.1" struct mfd_cell cell = { .name = "foo", .id = 1 }; mfd_add_devices(dev, 0, &cell, 1, ...); Devices still have obscure names. With changes, two MFD devices can do: // MFD device A generates sub-device named "foo-a" struct mfd_cell cell = { .name = "foo", .devname = "foo-a" }; mfd_add_devices(dev, PLATFORM_DEVID_NONE, &cell, 1, ...); // MFD device B generates sub-device named "foo-b" struct mfd_cell cell = { .name = "foo", .devname = "foo-b" }; mfd_add_devices(dev, PLATFORM_DEVID_NONE, &cell, 1, ...); Device names are explicit and facilitate identification. Benefit increases with more instances. No shorthand MFD_CELL_*() macro is created to exploit this field. Signed-off-by: Théo Lebrun --- drivers/mfd/mfd-core.c | 2 +- include/linux/mfd/core.h | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 6ad5c93027af..bdfbe860295a 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -271,7 +271,7 @@ static int mfd_add_device(struct device *parent, int id, if (ret) goto fail_res_conflict; - ret = platform_device_add(pdev); + ret = platform_device_add_with_name(pdev, cell->devname); if (ret) goto fail_res_conflict; diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index e8bcad641d8c..a2040372ca91 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -14,7 +14,8 @@ #define MFD_RES_SIZE(arr) (sizeof(arr) / sizeof(struct resource)) -#define MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg, _use_of_reg, _match) \ +#define MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, \ + _of_reg, _use_of_reg, _match, _devname) \ { \ .name = (_name), \ .resources = (_res), \ @@ -26,25 +27,26 @@ .use_of_reg = (_use_of_reg), \ .acpi_match = (_match), \ .id = (_id), \ + .devname = (_devname), \ } #define MFD_CELL_OF_REG(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg) \ - MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg, true, NULL) + MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, _of_reg, true, NULL, NULL) #define MFD_CELL_OF(_name, _res, _pdata, _pdsize, _id, _compat) \ - MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, 0, false, NULL) + MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, _compat, 0, false, NULL, NULL) #define MFD_CELL_ACPI(_name, _res, _pdata, _pdsize, _id, _match) \ - MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, 0, false, _match) + MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, 0, false, _match, NULL) #define MFD_CELL_BASIC(_name, _res, _pdata, _pdsize, _id) \ - MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, 0, false, NULL) + MFD_CELL_ALL(_name, _res, _pdata, _pdsize, _id, NULL, 0, false, NULL, NULL) #define MFD_CELL_RES(_name, _res) \ - MFD_CELL_ALL(_name, _res, NULL, 0, 0, NULL, 0, false, NULL) + MFD_CELL_ALL(_name, _res, NULL, 0, 0, NULL, 0, false, NULL, NULL) #define MFD_CELL_NAME(_name) \ - MFD_CELL_ALL(_name, NULL, NULL, 0, 0, NULL, 0, false, NULL) + MFD_CELL_ALL(_name, NULL, NULL, 0, 0, NULL, 0, false, NULL, NULL) #define MFD_DEP_LEVEL_NORMAL 0 #define MFD_DEP_LEVEL_HIGH 1 @@ -118,6 +120,9 @@ struct mfd_cell { */ int num_parent_supplies; const char * const *parent_supplies; + + /* Optional struct device name. */ + const char *devname; }; /* From patchwork Fri May 3 14:20:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652949 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 484C41E4B1; Fri, 3 May 2024 14:21:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746080; cv=none; b=oV9+jWFhF0lpR3Lss3ftKh+typgmtaD2sV53NLfH+N+84+AvvQ9NtDUgLDJ6VkXdZGVBwQJqKxWvC5lGjDXNzvZkefYAMgJkpPdem9rx3tCkul2xi1thsw6u3rmfGyT6ipzaruTY7jMNxGwqCfuV5x76OhecOpSOai91DbiUl8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746080; c=relaxed/simple; bh=hLQChgYtET0WRL3137IYLuOShHL1o5R/z9XElRCzlXQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iKUkofNOKvhTvEqGecYnpaNhr6ktRZJB9Rs9zkGakNlb1YSreAyrK69vhek9vi4q+5c2aB9vhrftxTPusGwCPQeEjy+lQEjhXQoFjHQd2oXfJHDTczDKDPhEwI229YS645RutTZfvn+xYfCsWr87oXEsePNG1mQLEeDibZy8Afg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=PD7bTcKT; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="PD7bTcKT" Received: by mail.gandi.net (Postfix) with ESMTPSA id D8B6BE0012; Fri, 3 May 2024 14:21:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746074; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9sSrxzyJYyHA2ZncHIX4c1wnuyo/szR276JP38Uilf4=; b=PD7bTcKTQUjHWKGO5rA1jVIn9BCkyxxTA5zR1VzznvYhonKW2PWGXU7brmVc3aRC7/KSv4 DRs838tY5RmDphCi3sWM7FwBharAZQJLoxZs8aSNAVs+XWHbxsRpq0EFKZdpM0dIqY6oBQ 2H+yQHy6c6qGAoMdFTX/NSAu7VzGJ43DYKzUO71YLLrha6u1Y+v765Dt39jrvg3lA+C4b8 d6sES4G7ntd52wB9G+0rzLJ62ZWCnNuwp2pSrPGNx4M4yuueVQNRz0LrmVh0T4LPD4auoT 0Ql772cZAlOwCQG/sZEYPrX3aP2wqMfP7aSioLNVJbPO4gAkvMKIhHP6USkbWg== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:51 +0200 Subject: [PATCH v2 06/11] mfd: olb: Add support for Mobileye OLB system-controller Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-6-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Mobileye OLB system-controller gets used in EyeQ5, EyeQ6L and EyeQ6H platforms. It hosts clock, reset and pinctrl functionality. Tiny iomem resources are declared for all cells. Some features are spread apart. Pinctrl is only used on EyeQ5. EyeQ6H is special: it hosts seven OLB controllers, each with a compatible. That means many clock and reset cells. Use cell->devname for explicit device names rather than clk-eyeq.ID or clk-eyeq.ID.auto. Signed-off-by: Théo Lebrun --- drivers/mfd/Kconfig | 10 +++ drivers/mfd/Makefile | 2 + drivers/mfd/mobileye-olb.c | 180 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 4b023ee229cf..d004a3f4d493 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1030,6 +1030,16 @@ config MFD_OCELOT If unsure, say N. +config MFD_OLB + bool "Mobileye EyeQ OLB System Controller Support" + select MFD_CORE + depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST + default MACH_EYEQ5 || MACH_EYEQ6H + help + Say yes here to add support for EyeQ platforms (EyeQ5, EyeQ6L and + EyeQ6H). This core MFD platform driver provides clock, reset and + pinctrl (only EyeQ5) support. + config EZX_PCAP bool "Motorola EZXPCAP Support" depends on SPI_MASTER diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index c66f07edcd0e..d872833966a8 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -120,6 +120,8 @@ obj-$(CONFIG_MFD_CORE) += mfd-core.o ocelot-soc-objs := ocelot-core.o ocelot-spi.o obj-$(CONFIG_MFD_OCELOT) += ocelot-soc.o +obj-$(CONFIG_MFD_OLB) += mobileye-olb.o + obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o obj-$(CONFIG_MFD_CPCAP) += motorola-cpcap.o diff --git a/drivers/mfd/mobileye-olb.c b/drivers/mfd/mobileye-olb.c new file mode 100644 index 000000000000..1640d63a3ddd --- /dev/null +++ b/drivers/mfd/mobileye-olb.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * System controller multi-function device for EyeQ platforms. + * + * Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms have MMIO mapped registers + * controlling core platform clocks, resets and pin control. Many other + * features are present and not yet exposed. + * + * Declare cells for each compatible. Only EyeQ5 has pinctrl. + * EyeQ6H has seven OLB instances; each has a name which we propagate to + * sub-devices using cell->devname. + * + * Copyright (C) 2024 Mobileye Vision Technologies Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define OLB_MFD_CELL(_name, _res, _devname) \ + MFD_CELL_ALL(_name, _res, NULL, 0, 0, NULL, 0, false, NULL, _devname) + +struct olb_match_data { + const struct mfd_cell *cells; + int nb_cells; /* int to match devm_mfd_add_devices() argument */ +}; + +#define OLB_DATA(_cells) { .cells = (_cells), .nb_cells = ARRAY_SIZE(_cells) } + +static int olb_probe(struct platform_device *pdev) +{ + const struct olb_match_data *match_data; + struct device *dev = &pdev->dev; + struct resource *res; + + match_data = device_get_match_data(dev); + if (!match_data) + return -ENODEV; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + match_data->cells, match_data->nb_cells, + res, 0, NULL); +} + +static const struct resource olb_eyeq5_clk_resources[] = { + DEFINE_RES_MEM_NAMED(0x02C, 10 * 8, "pll"), + DEFINE_RES_MEM_NAMED(0x11C, 1 * 4, "ospi"), +}; + +static const struct resource olb_eyeq5_reset_resources[] = { + DEFINE_RES_MEM_NAMED(0x004, 2 * 4, "d0"), + DEFINE_RES_MEM_NAMED(0x200, 13 * 4, "d1"), + DEFINE_RES_MEM_NAMED(0x120, 1 * 4, "d2"), +}; + +static const struct resource olb_eyeq5_pinctrl_resources[] = { + DEFINE_RES_MEM_NAMED(0x0B0, 12 * 4, "pinctrl"), +}; + +static const struct mfd_cell olb_eyeq5_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq5_clk_resources, NULL), + OLB_MFD_CELL("reset-eyeq", olb_eyeq5_reset_resources, NULL), + OLB_MFD_CELL("eyeq5-pinctrl", olb_eyeq5_pinctrl_resources, NULL), +}; + +static const struct olb_match_data olb_eyeq5_match_data = OLB_DATA(olb_eyeq5_cells); + +static const struct resource olb_eyeq6l_clk_resources[] = { + DEFINE_RES_MEM_NAMED(0x02C, 4 * 8, "pll"), +}; + +static const struct resource olb_eyeq6l_reset_resources[] = { + DEFINE_RES_MEM_NAMED(0x004, 2 * 4, "d0"), + DEFINE_RES_MEM_NAMED(0x200, 13 * 4, "d1"), +}; + +static const struct mfd_cell olb_eyeq6l_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq6l_clk_resources, NULL), + OLB_MFD_CELL("reset-eyeq", olb_eyeq6l_reset_resources, NULL), +}; + +static const struct olb_match_data olb_eyeq6l_match_data = OLB_DATA(olb_eyeq6l_cells); + +static const struct resource olb_eyeq6h_acc_clk_resources[] = { + DEFINE_RES_MEM_NAMED(0x040, 7 * 8, "pll"), +}; + +static const struct resource olb_eyeq6h_acc_reset_resources[] = { + DEFINE_RES_MEM_NAMED(0x000, 15 * 4, "d0"), +}; + +static const struct mfd_cell olb_eyeq6h_acc_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq6h_acc_clk_resources, "clk-eyeq-acc"), + OLB_MFD_CELL("reset-eyeq", olb_eyeq6h_acc_reset_resources, "reset-eyeq-acc"), +}; + +static const struct olb_match_data olb_eyeq6h_acc_match_data = OLB_DATA(olb_eyeq6h_acc_cells); + +static const struct resource olb_eyeq6h_we_clk_resources[] = { + DEFINE_RES_MEM_NAMED(0x074, 1 * 8, "pll"), +}; + +static const struct resource olb_eyeq6h_we_reset_resources[] = { + DEFINE_RES_MEM_NAMED(0x004, 4 * 4, "d0"), +}; + +static const struct mfd_cell olb_eyeq6h_west_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq6h_we_clk_resources, "clk-eyeq-west"), + OLB_MFD_CELL("reset-eyeq", olb_eyeq6h_we_reset_resources, "reset-eyeq-west"), +}; + +static const struct olb_match_data olb_eyeq6h_west_match_data = OLB_DATA(olb_eyeq6h_west_cells); + +static const struct mfd_cell olb_eyeq6h_east_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq6h_we_clk_resources, "clk-eyeq-east"), + OLB_MFD_CELL("reset-eyeq", olb_eyeq6h_we_reset_resources, "reset-eyeq-east"), +}; + +static const struct olb_match_data olb_eyeq6h_east_match_data = OLB_DATA(olb_eyeq6h_east_cells); + +static const struct resource olb_eyeq6h_south_clk_resources[] = { + DEFINE_RES_MEM_NAMED(0x000, 4 * 8, "pll"), + DEFINE_RES_MEM_NAMED(0x070, 1 * 4, "emmc"), + DEFINE_RES_MEM_NAMED(0x090, 1 * 4, "ospi"), + DEFINE_RES_MEM_NAMED(0x098, 1 * 4, "tsu"), +}; + +static const struct mfd_cell olb_eyeq6h_south_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq6h_south_clk_resources, "clk-eyeq-south"), +}; + +static const struct olb_match_data olb_eyeq6h_south_match_data = OLB_DATA(olb_eyeq6h_south_cells); + +static const struct resource olb_eyeq6h_ddr_clk_resources[] = { + DEFINE_RES_MEM_NAMED(0x074, 1 * 8, "pll"), +}; + +static const struct mfd_cell olb_eyeq6h_ddr0_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq6h_ddr_clk_resources, "clk-eyeq-ddr0"), +}; + +static const struct olb_match_data olb_eyeq6h_ddr0_match_data = OLB_DATA(olb_eyeq6h_ddr0_cells); + +static const struct mfd_cell olb_eyeq6h_ddr1_cells[] = { + OLB_MFD_CELL("clk-eyeq", olb_eyeq6h_ddr_clk_resources, "clk-eyeq-ddr1"), +}; + +static const struct olb_match_data olb_eyeq6h_ddr1_match_data = OLB_DATA(olb_eyeq6h_ddr1_cells); + +static const struct of_device_id olb_of_match[] = { + { .compatible = "mobileye,eyeq5-olb", .data = &olb_eyeq5_match_data }, + { .compatible = "mobileye,eyeq6l-olb", .data = &olb_eyeq6l_match_data }, + { .compatible = "mobileye,eyeq6h-acc-olb", .data = &olb_eyeq6h_acc_match_data }, + /* No central: it only has an early clock handled using CLK_OF_DECLARE_DRIVER(). */ + { .compatible = "mobileye,eyeq6h-east-olb", .data = &olb_eyeq6h_east_match_data }, + { .compatible = "mobileye,eyeq6h-west-olb", .data = &olb_eyeq6h_west_match_data }, + { .compatible = "mobileye,eyeq6h-south-olb", .data = &olb_eyeq6h_south_match_data }, + { .compatible = "mobileye,eyeq6h-ddr0-olb", .data = &olb_eyeq6h_ddr0_match_data }, + { .compatible = "mobileye,eyeq6h-ddr1-olb", .data = &olb_eyeq6h_ddr1_match_data }, + {}, +}; +MODULE_DEVICE_TABLE(of, olb_of_match); + +static struct platform_driver olb_driver = { + .probe = olb_probe, + .driver = { + .name = "olb", + .of_match_table = olb_of_match, + }, +}; +builtin_platform_driver(olb_driver); From patchwork Fri May 3 14:20:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652948 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A986154BF1; Fri, 3 May 2024 14:21:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746080; cv=none; b=dMyBqOT8ZMVxnzwfEgZDwoA4o6pEqpkuJ1ma369cGPmwCV73nWy7VTD1+W/kiauT+RNvkrbMHtFM7yc1jMfZssL7ua0v+tAs5ITERndJlj2agZEF3Taf0TH533w+85eyiptztZXyMbqMevaxgpSlz2jhuMacKmXtqMD3mb39ysE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746080; c=relaxed/simple; bh=aPqTKe7d4WbI7QD4yTnf4tncjyKh5eeTinicI+o4iQE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FdLbTrb7cxxRFIQ/zzWwMRDnuNSwCumwzBDCSyMjXVeIjZG5q+A7Z2rZdv3V3eafxlhjkhWMJ/GpfJSOz10N0F3F0yL4/pW32kqtsUl3W0H1wQkQwNOWykDlxjkG5AUBcQ4DeQdAc8H8QzFOe8PNziNc6STeLvqS9LmWaVcj8jI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=TlYeUop/; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="TlYeUop/" Received: by mail.gandi.net (Postfix) with ESMTPSA id D0FF8E000C; Fri, 3 May 2024 14:21:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746075; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=0CmhYS38FoiHM21EItP7+1kMUZLrboLBpS562xGjpdM=; b=TlYeUop/D26Wwi25qpQ4yhYXwqSEuNsVANHZGKT4my4vGC7jDA3sCFFedSehCrcJnhnSpl bz3aF90uTvhMFH3GBN3sbBUY4d7A5Xm62JTi9+DofOiHzBrpVIaSaNx7X8DVWfRSOabAqU yBzRncqpduNrxM//Sdj1O7JO3J4XKlRlVyN/KN6yEQa1E3YbJILU7zG05fgaRXjG61iliB 9LuBOASlsDnBcyJDEeAZGV/60ZxlmDukgQkG2tUhI3NLKddPMI/SyEqGVJGWUUgnNGO7If uDCIB7D/7B95zc98oGdjCAqtbZwAbfh2AgafUZiOeewl4qrM5xvsFvFeOKzYOA== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:52 +0200 Subject: [PATCH v2 07/11] clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-7-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Add CLK_DIVIDER_EVEN_INTEGERS flag to support divisor of 2, 4, 6, etc. The same divisor can be done using a table, which would be big and wasteful for a clock dividor of width 8 (256 entries). Require increasing flags size from u8 to u16 because CLK_DIVIDER_EVEN_INTEGERS is the eighth flag. Signed-off-by: Théo Lebrun --- drivers/clk/clk-divider.c | 12 +++++++++--- include/linux/clk-provider.h | 11 +++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index a2c2b5203b0a..b6654c5c36d2 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -72,6 +72,8 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width, return clk_div_mask(width); if (flags & CLK_DIVIDER_POWER_OF_TWO) return 1 << clk_div_mask(width); + if (flags & CLK_DIVIDER_EVEN_INTEGERS) + return 2 * (clk_div_mask(width) + 1); if (table) return _get_table_maxdiv(table, width); return clk_div_mask(width) + 1; @@ -97,6 +99,8 @@ static unsigned int _get_div(const struct clk_div_table *table, return 1 << val; if (flags & CLK_DIVIDER_MAX_AT_ZERO) return val ? val : clk_div_mask(width) + 1; + if (flags & CLK_DIVIDER_EVEN_INTEGERS) + return 2 * (val + 1); if (table) return _get_table_div(table, val); return val + 1; @@ -122,6 +126,8 @@ static unsigned int _get_val(const struct clk_div_table *table, return __ffs(div); if (flags & CLK_DIVIDER_MAX_AT_ZERO) return (div == clk_div_mask(width) + 1) ? 0 : div; + if (flags & CLK_DIVIDER_EVEN_INTEGERS) + return (div >> 1) - 1; if (table) return _get_table_val(table, div); return div - 1; @@ -538,7 +544,7 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { struct clk_divider *div; @@ -610,7 +616,7 @@ EXPORT_SYMBOL_GPL(__clk_hw_register_divider); struct clk *clk_register_divider_table(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, const struct clk_div_table *table, + u16 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { struct clk_hw *hw; @@ -664,7 +670,7 @@ struct clk_hw *__devm_clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock) { struct clk_hw **ptr, *hw; diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 4a537260f655..cb348e502e41 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -675,13 +675,15 @@ struct clk_div_table { * CLK_DIVIDER_BIG_ENDIAN - By default little endian register accesses are used * for the divider register. Setting this flag makes the register accesses * big endian. + * CLK_DIVIDER_EVEN_INTEGERS - clock divisor is 2, 4, 6, 8, 10, etc. + * Formula is 2 * (value read from hardware + 1). */ struct clk_divider { struct clk_hw hw; void __iomem *reg; u8 shift; u8 width; - u8 flags; + u16 flags; const struct clk_div_table *table; spinlock_t *lock; }; @@ -697,6 +699,7 @@ struct clk_divider { #define CLK_DIVIDER_READ_ONLY BIT(5) #define CLK_DIVIDER_MAX_AT_ZERO BIT(6) #define CLK_DIVIDER_BIG_ENDIAN BIT(7) +#define CLK_DIVIDER_EVEN_INTEGERS BIT(8) extern const struct clk_ops clk_divider_ops; extern const struct clk_ops clk_divider_ro_ops; @@ -726,18 +729,18 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock); struct clk_hw *__devm_clk_hw_register_divider(struct device *dev, struct device_node *np, const char *name, const char *parent_name, const struct clk_hw *parent_hw, const struct clk_parent_data *parent_data, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, + void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock); struct clk *clk_register_divider_table(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, const struct clk_div_table *table, + u16 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock); /** * clk_register_divider - register a divider clock with the clock framework From patchwork Fri May 3 14:20:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652951 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 46F6D15357A; Fri, 3 May 2024 14:21:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746081; cv=none; b=rhhKeXI3lf8+PPycD4hwriGmK0vgP5pf+HBwQygJZgnQ7Kwn7ZExCLoVdi3aVBZVLv5CxjsWpIcuIfUMGJUVeaaADr1rHH00ScvRs5EzKSmcLNfCq3WAvnHk++GL8YaRgUdNA2uKmjQSDjMOjwn9oPM+0aYlHtMtSS4tS/KOt1w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746081; c=relaxed/simple; bh=VgOovtitGxZOdeSrouwYLO65hhzqYnvhU5A5iejwBQY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=d0oil/2wTnDjeiW2B49RMuNOt1F6UjIfILknrHje4MQ7+40XS12KJQ02qpe1vtywSyLTO9cuiqaC7dyoNuRX2+I/u0H+4M0oGpJNM7hqKJTB2/8Wt6QA0SRS7SXfuc2IYURq8xW4tlZt3NXCgMduHW38yFpH5M3MZw0hEguJAC4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=o62FAvxy; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="o62FAvxy" Received: by mail.gandi.net (Postfix) with ESMTPSA id C3FD2E000A; Fri, 3 May 2024 14:21:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746076; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pv6WjXOvsOkRR4cY2/z8n791NvLjEHiCR0WJskoV+G0=; b=o62FAvxyKX6keRGUAmaF/5DYzULUsF51xIPLtrW7bsjk872wBtRdCVInoNIh0W8+Iektcx J63RIb/pqKH5DvxNdsAaqx6FfR6euGRJYIyNriwpzUubtvfnPBSyLv+GaprTIdkzjA8CLp zyNrK6EGO/6N0YwTjr7UdzPOvYTP9UynOs1FiWWn/UcY2OfFk7DsCw9QNp0huAHWHU2Oof NlFiMW20ur0BClQy3hs3771qPoBmeYHkDHfPnjON2TXgF04PinrD6s0EdltkjV5Z3b2hML RrMGa7CN+8NNVajqQHc8VIasC03pX4YpjNAZrAj9V0XA9YbDxWs+qqGrfuh52A== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:53 +0200 Subject: [PATCH v2 08/11] clk: eyeq: add driver Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-8-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Add Mobileye EyeQ5, EyeQ6L and EyeQ6H clock controller driver. It is both a platform driver and a hook onto of_clk_init() used for clocks required early (GIC timer, UARTs). For some compatible, it is both at the same time. eqc_init() initialises early PLLs and stores clock array in a static linked list. It marks other clocks as deferred. eqc_probe() retrieves the clock array and adds all remaining clocks. It exposes read-only PLLs derived from the main crystal on board. It also exposes another type of clocks: divider clocks. They always have even divisors and have one PLL as parent. Device is only used as MFD cell. Inherit parent OF node for property fetching helpers to work. Also, don't register match table on platform driver: rather fetch match-data manually using of_match_node(). Match table therefore targets parent MFD compatible. Signed-off-by: Théo Lebrun --- MAINTAINERS | 1 + drivers/clk/Kconfig | 11 + drivers/clk/Makefile | 1 + drivers/clk/clk-eyeq.c | 690 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 703 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index fcc9f4364a5d..f386e9da2cd0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14930,6 +14930,7 @@ F: Documentation/devicetree/bindings/soc/mobileye/ F: arch/mips/boot/dts/mobileye/ F: arch/mips/configs/eyeq5_defconfig F: arch/mips/mobileye/board-epm5.its.S +F: drivers/clk/clk-eyeq5.c F: include/dt-bindings/clock/mobileye,eyeq5-clk.h MODULE SUPPORT diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 50af5fc7f570..1eb6e70977a3 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -218,6 +218,17 @@ config COMMON_CLK_EN7523 This driver provides the fixed clocks and gates present on Airoha ARM silicon. +config COMMON_CLK_EYEQ + bool "Clock driver for the Mobileye EyeQ platform" + depends on OF || COMPILE_TEST + depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST + default MACH_EYEQ5 || MACH_EYEQ6H + help + This driver provides clocks found on Mobileye EyeQ5, EyeQ6L and Eye6H + SoCs. Controllers live in shared register regions called OLB. Driver + provides read-only PLLs, derived from the main crystal clock (which + must be constant). It also exposes some divider clocks. + config COMMON_CLK_FSL_FLEXSPI tristate "Clock driver for FlexSPI on Layerscape SoCs" depends on ARCH_LAYERSCAPE || COMPILE_TEST diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 14fa8d4ecc1f..52de92309aa8 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o obj-$(CONFIG_COMMON_CLK_EN7523) += clk-en7523.o +obj-$(CONFIG_COMMON_CLK_EYEQ) += clk-eyeq.o obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI) += clk-fsl-flexspi.o obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o diff --git a/drivers/clk/clk-eyeq.c b/drivers/clk/clk-eyeq.c new file mode 100644 index 000000000000..70348faf2383 --- /dev/null +++ b/drivers/clk/clk-eyeq.c @@ -0,0 +1,690 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PLL clock driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms. + * + * This controller handles read-only PLLs, all derived from the same main + * crystal clock. It also exposes divider clocks, those are children to PLLs. + * Parent clock is expected to be constant. This driver's registers live in + * a shared region called OLB. Some PLLs are initialised early by of_clk_init(). + * + * We use eqc_ as prefix, as-in "EyeQ Clock", but way shorter. + * + * Copyright (C) 2024 Mobileye Vision Technologies Ltd. + */ + +#define pr_fmt(fmt) "clk-eyeq: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define EQC_MAX_DIV_COUNT 4 + +/* In frac mode, it enables fractional noise canceling DAC. Else, no function. */ +#define PCSR0_DAC_EN BIT(0) +/* Fractional or integer mode */ +#define PCSR0_DSM_EN BIT(1) +#define PCSR0_PLL_EN BIT(2) +/* All clocks output held at 0 */ +#define PCSR0_FOUTPOSTDIV_EN BIT(3) +#define PCSR0_POST_DIV1 GENMASK(6, 4) +#define PCSR0_POST_DIV2 GENMASK(9, 7) +#define PCSR0_REF_DIV GENMASK(15, 10) +#define PCSR0_INTIN GENMASK(27, 16) +#define PCSR0_BYPASS BIT(28) +/* Bits 30..29 are reserved */ +#define PCSR0_PLL_LOCKED BIT(31) + +#define PCSR1_RESET BIT(0) +#define PCSR1_SSGC_DIV GENMASK(4, 1) +/* Spread amplitude (% = 0.1 * SPREAD[4:0]) */ +#define PCSR1_SPREAD GENMASK(9, 5) +#define PCSR1_DIS_SSCG BIT(10) +/* Down-spread or center-spread */ +#define PCSR1_DOWN_SPREAD BIT(11) +#define PCSR1_FRAC_IN GENMASK(31, 12) + +/* + * Driver might register clock provider from eqc_init() if PLLs are required + * early (before platform bus is ready). Store struct eqc_priv inside linked + * list to pass clock provider from eqc_init() to eqc_probe() and register + * remaining clocks from platform device probe. + * + * Clock provider is NOT created by eqc_init() if no early clock is required. + * Store as linked list because EyeQ6H has multiple clock controller instances. + * Matching is done based on devicetree node pointer. + */ +static DEFINE_SPINLOCK(eqc_list_slock); +static LIST_HEAD(eqc_list); + +struct eqc_pll { + unsigned int index; + const char *name; + unsigned int reg64; +}; + +/* + * Divider clock. Divider is 2*(v+1), with v the register value. + * Min divider is 2, max is 2*(2^width). + */ +struct eqc_div { + unsigned int index; + const char *name; + unsigned int parent; + unsigned int resource_index; + u8 shift; + u8 width; +}; + +struct eqc_match_data { + unsigned int pll_count; + const struct eqc_pll *plls; + + unsigned int div_count; + const struct eqc_div *divs; +}; + +struct eqc_early_match_data { + unsigned int early_pll_count; + const struct eqc_pll *early_plls; + /* Information required to init properly clk HW cells. */ + unsigned int nb_late_clks; +}; + +struct eqc_priv { + struct clk_hw_onecell_data *cells; + const struct eqc_early_match_data *early_data; + const struct eqc_match_data *data; + void __iomem *base; + struct device_node *np; + struct list_head list; +}; + +static int eqc_pll_parse_registers(u32 r0, u32 r1, unsigned long *mult, + unsigned long *div, unsigned long *acc) +{ + if (r0 & PCSR0_BYPASS) { + *mult = 1; + *div = 1; + *acc = 0; + return 0; + } + + if (!(r0 & PCSR0_PLL_LOCKED)) + return -EINVAL; + + *mult = FIELD_GET(PCSR0_INTIN, r0); + *div = FIELD_GET(PCSR0_REF_DIV, r0); + if (r0 & PCSR0_FOUTPOSTDIV_EN) + *div *= FIELD_GET(PCSR0_POST_DIV1, r0) * FIELD_GET(PCSR0_POST_DIV2, r0); + + /* Fractional mode, in 2^20 (0x100000) parts. */ + if (r0 & PCSR0_DSM_EN) { + *div *= 0x100000; + *mult = *mult * 0x100000 + FIELD_GET(PCSR1_FRAC_IN, r1); + } + + if (!*mult || !*div) + return -EINVAL; + + /* Spread spectrum. */ + if (!(r1 & (PCSR1_RESET | PCSR1_DIS_SSCG))) { + /* + * Spread is 1/1000 parts of frequency, accuracy is half of + * that. To get accuracy, convert to ppb (parts per billion). + */ + u32 spread = FIELD_GET(PCSR1_SPREAD, r1); + + *acc = spread * 500000; + if (r1 & PCSR1_DOWN_SPREAD) { + /* + * Downspreading: the central frequency is half a + * spread lower. + */ + *mult *= 2000 - spread; + *div *= 2000; + } + } else { + *acc = 0; + } + + return 0; +} + +static unsigned int eqc_compute_clock_count(const struct eqc_early_match_data *early_data, + const struct eqc_match_data *data) +{ + unsigned int i, nb_clks = 0, sum = 0; + + if (early_data) { + sum += early_data->early_pll_count; + + for (i = 0; i < early_data->early_pll_count; i++) + if (early_data->early_plls[i].index >= nb_clks) + nb_clks = early_data->early_plls[i].index + 1; + } + + if (data) { + sum += data->pll_count + data->div_count; + + for (i = 0; i < data->pll_count; i++) + if (data->plls[i].index >= nb_clks) + nb_clks = data->plls[i].index + 1; + + for (i = 0; i < data->div_count; i++) + if (data->divs[i].index >= nb_clks) + nb_clks = data->divs[i].index + 1; + } + + /* We expect the biggest clock index to be 1 below the clock count. */ + WARN_ON(nb_clks != sum); + + return nb_clks; +} + +static const struct eqc_pll eqc_eyeq5_plls[] = { + { .index = EQ5C_PLL_VMP, .name = "pll-vmp", .reg64 = 0x08 }, + { .index = EQ5C_PLL_PMA, .name = "pll-pma", .reg64 = 0x10 }, + { .index = EQ5C_PLL_VDI, .name = "pll-vdi", .reg64 = 0x18 }, + { .index = EQ5C_PLL_DDR0, .name = "pll-ddr0", .reg64 = 0x20 }, + { .index = EQ5C_PLL_PCI, .name = "pll-pci", .reg64 = 0x28 }, + { .index = EQ5C_PLL_PMAC, .name = "pll-pmac", .reg64 = 0x38 }, + { .index = EQ5C_PLL_MPC, .name = "pll-mpc", .reg64 = 0x40 }, + { .index = EQ5C_PLL_DDR1, .name = "pll-ddr1", .reg64 = 0x48 }, +}; + +static const struct eqc_div eqc_eyeq5_divs[] = { + { + .index = EQ5C_DIV_OSPI, + .name = "div-ospi", + .parent = EQ5C_PLL_PER, + .resource_index = 1, + .shift = 0, + .width = 4, + }, +}; + +static const struct eqc_match_data eqc_eyeq5_match_data = { + .pll_count = ARRAY_SIZE(eqc_eyeq5_plls), + .plls = eqc_eyeq5_plls, + + .div_count = ARRAY_SIZE(eqc_eyeq5_divs), + .divs = eqc_eyeq5_divs, +}; + +static const struct eqc_pll eqc_eyeq6l_plls[] = { + { .index = EQ6LC_PLL_DDR, .name = "pll-ddr", .reg64 = 0x00 }, + { .index = EQ6LC_PLL_CPU, .name = "pll-cpu", .reg64 = 0x08 }, /* also acc */ + { .index = EQ6LC_PLL_PER, .name = "pll-per", .reg64 = 0x10 }, + { .index = EQ6LC_PLL_VDI, .name = "pll-vdi", .reg64 = 0x18 }, +}; + +static const struct eqc_match_data eqc_eyeq6l_match_data = { + .pll_count = ARRAY_SIZE(eqc_eyeq6l_plls), + .plls = eqc_eyeq6l_plls, +}; + +static const struct eqc_pll eqc_eyeq6h_east_plls[] = { + { .index = 0, .name = "pll-east", .reg64 = 0x0 }, +}; + +static const struct eqc_match_data eqc_eyeq6h_east_match_data = { + .pll_count = ARRAY_SIZE(eqc_eyeq6h_east_plls), + .plls = eqc_eyeq6h_east_plls, +}; + +static const struct eqc_pll eqc_eyeq6h_south_plls[] = { + { .index = EQ6HC_SOUTH_PLL_VDI, .name = "pll-vdi", .reg64 = 0x00 }, + { .index = EQ6HC_SOUTH_PLL_PCIE, .name = "pll-pcie", .reg64 = 0x08 }, + { .index = EQ6HC_SOUTH_PLL_PER, .name = "pll-per", .reg64 = 0x10 }, + { .index = EQ6HC_SOUTH_PLL_ISP, .name = "pll-isp", .reg64 = 0x18 }, +}; + +static const struct eqc_div eqc_eyeq6h_south_divs[] = { + { + .index = EQ6HC_SOUTH_DIV_EMMC, + .name = "div-emmc", + .parent = EQ6HC_SOUTH_PLL_PER, + .resource_index = 1, + .shift = 4, + .width = 4, + }, + { + .index = EQ6HC_SOUTH_DIV_OSPI_REF, + .name = "div-ospi-ref", + .parent = EQ6HC_SOUTH_PLL_PER, + .resource_index = 2, + .shift = 4, + .width = 4, + }, + { + .index = EQ6HC_SOUTH_DIV_OSPI_SYS, + .name = "div-ospi-sys", + .parent = EQ6HC_SOUTH_PLL_PER, + .resource_index = 2, + .shift = 8, + .width = 1, + }, + { + .index = EQ6HC_SOUTH_DIV_TSU, + .name = "div-tsu", + .parent = EQ6HC_SOUTH_PLL_PCIE, + .resource_index = 3, + .shift = 4, + .width = 8, + }, +}; + +static const struct eqc_match_data eqc_eyeq6h_south_match_data = { + .pll_count = ARRAY_SIZE(eqc_eyeq6h_south_plls), + .plls = eqc_eyeq6h_south_plls, + + .div_count = ARRAY_SIZE(eqc_eyeq6h_south_divs), + .divs = eqc_eyeq6h_south_divs, +}; + +static const struct eqc_pll eqc_eyeq6h_ddr0_plls[] = { + { .index = 0, .name = "pll-ddr0", .reg64 = 0x0 }, +}; + +static const struct eqc_match_data eqc_eyeq6h_ddr0_match_data = { + .pll_count = ARRAY_SIZE(eqc_eyeq6h_ddr0_plls), + .plls = eqc_eyeq6h_ddr0_plls, +}; + +static const struct eqc_pll eqc_eyeq6h_ddr1_plls[] = { + { .index = 0, .name = "pll-ddr1", .reg64 = 0x0 }, +}; + +static const struct eqc_match_data eqc_eyeq6h_ddr1_match_data = { + .pll_count = ARRAY_SIZE(eqc_eyeq6h_ddr1_plls), + .plls = eqc_eyeq6h_ddr1_plls, +}; + +static const struct eqc_pll eqc_eyeq6h_acc_plls[] = { + { .index = EQ6HC_ACC_PLL_XNN, .name = "pll-xnn", .reg64 = 0x00 }, + { .index = EQ6HC_ACC_PLL_VMP, .name = "pll-vmp", .reg64 = 0x10 }, + { .index = EQ6HC_ACC_PLL_PMA, .name = "pll-pma", .reg64 = 0x1C }, + { .index = EQ6HC_ACC_PLL_MPC, .name = "pll-mpc", .reg64 = 0x28 }, + { .index = EQ6HC_ACC_PLL_NOC, .name = "pll-noc", .reg64 = 0x30 }, +}; + +static const struct eqc_match_data eqc_eyeq6h_acc_match_data = { + .pll_count = ARRAY_SIZE(eqc_eyeq6h_acc_plls), + .plls = eqc_eyeq6h_acc_plls, +}; + +/* + * Table describes OLB system-controller compatibles and is NOT registered on + * platform driver. It gets matched against MFD parent OF node. + */ +static const struct of_device_id eqc_match_table[] = { + { .compatible = "mobileye,eyeq5-olb", .data = &eqc_eyeq5_match_data }, + { .compatible = "mobileye,eyeq6l-olb", .data = &eqc_eyeq6l_match_data }, + { .compatible = "mobileye,eyeq6h-east-olb", .data = &eqc_eyeq6h_east_match_data }, + { .compatible = "mobileye,eyeq6h-south-olb", .data = &eqc_eyeq6h_south_match_data }, + { .compatible = "mobileye,eyeq6h-ddr0-olb", .data = &eqc_eyeq6h_ddr0_match_data }, + { .compatible = "mobileye,eyeq6h-ddr1-olb", .data = &eqc_eyeq6h_ddr1_match_data }, + { .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqc_eyeq6h_acc_match_data }, + {} +}; +MODULE_DEVICE_TABLE(of, eqc_match_table); + +static void eqc_probe_init_plls(struct device *dev, struct eqc_priv *priv) +{ + const struct eqc_match_data *data = priv->data; + unsigned long mult, div, acc; + const struct eqc_pll *pll; + struct clk_hw *hw; + unsigned int i; + u32 r0, r1; + u64 val; + int ret; + + for (i = 0; i < data->pll_count; i++) { + pll = &data->plls[i]; + + val = readq(priv->base + pll->reg64); + r0 = val; + r1 = val >> 32; + + ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc); + if (ret) { + dev_warn(dev, "failed parsing state of %s\n", pll->name); + priv->cells->hws[pll->index] = ERR_PTR(ret); + continue; + } + + hw = clk_hw_register_fixed_factor_with_accuracy_fwname(dev, + dev->of_node, pll->name, "ref", 0, mult, div, acc); + priv->cells->hws[pll->index] = hw; + if (IS_ERR(hw)) + dev_warn(dev, "failed registering %s: %pe\n", pll->name, hw); + } +} + +static void eqc_probe_init_divs(struct platform_device *pdev, struct device *dev, + struct eqc_priv *priv) +{ + /* +1 because div clk resources start at 1, zero is always PLLs. */ + void __iomem *div_resources[EQC_MAX_DIV_COUNT + 1]; + const struct eqc_match_data *data = priv->data; + const struct eqc_div *div; + unsigned int res_index; + struct clk_hw *parent; + void __iomem *base; + struct clk_hw *hw; + unsigned int i; + + for (i = 0; i < data->div_count; i++) { + div = &data->divs[i]; + res_index = div->resource_index; + + /* Skip already acquired resources. */ + if (div_resources[res_index]) + continue; + + div_resources[res_index] = devm_platform_ioremap_resource(pdev, res_index); + } + + for (i = 0; i < data->div_count; i++) { + div = &data->divs[i]; + + base = div_resources[div->resource_index]; + if (IS_ERR(base)) { + dev_warn(dev, "failed to iomap resource for %s\n", div->name); + priv->cells->hws[div->index] = base; + continue; + } + + parent = priv->cells->hws[div->parent]; + + hw = clk_hw_register_divider_table_parent_hw(dev, div->name, + parent, 0, base, div->shift, div->width, + CLK_DIVIDER_EVEN_INTEGERS, NULL, NULL); + priv->cells->hws[div->index] = hw; + if (IS_ERR(hw)) + dev_warn(dev, "failed registering %s: %pe\n", + div->name, hw); + } +} + +static int eqc_probe(struct platform_device *pdev) +{ + const struct eqc_match_data *data; + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct eqc_priv *priv = NULL; + struct eqc_priv *entry; + unsigned int nb_clks; + + /* Spawned as MFD sub-device, use parent's OF node. */ + if (!dev->of_node) { + device_set_of_node_from_dev(dev, dev->parent); + if (!dev->of_node) + return -ENODEV; + } + + match = of_match_node(eqc_match_table, dev->of_node); + if (!match || !match->data) + return 0; /* NULL means zero clocks, we are done. */ + data = match->data; + + /* Try retrieving early init private data. */ + spin_lock(&eqc_list_slock); + list_for_each_entry(entry, &eqc_list, list) { + if (entry->np == dev->of_node) { + priv = entry; + break; + } + } + spin_unlock(&eqc_list_slock); + + if (!priv) { + /* Device did not get init early. Do it now. */ + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->np = dev->of_node; + + nb_clks = eqc_compute_clock_count(NULL, data); + priv->cells = devm_kzalloc(dev, struct_size(priv->cells, hws, nb_clks), + GFP_KERNEL); + if (!priv->cells) + return -ENOMEM; + + priv->cells->num = nb_clks; + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + } else { + /* + * Device got init early. Check clock count. + * + * eqc_init() should already know the exact clk count using + * nb_late_clks field. We ensure computation was right and fix + * clk cells if not. + */ + nb_clks = eqc_compute_clock_count(priv->early_data, data); + if (WARN_ON(nb_clks != priv->cells->num)) + priv->cells->num = nb_clks; + } + + priv->data = data; + + eqc_probe_init_plls(dev, priv); + + eqc_probe_init_divs(pdev, dev, priv); + + /* Clock provider has not been registered by eqc_init(). Do it now. */ + if (!priv->early_data) { + /* When providing a single clock, require no cell. */ + if (priv->cells->num == 1) + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + priv->cells->hws[0]); + else + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + priv->cells); + } + + return 0; +} + +static struct platform_driver eqc_driver = { + .probe = eqc_probe, + .driver = { + .name = "clk-eyeq", + }, +}; +builtin_platform_driver(eqc_driver); + +/* Required early for GIC timer (pll-cpu) and UARTs (pll-per). */ +static const struct eqc_pll eqc_eyeq5_early_plls[] = { + { .index = EQ5C_PLL_CPU, .name = "pll-cpu", .reg64 = 0x00 }, + { .index = EQ5C_PLL_PER, .name = "pll-per", .reg64 = 0x30 }, +}; + +static const struct eqc_early_match_data eqc_eyeq5_early_match_data = { + .early_pll_count = ARRAY_SIZE(eqc_eyeq5_early_plls), + .early_plls = eqc_eyeq5_early_plls, + .nb_late_clks = eqc_eyeq5_match_data.pll_count + eqc_eyeq5_match_data.div_count, +}; + +/* Required early for GIC timer. */ +static const struct eqc_pll eqc_eyeq6h_central_early_plls[] = { + { .index = 0, .name = "pll-cpu", .reg64 = 0x2c }, +}; + +static const struct eqc_early_match_data eqc_eyeq6h_central_early_match_data = { + .early_pll_count = ARRAY_SIZE(eqc_eyeq6h_central_early_plls), + .early_plls = eqc_eyeq6h_central_early_plls, + .nb_late_clks = 0, +}; + +/* Required early for UART. */ +static const struct eqc_pll eqc_eyeq6h_west_early_plls[] = { + { .index = 0, .name = "pll-west", .reg64 = 0x74 }, +}; + +static const struct eqc_early_match_data eqc_eyeq6h_west_early_match_data = { + .early_pll_count = ARRAY_SIZE(eqc_eyeq6h_west_early_plls), + .early_plls = eqc_eyeq6h_west_early_plls, + .nb_late_clks = 0, +}; + +static const struct of_device_id eqc_early_match_table[] = { + { + .compatible = "mobileye,eyeq5-olb", + .data = &eqc_eyeq5_early_match_data, + }, + { + .compatible = "mobileye,eyeq6h-central-olb", + .data = &eqc_eyeq6h_central_early_match_data, + }, + { + .compatible = "mobileye,eyeq6h-west-olb", + .data = &eqc_eyeq6h_west_early_match_data, + }, + {} +}; +MODULE_DEVICE_TABLE(of, eqc_early_match_table); + +static void __init eqc_init(struct device_node *np) +{ + const struct eqc_early_match_data *early_data; + unsigned int nb_clks = 0; + struct eqc_priv *priv; + unsigned int i; + int ret; + + early_data = of_match_node(eqc_early_match_table, np)->data; + + /* No reason to early init this clock provider. Delay until probe. */ + if (!early_data || early_data->early_pll_count == 0) + return; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto err; + } + + priv->np = np; + priv->early_data = early_data; + + nb_clks = early_data->early_pll_count + early_data->nb_late_clks; + priv->cells = kzalloc(struct_size(priv->cells, hws, nb_clks), GFP_KERNEL); + if (!priv->cells) { + ret = -ENOMEM; + goto err; + } + + priv->cells->num = nb_clks; + + /* + * Mark all clocks as deferred; some are registered here, the rest at + * platform device probe. + */ + for (i = 0; i < nb_clks; i++) + priv->cells->hws[i] = ERR_PTR(-EPROBE_DEFER); + + priv->base = of_iomap(np, 0); + if (!priv->base) { + ret = -ENODEV; + goto err; + } + + for (i = 0; i < early_data->early_pll_count; i++) { + const struct eqc_pll *pll = &early_data->early_plls[i]; + unsigned long mult, div, acc; + struct clk_hw *hw; + u32 r0, r1; + u64 val; + + val = readq(priv->base + pll->reg64); + r0 = val; + r1 = val >> 32; + + ret = eqc_pll_parse_registers(r0, r1, &mult, &div, &acc); + if (ret) { + pr_err("failed parsing state of %s\n", pll->name); + goto err; + } + + hw = clk_hw_register_fixed_factor_with_accuracy_fwname(NULL, + np, pll->name, "ref", 0, mult, div, acc); + priv->cells->hws[pll->index] = hw; + if (IS_ERR(hw)) { + pr_err("failed registering %s: %pe\n", pll->name, hw); + ret = PTR_ERR(hw); + goto err; + } + } + + /* When providing a single clock, require no cell. */ + if (nb_clks == 1) + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, priv->cells->hws[0]); + else + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, priv->cells); + if (ret) { + pr_err("failed registering clk provider: %d\n", ret); + goto err; + } + + spin_lock(&eqc_list_slock); + list_add_tail(&priv->list, &eqc_list); + spin_unlock(&eqc_list_slock); + + return; + +err: + /* + * We are doomed. The system will not be able to boot. + * + * Let's still try to be good citizens by freeing resources and print + * a last error message that might help debugging. + */ + + if (priv && priv->cells) { + of_clk_del_provider(np); + + for (i = 0; i < early_data->early_pll_count; i++) { + const struct eqc_pll *pll = &early_data->early_plls[i]; + struct clk_hw *hw = priv->cells->hws[pll->index]; + + if (!IS_ERR_OR_NULL(hw)) + clk_hw_unregister_fixed_factor(hw); + } + + kfree(priv->cells); + } + + kfree(priv); + + pr_err("failed clk init: %d\n", ret); +} + +CLK_OF_DECLARE_DRIVER(eqc_eyeq5, "mobileye,eyeq5-olb", eqc_init); +CLK_OF_DECLARE_DRIVER(eqc_eyeq6h_central, "mobileye,eyeq6h-central-olb", eqc_init); +CLK_OF_DECLARE_DRIVER(eqc_eyeq6h_west, "mobileye,eyeq6h-west-olb", eqc_init); From patchwork Fri May 3 14:20:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652953 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 32E20154BF8; Fri, 3 May 2024 14:21:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746082; cv=none; b=PARW5T9Wu0CkVp3lDDl12tK3bYFrAc+7FlPiLUWmilg1x2TAmbuFEToswgPkjA0i2IFNOn2/ZwMny39xA5rYThuITS1v+Qb3YJToDQwhpGh0yMXZAgoSNYU79Idjkn+EJSLLx8V7azoXrDvTZDCVgEa1JB3b42BWvFyJNcuTka0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746082; c=relaxed/simple; bh=1vROglKEHTUE1+/d4TvHZj1kKwfzplAgMYvFn36G9cA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VB9/XwVqcesIk86zN+glYXSLLYsE19iIeS8JImHUwPIzfGpRfa+Yx757OXf0xNihI1G8UZlFbHQoejdvdmVCV1FU+FwJ4y9YrRNVXsDYWEPo+hwMtiogRLCvns5a22SCJeQCfQ+q3td/IW+KCgChdwFgeUjhcOVgjtZUBJWAY1w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=omiQ58CO; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="omiQ58CO" Received: by mail.gandi.net (Postfix) with ESMTPSA id C5CC4E000E; Fri, 3 May 2024 14:21:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746077; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3MiG7fUumAH1Qk+QreYmndc4hwEFRBfhCe7y3kYMo1c=; b=omiQ58CORkh1ishzPxqGGwzs9wPJhGZZSKllYD7o+7ooX4YdAVi6WCzjmbUqwNPH3BZZJu 29CY9oFEIaqlyCRh9v0KE26Ngx830QBu29pp5MloBCrKjg1RYjzG0WxXobAe7GZRj0YIE+ mXjkxUeM4KkacA7jqmpiFAkFJNq0P8FZJ4qqxAMv++832Ns8BBiABPGTbWmEfXUhgjHMOM +DxO1ayYaWF00DwZRjSqvWTRM+BMwYow1zoYD+aow2OfQdaJBE4hCt9aDpxG9WWcR3qBq9 yHvonhLDQORQmG/GC/eqAdpfaJy93WejnX7bcfKiNEN8o2p8wzRgKRaGGNgxXA== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:54 +0200 Subject: [PATCH v2 09/11] reset: eyeq: add platform driver Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-9-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Add Mobileye EyeQ reset controller driver, for EyeQ5, EyeQ6L and EyeQ6H SoCs. Instances belong to a shared register region called OLB. There is one OLB instance for EyeQ5 and EyeQ6L. There are seven OLB instances on EyeQ6H; three have a reset controller embedded: - West and east get handled by the same compatible. - Acc (accelerator) is another one. Each instance vary in the number and types of reset domains. Instances with single domain expect a single cell, others two. Device is only used as MFD cell. Inherit parent OF node for property fetching helpers to work. Also, don't register match table on platform driver: rather fetch match-data manually using of_match_node(). Match table therefore targets parent MFD compatible. Signed-off-by: Théo Lebrun --- MAINTAINERS | 1 + drivers/reset/Kconfig | 13 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-eyeq.c | 541 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 556 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f386e9da2cd0..36f4001c7f51 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14931,6 +14931,7 @@ F: arch/mips/boot/dts/mobileye/ F: arch/mips/configs/eyeq5_defconfig F: arch/mips/mobileye/board-epm5.its.S F: drivers/clk/clk-eyeq5.c +F: drivers/reset/reset-eyeq5.c F: include/dt-bindings/clock/mobileye,eyeq5-clk.h MODULE SUPPORT diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 85b27c42cf65..18ee99ed8ecc 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -66,6 +66,19 @@ config RESET_BRCMSTB_RESCAL This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on BCM7216. +config RESET_EYEQ + bool "Mobileye EyeQ reset controller" + depends on MFD_SYSCON + depends on MACH_EYEQ5 || MACH_EYEQ6H || COMPILE_TEST + default MACH_EYEQ5 || MACH_EYEQ6H + help + This enables the Mobileye EyeQ reset controller, used in EyeQ5, EyeQ6L + and EyeQ6H SoCs. + + It has one or more domains, with a varying number of resets in each. + Registers are located in a shared register region called OLB. EyeQ6H + has multiple reset instances. + config RESET_GPIO tristate "GPIO reset controller" help diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index fd8b49fa46fc..a4e6fea29800 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_RESET_BCM6345) += reset-bcm6345.o obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o obj-$(CONFIG_RESET_BRCMSTB) += reset-brcmstb.o obj-$(CONFIG_RESET_BRCMSTB_RESCAL) += reset-brcmstb-rescal.o +obj-$(CONFIG_RESET_EYEQ) += reset-eyeq.o obj-$(CONFIG_RESET_GPIO) += reset-gpio.o obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o diff --git a/drivers/reset/reset-eyeq.c b/drivers/reset/reset-eyeq.c new file mode 100644 index 000000000000..07e08b6231af --- /dev/null +++ b/drivers/reset/reset-eyeq.c @@ -0,0 +1,541 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Reset driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms. + * + * Controllers live in a shared register region called OLB. EyeQ5 and EyeQ6L + * have a single OLB instance for a single reset controller. EyeQ6H has seven + * OLB instances; three host reset controllers. + * + * Each reset controller has one or more domain. Domains are of a given type + * (see enum eqr_domain_type), with a valid offset mask (up to 32 resets per + * domain). + * + * Domain types define expected behavior: one-register-per-reset, + * one-bit-per-reset, status detection method, busywait duration, etc. + * + * We use eqr_ as prefix, as-in "EyeQ Reset", but way shorter. + * + * Known resets in EyeQ5 domain 0 (type EQR_EYEQ5_SARCR): + * 3. CAN0 4. CAN1 5. CAN2 6. SPI0 + * 7. SPI1 8. SPI2 9. SPI3 10. UART0 + * 11. UART1 12. UART2 13. I2C0 14. I2C1 + * 15. I2C2 16. I2C3 17. I2C4 18. TIMER0 + * 19. TIMER1 20. TIMER2 21. TIMER3 22. TIMER4 + * 23. WD0 24. EXT0 25. EXT1 26. GPIO + * 27. WD1 + * + * Known resets in EyeQ5 domain 1 (type EQR_EYEQ5_ACRP): + * 0. VMP0 1. VMP1 2. VMP2 3. VMP3 + * 4. PMA0 5. PMA1 6. PMAC0 7. PMAC1 + * 8. MPC0 9. MPC1 10. MPC2 11. MPC3 + * 12. MPC4 + * + * Known resets in EyeQ5 domain 2 (type EQR_EYEQ5_PCIE): + * 0. PCIE0_CORE 1. PCIE0_APB 2. PCIE0_LINK_AXI 3. PCIE0_LINK_MGMT + * 4. PCIE0_LINK_HOT 5. PCIE0_LINK_PIPE 6. PCIE1_CORE 7. PCIE1_APB + * 8. PCIE1_LINK_AXI 9. PCIE1_LINK_MGMT 10. PCIE1_LINK_HOT 11. PCIE1_LINK_PIPE + * 12. MULTIPHY 13. MULTIPHY_APB 15. PCIE0_LINK_MGMT 16. PCIE1_LINK_MGMT + * 17. PCIE0_LINK_PM 18. PCIE1_LINK_PM + * + * Known resets in EyeQ6L domain 0 (type EQR_EYEQ5_SARCR): + * 0. SPI0 1. SPI1 2. UART0 3. I2C0 + * 4. I2C1 5. TIMER0 6. TIMER1 7. TIMER2 + * 8. TIMER3 9. WD0 10. WD1 11. EXT0 + * 12. EXT1 13. GPIO + * + * Known resets in EyeQ6L domain 1 (type EQR_EYEQ5_ACRP): + * 0. VMP0 1. VMP1 2. VMP2 3. VMP3 + * 4. PMA0 5. PMA1 6. PMAC0 7. PMAC1 + * 8. MPC0 9. MPC1 10. MPC2 11. MPC3 + * 12. MPC4 + * + * Known resets in EyeQ6H west/east (type EQR_EYEQ6H_SARCR): + * 0. CAN 1. SPI0 2. SPI1 3. UART0 + * 4. UART1 5. I2C0 6. I2C1 7. -hole- + * 8. TIMER0 9. TIMER1 10. WD 11. EXT TIMER + * 12. GPIO + * + * Known resets in EyeQ6H acc (type EQR_EYEQ5_ACRP): + * 1. XNN0 2. XNN1 3. XNN2 4. XNN3 + * 5. VMP0 6. VMP1 7. VMP2 8. VMP3 + * 9. PMA0 10. PMA1 11. MPC0 12. MPC1 + * 13. MPC2 14. MPC3 15. PERIPH + * + * Abbreviations: + * - PMA: Programmable Macro Array + * - MPC: Multi-threaded Processing Clusters + * - VMP: Vector Microcode Processors + * + * Copyright (C) 2024 Mobileye Vision Technologies Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * A reset ID, as returned by eqr_of_xlate, is a (domain, offset) pair. + * Low byte is domain, rest is offset. + */ +#define ID_DOMAIN_MASK GENMASK(7, 0) +#define ID_OFFSET_MASK GENMASK(31, 8) + +enum eqr_domain_type { + EQR_EYEQ5_SARCR, + EQR_EYEQ5_ACRP, + EQR_EYEQ5_PCIE, + EQR_EYEQ6H_SARCR, +}; + +/* + * Domain type EQR_EYEQ5_SARCR register offsets. + */ +#define EQR_EYEQ5_SARCR_REQUEST (0x000) +#define EQR_EYEQ5_SARCR_STATUS (0x004) + +/* + * Domain type EQR_EYEQ5_ACRP register masks. + * Registers are: base + 4 * offset. + */ +#define EQR_EYEQ5_ACRP_PD_REQ BIT(0) +#define EQR_EYEQ5_ACRP_ST_POWER_DOWN BIT(27) +#define EQR_EYEQ5_ACRP_ST_ACTIVE BIT(29) + +/* + * Domain type EQR_EYEQ6H_SARCR register offsets. + */ +#define EQR_EYEQ6H_SARCR_RST_REQUEST (0x000) +#define EQR_EYEQ6H_SARCR_CLK_STATUS (0x004) +#define EQR_EYEQ6H_SARCR_RST_STATUS (0x008) +#define EQR_EYEQ6H_SARCR_CLK_REQUEST (0x00C) + +struct eqr_busy_wait_timings { + unsigned long sleep_us; + unsigned long timeout_us; +}; + +static const struct eqr_busy_wait_timings eqr_timings[] = { + [EQR_EYEQ5_SARCR] = {1, 10}, + [EQR_EYEQ5_ACRP] = {1, 40 * USEC_PER_MSEC}, /* LBIST implies long timeout. */ + /* EQR_EYEQ5_PCIE does no busy waiting. */ + [EQR_EYEQ6H_SARCR] = {1, 400}, +}; + +#define EQR_MAX_DOMAIN_COUNT 3 + +struct eqr_domain_descriptor { + enum eqr_domain_type type; + u32 valid_mask; +}; + +struct eqr_match_data { + unsigned int domain_count; + const struct eqr_domain_descriptor *domains; +}; + +struct eqr_private { + struct mutex mutexes[EQR_MAX_DOMAIN_COUNT]; + void __iomem *bases[EQR_MAX_DOMAIN_COUNT]; + const struct eqr_match_data *data; + struct reset_controller_dev rcdev; +}; + +#define rcdev_to_priv(rcdev) container_of(rcdev, struct eqr_private, rcdev) + +static u32 eqr_double_readl(void __iomem *addr_a, void __iomem *addr_b, + u32 *dest_a, u32 *dest_b) +{ + *dest_a = readl(addr_a); + *dest_b = readl(addr_b); + return 0; /* read_poll_timeout() op argument must return something. */ +} + +static int eqr_busy_wait_locked(struct eqr_private *priv, struct device *dev, + u32 domain, u32 offset, bool assert) +{ + enum eqr_domain_type domain_type = priv->data->domains[domain].type; + unsigned long sleep_us, timeout_us; + u32 val, mask, val0, val1; + void __iomem *base, *reg; + int ret; + + lockdep_assert_held(&priv->mutexes[domain]); + + base = priv->bases[domain]; + sleep_us = eqr_timings[domain_type].sleep_us; + timeout_us = eqr_timings[domain_type].timeout_us; + + switch (domain_type) { + case EQR_EYEQ5_SARCR: + reg = base + EQR_EYEQ5_SARCR_STATUS; + mask = BIT(offset); + + ret = readl_poll_timeout(reg, val, !(val & mask) == assert, + sleep_us, timeout_us); + break; + + case EQR_EYEQ5_ACRP: + reg = base + 4 * offset; + if (assert) + mask = EQR_EYEQ5_ACRP_ST_POWER_DOWN; + else + mask = EQR_EYEQ5_ACRP_ST_ACTIVE; + + ret = readl_poll_timeout(reg, val, !!(val & mask), + sleep_us, timeout_us); + break; + + case EQR_EYEQ5_PCIE: + ret = 0; /* No busy waiting. */ + break; + + case EQR_EYEQ6H_SARCR: + /* + * Wait until both bits change: + * readl(base + EQR_EYEQ6H_SARCR_RST_STATUS) & BIT(offset) + * readl(base + EQR_EYEQ6H_SARCR_CLK_STATUS) & BIT(offset) + */ + mask = BIT(offset); + ret = read_poll_timeout(eqr_double_readl, val, + (!(val0 & mask) == assert) && + (!(val1 & mask) == assert), + sleep_us, timeout_us, false, + base + EQR_EYEQ6H_SARCR_RST_STATUS, + base + EQR_EYEQ6H_SARCR_CLK_STATUS, + &val0, &val1); + break; + + default: + WARN_ON(1); + ret = -EINVAL; + break; + } + + if (ret == -ETIMEDOUT) + dev_dbg(dev, "%u-%u: timeout\n", domain, offset); + return ret; +} + +static void eqr_assert_locked(struct eqr_private *priv, u32 domain, u32 offset) +{ + enum eqr_domain_type domain_type = priv->data->domains[domain].type; + void __iomem *base, *reg; + u32 val; + + lockdep_assert_held(&priv->mutexes[domain]); + + base = priv->bases[domain]; + + switch (domain_type) { + case EQR_EYEQ5_SARCR: + reg = base + EQR_EYEQ5_SARCR_REQUEST; + writel(readl(reg) & ~BIT(offset), reg); + break; + + case EQR_EYEQ5_ACRP: + reg = base + 4 * offset; + writel(readl(reg) | EQR_EYEQ5_ACRP_PD_REQ, reg); + break; + + case EQR_EYEQ5_PCIE: + writel(readl(base) & ~BIT(offset), base); + break; + + case EQR_EYEQ6H_SARCR: + val = readl(base + EQR_EYEQ6H_SARCR_RST_REQUEST); + val &= ~BIT(offset); + writel(val, base + EQR_EYEQ6H_SARCR_RST_REQUEST); + writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST); + break; + + default: + WARN_ON(1); + break; + } +} + +static int eqr_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct eqr_private *priv = rcdev_to_priv(rcdev); + u32 domain = FIELD_GET(ID_DOMAIN_MASK, id); + u32 offset = FIELD_GET(ID_OFFSET_MASK, id); + + dev_dbg(rcdev->dev, "%u-%u: assert request\n", domain, offset); + + guard(mutex)(&priv->mutexes[domain]); + eqr_assert_locked(priv, domain, offset); + return eqr_busy_wait_locked(priv, rcdev->dev, domain, offset, true); +} + +static void eqr_deassert_locked(struct eqr_private *priv, u32 domain, + u32 offset) +{ + enum eqr_domain_type domain_type = priv->data->domains[domain].type; + void __iomem *base, *reg; + u32 val; + + lockdep_assert_held(&priv->mutexes[domain]); + + base = priv->bases[domain]; + + switch (domain_type) { + case EQR_EYEQ5_SARCR: + reg = base + EQR_EYEQ5_SARCR_REQUEST; + writel(readl(reg) | BIT(offset), reg); + break; + + case EQR_EYEQ5_ACRP: + reg = base + 4 * offset; + writel(readl(reg) & ~EQR_EYEQ5_ACRP_PD_REQ, reg); + break; + + case EQR_EYEQ5_PCIE: + writel(readl(base) | BIT(offset), base); + break; + + case EQR_EYEQ6H_SARCR: + val = readl(base + EQR_EYEQ6H_SARCR_RST_REQUEST); + val |= BIT(offset); + writel(val, base + EQR_EYEQ6H_SARCR_RST_REQUEST); + writel(val, base + EQR_EYEQ6H_SARCR_CLK_REQUEST); + break; + + default: + WARN_ON(1); + break; + } +} + +static int eqr_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct eqr_private *priv = rcdev_to_priv(rcdev); + u32 domain = FIELD_GET(ID_DOMAIN_MASK, id); + u32 offset = FIELD_GET(ID_OFFSET_MASK, id); + + dev_dbg(rcdev->dev, "%u-%u: deassert request\n", domain, offset); + + guard(mutex)(&priv->mutexes[domain]); + eqr_deassert_locked(priv, domain, offset); + return eqr_busy_wait_locked(priv, rcdev->dev, domain, offset, false); +} + +static int eqr_status(struct reset_controller_dev *rcdev, unsigned long id) +{ + u32 domain = FIELD_GET(ID_DOMAIN_MASK, id); + struct eqr_private *priv = rcdev_to_priv(rcdev); + enum eqr_domain_type domain_type = priv->data->domains[domain].type; + u32 offset = FIELD_GET(ID_OFFSET_MASK, id); + void __iomem *base, *reg; + + dev_dbg(rcdev->dev, "%u-%u: status request\n", domain, offset); + + guard(mutex)(&priv->mutexes[domain]); + + base = priv->bases[domain]; + + switch (domain_type) { + case EQR_EYEQ5_SARCR: + reg = base + EQR_EYEQ5_SARCR_STATUS; + return !(readl(reg) & BIT(offset)); + case EQR_EYEQ5_ACRP: + reg = base + 4 * offset; + return !(readl(reg) & EQR_EYEQ5_ACRP_ST_ACTIVE); + case EQR_EYEQ5_PCIE: + return !(readl(base) & BIT(offset)); + case EQR_EYEQ6H_SARCR: + reg = base + EQR_EYEQ6H_SARCR_RST_STATUS; + return !(readl(reg) & BIT(offset)); + default: + return -EINVAL; + } +} + +static const struct reset_control_ops eqr_ops = { + .assert = eqr_assert, + .deassert = eqr_deassert, + .status = eqr_status, +}; + +static int eqr_of_xlate_internal(struct reset_controller_dev *rcdev, + u32 domain, u32 offset) +{ + struct eqr_private *priv = rcdev_to_priv(rcdev); + + if (domain >= priv->data->domain_count || offset > 31 || + !(priv->data->domains[domain].valid_mask & BIT(offset))) { + dev_err(rcdev->dev, "%u-%u: invalid reset\n", domain, offset); + return -EINVAL; + } + + return FIELD_PREP(ID_DOMAIN_MASK, domain) | FIELD_PREP(ID_OFFSET_MASK, offset); +} + +static int eqr_of_xlate_onecell(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + return eqr_of_xlate_internal(rcdev, 0, reset_spec->args[0]); +} + +static int eqr_of_xlate_twocells(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + return eqr_of_xlate_internal(rcdev, reset_spec->args[0], reset_spec->args[1]); +} + +static const struct eqr_domain_descriptor eqr_eyeq5_domains[] = { + { + .type = EQR_EYEQ5_SARCR, + .valid_mask = 0xFFFFFF8, + }, + { + .type = EQR_EYEQ5_ACRP, + .valid_mask = 0x0001FFF, + }, + { + .type = EQR_EYEQ5_PCIE, + .valid_mask = 0x007BFFF, + }, +}; + +static const struct eqr_match_data eqr_eyeq5_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq5_domains), + .domains = eqr_eyeq5_domains, +}; + +static const struct eqr_domain_descriptor eqr_eyeq6l_domains[] = { + { + .type = EQR_EYEQ5_SARCR, + .valid_mask = 0x3FFF, + }, + { + .type = EQR_EYEQ5_ACRP, + .valid_mask = 0x00FF, + }, +}; + +static const struct eqr_match_data eqr_eyeq6l_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq6l_domains), + .domains = eqr_eyeq6l_domains, +}; + +/* West and east OLBs each have an instance. */ +static const struct eqr_domain_descriptor eqr_eyeq6h_we_domains[] = { + { + .type = EQR_EYEQ6H_SARCR, + .valid_mask = 0x1F7F, + }, +}; + +static const struct eqr_match_data eqr_eyeq6h_we_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq6h_we_domains), + .domains = eqr_eyeq6h_we_domains, +}; + +static const struct eqr_domain_descriptor eqr_eyeq6h_acc_domains[] = { + { + .type = EQR_EYEQ5_ACRP, + .valid_mask = 0x7FFF, + }, +}; + +static const struct eqr_match_data eqr_eyeq6h_acc_data = { + .domain_count = ARRAY_SIZE(eqr_eyeq6h_acc_domains), + .domains = eqr_eyeq6h_acc_domains, +}; + +/* + * Table describes OLB system-controller compatibles and is NOT registered on + * platform driver. It gets matched against MFD parent OF node. + */ +static const struct of_device_id eqr_match_table[] = { + { .compatible = "mobileye,eyeq5-olb", .data = &eqr_eyeq5_data }, + { .compatible = "mobileye,eyeq6l-olb", .data = &eqr_eyeq6l_data }, + { .compatible = "mobileye,eyeq6h-west-olb", .data = &eqr_eyeq6h_we_data }, + { .compatible = "mobileye,eyeq6h-east-olb", .data = &eqr_eyeq6h_we_data }, + { .compatible = "mobileye,eyeq6h-acc-olb", .data = &eqr_eyeq6h_acc_data }, + {} +}; +MODULE_DEVICE_TABLE(of, eqr_match_table); + +static int eqr_probe(struct platform_device *pdev) +{ + const struct of_device_id *match; + struct device *dev = &pdev->dev; + struct eqr_private *priv; + unsigned int i; + int ret; + + /* Spawned as MFD sub-device, use parent's OF node. */ + if (!dev->of_node) { + device_set_of_node_from_dev(dev, dev->parent); + if (!dev->of_node) + return -ENODEV; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + match = of_match_node(eqr_match_table, dev->of_node); + if (!match || !match->data) + return -ENODEV; + + priv->data = match->data; + + priv->rcdev.ops = &eqr_ops; + priv->rcdev.owner = THIS_MODULE; + priv->rcdev.dev = dev; + priv->rcdev.of_node = dev->of_node; + + if (priv->data->domain_count == 1) { + priv->rcdev.of_reset_n_cells = 1; + priv->rcdev.of_xlate = eqr_of_xlate_onecell; + } else { + priv->rcdev.of_reset_n_cells = 2; + priv->rcdev.of_xlate = eqr_of_xlate_twocells; + } + + for (i = 0; i < priv->data->domain_count; i++) { + priv->bases[i] = devm_platform_ioremap_resource(pdev, i); + if (IS_ERR(priv->bases[i])) + return PTR_ERR(priv->bases[i]); + } + + for (i = 0; i < priv->data->domain_count; i++) + mutex_init(&priv->mutexes[i]); + + priv->rcdev.nr_resets = 0; + for (i = 0; i < priv->data->domain_count; i++) + priv->rcdev.nr_resets += hweight32(priv->data->domains[i].valid_mask); + + ret = devm_reset_controller_register(dev, &priv->rcdev); + if (ret) + return dev_err_probe(dev, ret, "failed registering reset controller\n"); + + return 0; +} + +static struct platform_driver eqr_driver = { + .probe = eqr_probe, + .driver = { + .name = "reset-eyeq", + }, +}; +builtin_platform_driver(eqr_driver); From patchwork Fri May 3 14:20:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652958 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0460415532B; Fri, 3 May 2024 14:21:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746084; cv=none; b=H11s1vpjIUjjArQE95PqZNd4CkSagQAZiLYHhoHD8MBWDz6uuKlBCbXNBHv94Y1Hlkx6QT+k3X2aNr4UMMZZNsDlTdFDneCqh8K3n+LNDg7JfeWvl+hop3Lw8+7dp5pWv1xmFlcFg+AaC+jAQpLjP7GTxnPkp7Aq3sBgu3sbF8A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746084; c=relaxed/simple; bh=4rRfIUg2vO53nU0BiTMlVvjs/MMF5kzhSROs7DV+43A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AekDj2YCx9jxfvvXZc1tJqF3HhvZnNBfXsWBzkbp9Bqb7fId+TbVBgtOBx3p/T9oNtoaMm76hI/8rmwKXZNAgtxOwCSkZII/I7k5gwYaI8AW+3Be9aPbaB7AsFsAL/cqXcT/OPMujFF17f2P+BlAvf3nrE9a4GCOM18us3cdtWw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=EKuS6xMN; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="EKuS6xMN" Received: by mail.gandi.net (Postfix) with ESMTPSA id BB4F3E0017; Fri, 3 May 2024 14:21:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3eVs1rIllIy84zTmglwVMgCSsEOvy2fJcVtS2At41aQ=; b=EKuS6xMN5YtT60Sabzex/3KrO6Fpp/mRcBTLDQdyLfb4O+ffggAT/SoaxL3rjxQ1vHwLTk e3dtcoJoNNxKnvbR6tr4ugwcTOJDFQNvnPLgKEWYCMBFAgRGRGAboAV7/nEB9ESI6roovg oujkeFQHix/bpSqvYUp6COGGFAfZ2JIpSmbcK/9gC6y7wrzQ8TMFDYxUuY59rdemGGeEg3 ENVGK6kFmd8a+B1NMZ8MPPLo0NDepdgodRmF/ngUABy9sSMGNHIxFrCkp9Bh4xT2t1F65v SG9YrLvkLbthDXGkLmTGv39QUdXrO9U9IgAF50hIC5/o4TbUml1WAjE+rNbmmw== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:55 +0200 Subject: [PATCH v2 10/11] pinctrl: eyeq5: add platform driver Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-10-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com Add the Mobileye EyeQ5 pin controller driver. It belongs to a syscon region called OLB. Existing pins and their function live statically in the driver code rather than in the devicetree, see compatible match data. Device is only used as MFD cell. No compatible is registered; device only appears on EyeQ5. Reviewed-by: Linus Walleij Signed-off-by: Théo Lebrun --- MAINTAINERS | 1 + drivers/pinctrl/Kconfig | 14 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-eyeq5.c | 573 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 589 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 36f4001c7f51..09c3b05035d2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14931,6 +14931,7 @@ F: arch/mips/boot/dts/mobileye/ F: arch/mips/configs/eyeq5_defconfig F: arch/mips/mobileye/board-epm5.its.S F: drivers/clk/clk-eyeq5.c +F: drivers/pinctrl/pinctrl-eyeq5.c F: drivers/reset/reset-eyeq5.c F: include/dt-bindings/clock/mobileye,eyeq5-clk.h diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index d45657aa986a..b266326372e2 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -213,6 +213,20 @@ config PINCTRL_EQUILIBRIUM desired pin functions, configure GPIO attributes for LGM SoC pins. Pin muxing and pin config settings are retrieved from device tree. +config PINCTRL_EYEQ5 + bool "Mobileye EyeQ5 pinctrl driver" + depends on MACH_EYEQ5 || COMPILE_TEST + select PINMUX + select GENERIC_PINCONF + select MFD_SYSCON + default MACH_EYEQ5 + help + Pin controller driver for the Mobileye EyeQ5 platform. It does both + pin config & pin muxing. It does not handle GPIO. + + Pin muxing supports two functions for each pin: first is GPIO, second + is pin-dependent. Pin config is about bias & drive strength. + config PINCTRL_GEMINI bool depends on ARCH_GEMINI diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 2152539b53d5..6113e980cdb2 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o obj-$(CONFIG_PINCTRL_DA9062) += pinctrl-da9062.o obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_EQUILIBRIUM) += pinctrl-equilibrium.o +obj-$(CONFIG_PINCTRL_EYEQ5) += pinctrl-eyeq5.o obj-$(CONFIG_PINCTRL_GEMINI) += pinctrl-gemini.o obj-$(CONFIG_PINCTRL_INGENIC) += pinctrl-ingenic.o obj-$(CONFIG_PINCTRL_K210) += pinctrl-k210.o diff --git a/drivers/pinctrl/pinctrl-eyeq5.c b/drivers/pinctrl/pinctrl-eyeq5.c new file mode 100644 index 000000000000..9e4547aa2a7d --- /dev/null +++ b/drivers/pinctrl/pinctrl-eyeq5.c @@ -0,0 +1,573 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Pinctrl driver for the Mobileye EyeQ5 platform. + * + * The registers are located in a syscon region called OLB. There are two pin + * banks, each being controlled by 5 registers (see enum eq5p_regs) for + * pull-down, pull-up, drive strength and muxing. + * + * For each pin, muxing is between two functions: (0) GPIO or (1) another one + * that is pin-dependent. Functions are declared statically in this driver. + * + * We create pinctrl groups that are 1:1 equivalent to pins: each group has a + * single pin, and its index/selector is the pin number. + * + * We use eq5p_ as prefix, as-in "EyeQ5 Pinctrl", but way shorter. + * + * Copyright (C) 2024 Mobileye Vision Technologies Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "core.h" +#include "pinctrl-utils.h" + +struct eq5p_pinctrl { + struct pinctrl_desc desc; + void __iomem *base; +}; + +enum eq5p_bank { + EQ5P_BANK_A, + EQ5P_BANK_B, + + EQ5P_BANK_COUNT, +}; + +enum eq5p_regs { + EQ5P_PD, + EQ5P_PU, + EQ5P_DS_LOW, + EQ5P_DS_HIGH, + EQ5P_IOCR, + + EQ5P_REG_COUNT, +}; + +static const unsigned int eq5p_regs[EQ5P_BANK_COUNT][EQ5P_REG_COUNT] = { + [EQ5P_BANK_A] = {0x010, 0x014, 0x020, 0x024, 0x000}, + [EQ5P_BANK_B] = {0x018, 0x01C, 0x028, 0x02C, 0x004}, +}; + +/* + * Drive strength; two bits per pin. + */ +#define EQ5P_DS_MASK GENMASK(1, 0) + +/* + * Comments to the right of each pin are the "signal name" in the datasheet. + */ +static const struct pinctrl_pin_desc eq5p_pins[] = { + /* Bank A */ + PINCTRL_PIN(0, "PA0"), /* A0_TIMER0_CK */ + PINCTRL_PIN(1, "PA1"), /* A1_TIMER0_EOC */ + PINCTRL_PIN(2, "PA2"), /* A2_TIMER1_CK */ + PINCTRL_PIN(3, "PA3"), /* A3_TIMER1_EOC */ + PINCTRL_PIN(4, "PA4"), /* A4_TIMER2_CK */ + PINCTRL_PIN(5, "PA5"), /* A5_TIMER2_EOC */ + PINCTRL_PIN(6, "PA6"), /* A6_TIMER5_EXT_INCAP1 */ + PINCTRL_PIN(7, "PA7"), /* A7_TIMER5_EXT_INCAP2 */ + PINCTRL_PIN(8, "PA8"), /* A8_TIMER5_EXT_OUTCMP1 */ + PINCTRL_PIN(9, "PA9"), /* A9_TIMER5_EXT_OUTCMP2 */ + PINCTRL_PIN(10, "PA10"), /* A10_UART_0_TX */ + PINCTRL_PIN(11, "PA11"), /* A11_UART_0_RX */ + PINCTRL_PIN(12, "PA12"), /* A12_UART_1_TX */ + PINCTRL_PIN(13, "PA13"), /* A13_UART_1_RX */ + PINCTRL_PIN(14, "PA14"), /* A14_CAN_0_TX */ + PINCTRL_PIN(15, "PA15"), /* A15_CAN_0_RX */ + PINCTRL_PIN(16, "PA16"), /* A16_CAN_1_TX */ + PINCTRL_PIN(17, "PA17"), /* A17_CAN_1_RX */ + PINCTRL_PIN(18, "PA18"), /* A18_SPI_0_DO */ + PINCTRL_PIN(19, "PA19"), /* A19_SPI_0_DI */ + PINCTRL_PIN(20, "PA20"), /* A20_SPI_0_CK */ + PINCTRL_PIN(21, "PA21"), /* A21_SPI_0_CS0 */ + PINCTRL_PIN(22, "PA22"), /* A22_SPI_0_CS1 */ + PINCTRL_PIN(23, "PA23"), /* A23_SPI_1_DO */ + PINCTRL_PIN(24, "PA24"), /* A24_SPI_1_DI */ + PINCTRL_PIN(25, "PA25"), /* A25_SPI_1_CK */ + PINCTRL_PIN(26, "PA26"), /* A26_SPI_1_CS0 */ + PINCTRL_PIN(27, "PA27"), /* A27_SPI_1_CS1 */ + PINCTRL_PIN(28, "PA28"), /* A28_REF_CLK0 */ + +#define EQ5P_PIN_OFFSET_BANK_B 29 + + /* Bank B */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 0, "PB0"), /* B0_TIMER3_CK */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 1, "PB1"), /* B1_TIMER3_EOC */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 2, "PB2"), /* B2_TIMER4_CK */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 3, "PB3"), /* B3_TIMER4_EOC */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 4, "PB4"), /* B4_TIMER6_EXT_INCAP1 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 5, "PB5"), /* B5_TIMER6_EXT_INCAP2 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 6, "PB6"), /* B6_TIMER6_EXT_OUTCMP1 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 7, "PB7"), /* B7_TIMER6_EXT_OUTCMP2 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 8, "PB8"), /* B8_UART_2_TX */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 9, "PB9"), /* B9_UART_2_RX */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 10, "PB10"), /* B10_CAN_2_TX */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 11, "PB11"), /* B11_CAN_2_RX */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 12, "PB12"), /* B12_SPI_2_DO */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 13, "PB13"), /* B13_SPI_2_DI */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 14, "PB14"), /* B14_SPI_2_CK */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 15, "PB15"), /* B15_SPI_2_CS0 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 16, "PB16"), /* B16_SPI_2_CS1 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 17, "PB17"), /* B17_SPI_3_DO */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 18, "PB18"), /* B18_SPI_3_DI */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 19, "PB19"), /* B19_SPI_3_CK */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 20, "PB20"), /* B20_SPI_3_CS0 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 21, "PB21"), /* B21_SPI_3_CS1 */ + PINCTRL_PIN(EQ5P_PIN_OFFSET_BANK_B + 22, "PB22"), /* B22_MCLK0 */ +}; + +static const char * const gpio_groups[] = { + /* Bank A */ + "PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7", + "PA8", "PA9", "PA10", "PA11", "PA12", "PA13", "PA14", "PA15", + "PA16", "PA17", "PA18", "PA19", "PA20", "PA21", "PA22", "PA23", + "PA24", "PA25", "PA26", "PA27", "PA28", + + /* Bank B */ + "PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7", + "PB8", "PB9", "PB10", "PB11", "PB12", "PB13", "PB14", "PB15", + "PB16", "PB17", "PB18", "PB19", "PB20", "PB21", "PB22", +}; + +/* Groups of functions on bank A */ +static const char * const timer0_groups[] = { "PA0", "PA1" }; +static const char * const timer1_groups[] = { "PA2", "PA3" }; +static const char * const timer2_groups[] = { "PA4", "PA5" }; +static const char * const timer5_groups[] = { "PA6", "PA7", "PA8", "PA9" }; +static const char * const uart0_groups[] = { "PA10", "PA11" }; +static const char * const uart1_groups[] = { "PA12", "PA13" }; +static const char * const can0_groups[] = { "PA14", "PA15" }; +static const char * const can1_groups[] = { "PA16", "PA17" }; +static const char * const spi0_groups[] = { "PA18", "PA19", "PA20", "PA21", "PA22" }; +static const char * const spi1_groups[] = { "PA23", "PA24", "PA25", "PA26", "PA27" }; +static const char * const refclk0_groups[] = { "PA28" }; + +/* Groups of functions on bank B */ +static const char * const timer3_groups[] = { "PB0", "PB1" }; +static const char * const timer4_groups[] = { "PB2", "PB3" }; +static const char * const timer6_groups[] = { "PB4", "PB5", "PB6", "PB7" }; +static const char * const uart2_groups[] = { "PB8", "PB9" }; +static const char * const can2_groups[] = { "PB10", "PB11" }; +static const char * const spi2_groups[] = { "PB12", "PB13", "PB14", "PB15", "PB16" }; +static const char * const spi3_groups[] = { "PB17", "PB18", "PB19", "PB20", "PB21" }; +static const char * const mclk0_groups[] = { "PB22" }; + +static const struct pinfunction eq5p_functions[] = { + /* GPIO having a fixed index is depended upon, see GPIO_FUNC_SELECTOR. */ + PINCTRL_PINFUNCTION("gpio", gpio_groups, ARRAY_SIZE(gpio_groups)), +#define GPIO_FUNC_SELECTOR 0 + + /* Bank A functions */ + PINCTRL_PINFUNCTION("timer0", timer0_groups, ARRAY_SIZE(timer0_groups)), + PINCTRL_PINFUNCTION("timer1", timer1_groups, ARRAY_SIZE(timer1_groups)), + PINCTRL_PINFUNCTION("timer2", timer2_groups, ARRAY_SIZE(timer2_groups)), + PINCTRL_PINFUNCTION("timer5", timer5_groups, ARRAY_SIZE(timer5_groups)), + PINCTRL_PINFUNCTION("uart0", uart0_groups, ARRAY_SIZE(uart0_groups)), + PINCTRL_PINFUNCTION("uart1", uart1_groups, ARRAY_SIZE(uart1_groups)), + PINCTRL_PINFUNCTION("can0", can0_groups, ARRAY_SIZE(can0_groups)), + PINCTRL_PINFUNCTION("can1", can1_groups, ARRAY_SIZE(can1_groups)), + PINCTRL_PINFUNCTION("spi0", spi0_groups, ARRAY_SIZE(spi0_groups)), + PINCTRL_PINFUNCTION("spi1", spi1_groups, ARRAY_SIZE(spi1_groups)), + PINCTRL_PINFUNCTION("refclk0", refclk0_groups, ARRAY_SIZE(refclk0_groups)), + + /* Bank B functions */ + PINCTRL_PINFUNCTION("timer3", timer3_groups, ARRAY_SIZE(timer3_groups)), + PINCTRL_PINFUNCTION("timer4", timer4_groups, ARRAY_SIZE(timer4_groups)), + PINCTRL_PINFUNCTION("timer6", timer6_groups, ARRAY_SIZE(timer6_groups)), + PINCTRL_PINFUNCTION("uart2", uart2_groups, ARRAY_SIZE(uart2_groups)), + PINCTRL_PINFUNCTION("can2", can2_groups, ARRAY_SIZE(can2_groups)), + PINCTRL_PINFUNCTION("spi2", spi2_groups, ARRAY_SIZE(spi2_groups)), + PINCTRL_PINFUNCTION("spi3", spi3_groups, ARRAY_SIZE(spi3_groups)), + PINCTRL_PINFUNCTION("mclk0", mclk0_groups, ARRAY_SIZE(mclk0_groups)), +}; + +static void eq5p_update_bits(const struct eq5p_pinctrl *pctrl, + enum eq5p_bank bank, enum eq5p_regs reg, + u32 mask, u32 val) +{ + void __iomem *ptr = pctrl->base + eq5p_regs[bank][reg]; + + writel((readl(ptr) & ~mask) | (val & mask), ptr); +} + +static bool eq5p_test_bit(const struct eq5p_pinctrl *pctrl, + enum eq5p_bank bank, enum eq5p_regs reg, int offset) +{ + u32 val = readl(pctrl->base + eq5p_regs[bank][reg]); + + if (WARN_ON(offset > 31)) + return false; + + return (val & BIT(offset)) != 0; +} + +static enum eq5p_bank eq5p_pin_to_bank(unsigned int pin) +{ + if (pin < EQ5P_PIN_OFFSET_BANK_B) + return EQ5P_BANK_A; + else + return EQ5P_BANK_B; +} + +static unsigned int eq5p_pin_to_offset(unsigned int pin) +{ + if (pin < EQ5P_PIN_OFFSET_BANK_B) + return pin; + else + return pin - EQ5P_PIN_OFFSET_BANK_B; +} + +static int eq5p_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(eq5p_pins); +} + +static const char *eq5p_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return pctldev->desc->pins[selector].name; +} + +static int eq5p_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + *pins = &pctldev->desc->pins[selector].number; + *num_pins = 1; + return 0; +} + +static int eq5p_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config) +{ + enum pin_config_param param = pinconf_to_config_param(*config); + struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + unsigned int offset = eq5p_pin_to_offset(pin); + enum eq5p_bank bank = eq5p_pin_to_bank(pin); + u32 val_ds, arg; + bool pd, pu; + + pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset); + pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + arg = !(pd || pu); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + arg = pd; + break; + case PIN_CONFIG_BIAS_PULL_UP: + arg = pu; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + offset *= 2; /* two bits per pin */ + if (offset >= 32) { + val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_HIGH]); + offset -= 32; + } else { + val_ds = readl(pctrl->base + eq5p_regs[bank][EQ5P_DS_LOW]); + } + arg = (val_ds >> offset) & EQ5P_DS_MASK; + break; + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + return 0; +} + +static void eq5p_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, + unsigned int pin) +{ + struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const char *pin_name = pctrl->desc.pins[pin].name; + unsigned int offset = eq5p_pin_to_offset(pin); + enum eq5p_bank bank = eq5p_pin_to_bank(pin); + const char *func_name, *bias; + unsigned long ds_config; + u32 drive_strength; + bool pd, pu; + int i, j; + + /* + * First, let's get the function name. All pins have only two functions: + * GPIO (IOCR == 0) and something else (IOCR == 1). + */ + if (eq5p_test_bit(pctrl, bank, EQ5P_IOCR, offset)) { + func_name = NULL; + for (i = 0; i < ARRAY_SIZE(eq5p_functions); i++) { + if (i == GPIO_FUNC_SELECTOR) + continue; + + for (j = 0; j < eq5p_functions[i].ngroups; j++) { + /* Groups and pins are the same thing for us. */ + const char *x = eq5p_functions[i].groups[j]; + + if (strcmp(x, pin_name) == 0) { + func_name = eq5p_functions[i].name; + break; + } + } + + if (func_name) + break; + } + + /* + * We have not found the function attached to this pin, this + * should never occur as all pins have exactly two functions. + */ + if (!func_name) + func_name = "unknown"; + } else { + func_name = eq5p_functions[GPIO_FUNC_SELECTOR].name; + } + + /* Second, we retrieve the bias. */ + pd = eq5p_test_bit(pctrl, bank, EQ5P_PD, offset); + pu = eq5p_test_bit(pctrl, bank, EQ5P_PU, offset); + if (pd && pu) + bias = "both"; + else if (pd && !pu) + bias = "pulldown"; + else if (!pd && pu) + bias = "pullup"; + else + bias = "none"; + + /* Third, we get the drive strength. */ + ds_config = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, 0); + eq5p_pinconf_get(pctldev, pin, &ds_config); + drive_strength = pinconf_to_config_argument(ds_config); + + seq_printf(s, "function=%s bias=%s drive_strength=%d", + func_name, bias, drive_strength); +} + +static const struct pinctrl_ops eq5p_pinctrl_ops = { + .get_groups_count = eq5p_pinctrl_get_groups_count, + .get_group_name = eq5p_pinctrl_get_group_name, + .get_group_pins = eq5p_pinctrl_get_group_pins, + .pin_dbg_show = eq5p_pinctrl_pin_dbg_show, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinctrl_utils_free_map, +}; + +static int eq5p_pinmux_get_functions_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(eq5p_functions); +} + +static const char *eq5p_pinmux_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return eq5p_functions[selector].name; +} + +static int eq5p_pinmux_get_function_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned int *num_groups) +{ + *groups = eq5p_functions[selector].groups; + *num_groups = eq5p_functions[selector].ngroups; + return 0; +} + +static int eq5p_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned int func_selector, unsigned int pin) +{ + struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const char *func_name = eq5p_functions[func_selector].name; + const char *group_name = pctldev->desc->pins[pin].name; + bool is_gpio = func_selector == GPIO_FUNC_SELECTOR; + unsigned int offset = eq5p_pin_to_offset(pin); + enum eq5p_bank bank = eq5p_pin_to_bank(pin); + u32 mask, val; + + dev_dbg(pctldev->dev, "func=%s group=%s\n", func_name, group_name); + + mask = BIT(offset); + val = is_gpio ? 0 : mask; + eq5p_update_bits(pctrl, bank, EQ5P_IOCR, mask, val); + return 0; +} + +static int eq5p_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int pin) +{ + /* Pin numbers and group selectors are the same thing in our case. */ + return eq5p_pinmux_set_mux(pctldev, GPIO_FUNC_SELECTOR, pin); +} + +static const struct pinmux_ops eq5p_pinmux_ops = { + .get_functions_count = eq5p_pinmux_get_functions_count, + .get_function_name = eq5p_pinmux_get_function_name, + .get_function_groups = eq5p_pinmux_get_function_groups, + .set_mux = eq5p_pinmux_set_mux, + .gpio_request_enable = eq5p_pinmux_gpio_request_enable, + .strict = true, +}; + +static int eq5p_pinconf_set_drive_strength(struct pinctrl_dev *pctldev, + unsigned int pin, u32 arg) +{ + struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + unsigned int offset = eq5p_pin_to_offset(pin); + enum eq5p_bank bank = eq5p_pin_to_bank(pin); + unsigned int reg; + u32 mask, val; + + if (arg & ~EQ5P_DS_MASK) { + dev_err(pctldev->dev, "Unsupported drive strength: %u\n", arg); + return -EINVAL; + } + + offset *= 2; /* two bits per pin */ + + if (offset >= 32) { + reg = EQ5P_DS_HIGH; + offset -= 32; + } else { + reg = EQ5P_DS_LOW; + } + + mask = EQ5P_DS_MASK << offset; + val = arg << offset; + eq5p_update_bits(pctrl, bank, reg, mask, val); + return 0; +} + +static int eq5p_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + struct eq5p_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); + const char *pin_name = pctldev->desc->pins[pin].name; + unsigned int offset = eq5p_pin_to_offset(pin); + enum eq5p_bank bank = eq5p_pin_to_bank(pin); + struct device *dev = pctldev->dev; + u32 val = BIT(offset); + unsigned int i; + + for (i = 0; i < num_configs; i++) { + enum pin_config_param param = pinconf_to_config_param(configs[i]); + u32 arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + dev_dbg(dev, "pin=%s bias_disable\n", pin_name); + + eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0); + eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0); + break; + + case PIN_CONFIG_BIAS_PULL_DOWN: + dev_dbg(dev, "pin=%s bias_pull_down arg=%u\n", + pin_name, arg); + + if (arg == 0) /* cannot connect to GND */ + return -ENOTSUPP; + + eq5p_update_bits(pctrl, bank, EQ5P_PD, val, val); + eq5p_update_bits(pctrl, bank, EQ5P_PU, val, 0); + break; + + case PIN_CONFIG_BIAS_PULL_UP: + dev_dbg(dev, "pin=%s bias_pull_up arg=%u\n", + pin_name, arg); + + if (arg == 0) /* cannot connect to VDD */ + return -ENOTSUPP; + + eq5p_update_bits(pctrl, bank, EQ5P_PD, val, 0); + eq5p_update_bits(pctrl, bank, EQ5P_PU, val, val); + break; + + case PIN_CONFIG_DRIVE_STRENGTH: + dev_dbg(dev, "pin=%s drive_strength arg=%u\n", + pin_name, arg); + + eq5p_pinconf_set_drive_strength(pctldev, pin, arg); + break; + + default: + dev_err(dev, "Unsupported pinconf %u\n", param); + return -ENOTSUPP; + } + } + + return 0; +} + +static const struct pinconf_ops eq5p_pinconf_ops = { + .is_generic = true, + .pin_config_get = eq5p_pinconf_get, + .pin_config_set = eq5p_pinconf_set, + /* Pins and groups are equivalent in this driver. */ + .pin_config_group_get = eq5p_pinconf_get, + .pin_config_group_set = eq5p_pinconf_set, +}; + +static int eq5p_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct pinctrl_dev *pctldev; + struct eq5p_pinctrl *pctrl; + int ret; + + pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); + if (!pctrl) + return -ENOMEM; + + pctrl->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pctrl->base)) + return PTR_ERR(pctrl->base); + + pctrl->desc.name = dev_name(dev); + pctrl->desc.pins = eq5p_pins; + pctrl->desc.npins = ARRAY_SIZE(eq5p_pins); + pctrl->desc.pctlops = &eq5p_pinctrl_ops; + pctrl->desc.pmxops = &eq5p_pinmux_ops; + pctrl->desc.confops = &eq5p_pinconf_ops; + pctrl->desc.owner = THIS_MODULE; + + ret = devm_pinctrl_register_and_init(dev, &pctrl->desc, pctrl, &pctldev); + if (ret) + return dev_err_probe(dev, ret, "failed registering pinctrl device\n"); + + ret = pinctrl_enable(pctldev); + if (ret) + return dev_err_probe(dev, ret, "failed enabling pinctrl device\n"); + + return 0; +} + +static struct platform_driver eq5p_driver = { + .probe = eq5p_probe, + .driver = { + .name = "eyeq5-pinctrl", + }, +}; +builtin_platform_driver(eq5p_driver); From patchwork Fri May 3 14:20:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Th=C3=A9o_Lebrun?= X-Patchwork-Id: 13652956 Received: from relay4-d.mail.gandi.net (relay4-d.mail.gandi.net [217.70.183.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0335B15532A; Fri, 3 May 2024 14:21:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746084; cv=none; b=PDtHmDkXEimB4Ps2o1B6d5l1b+GXzELLp13KDTLGwrxnbMN7mW8C10GJk/AcbXuS1snesGokR21QJi5G1dG5cEhNXOr749Zs/dw5hUOk8V161Spgdj1nSkjcBULb8s4JSBJJ+/5cR946hXnYvUtWCmoI/PN72SVOBYJV5D7qKSU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714746084; c=relaxed/simple; bh=o812vmTv/37XhnZr89HkXmMz2BjipKgggsVomAsEQrM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dnosNFOuUA7cOr4A1J60i4jOX6bFjyJxvNVB3SS97Pln0y2LbXfXZtBm/cVoUUBc5O4U9Tu7MFcAeEAgt4KexCpaURkUB5jmRzr/hnshS7IomR7J/pJKpmczC07dXm+A7+fzd0cYbASC+Ho9e6a4ulno4mKGfQS307McMIsXugE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=TvJvxe0S; arc=none smtp.client-ip=217.70.183.196 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="TvJvxe0S" Received: by mail.gandi.net (Postfix) with ESMTPSA id B299EE0014; Fri, 3 May 2024 14:21:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1714746079; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ki2wnu9wyJ0LextOX4U/5GKltoJpPAZbH1kGFJvFKMM=; b=TvJvxe0SXp1+3Ny1RJ+ocZJIzLqXHQug0YGuOIDvgoYXU9cuWSRg4YARsKPmUFv8+HgVcv gzwgHTRFpGGKA7nQn8us+E42KLVgpuGOCShkMyXBXY+VusIt9WPtQO2owS5o3dJr8bRcc5 GAN8hC0OC2Wr98ke419dOedJmHDke8H4yq82JGyr85Nb2y3bZ+6GpVt9gwZ+mkF5NdpIzx mSEYdSgAmyUC9LJWO1nPXy24vgmo4tjVbY9R0auANllLTuyzkuNGTmB/INtMC+67pEjJuC YpAN9LkvPxfTAeXRaxZPhR4TQbOXR2XhEs1NDpNWSEC3Uid6ooN26lkte9GivQ== From: =?utf-8?q?Th=C3=A9o_Lebrun?= Date: Fri, 03 May 2024 16:20:56 +0200 Subject: [PATCH v2 11/11] MIPS: mobileye: eyeq5: add OLB system-controller node Precedence: bulk X-Mailing-List: linux-clk@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240503-mbly-olb-v2-11-95ce5a1e18fe@bootlin.com> References: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> In-Reply-To: <20240503-mbly-olb-v2-0-95ce5a1e18fe@bootlin.com> To: Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Philipp Zabel , Linus Walleij , Greg Kroah-Hartman , "Rafael J. Wysocki" , Lee Jones , Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, Vladimir Kondratiev , Gregory CLEMENT , Thomas Petazzoni , Tawfik Bayouk , =?utf-8?q?Th=C3=A9o_Lebrun?= X-Mailer: b4 0.13.0 X-GND-Sasl: theo.lebrun@bootlin.com The OLB ("Other Logic Block") is a syscon region hosting clock, reset and pin controllers. It contains registers such as I2C speed mode that need to be accessible by other nodes. Remove fixed-clocks previously used; replace references. Add parent crystal clock, fixed at 30MHz. Add pin nodes for all functions. Add mobileye,eyeq5-olb compatible node, hosting clk, reset and pinctrl. Add reset and pinctrl references to UART nodes. Signed-off-by: Théo Lebrun --- .../{eyeq5-fixed-clocks.dtsi => eyeq5-clocks.dtsi} | 54 +++------ arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi | 125 +++++++++++++++++++++ arch/mips/boot/dts/mobileye/eyeq5.dtsi | 22 +++- 3 files changed, 162 insertions(+), 39 deletions(-) diff --git a/arch/mips/boot/dts/mobileye/eyeq5-fixed-clocks.dtsi b/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi similarity index 88% rename from arch/mips/boot/dts/mobileye/eyeq5-fixed-clocks.dtsi rename to arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi index 78f5533a95c6..17a342cc744e 100644 --- a/arch/mips/boot/dts/mobileye/eyeq5-fixed-clocks.dtsi +++ b/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi @@ -3,42 +3,20 @@ * Copyright 2023 Mobileye Vision Technologies Ltd. */ +#include + / { /* Fixed clock */ - pll_cpu: pll-cpu { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <1500000000>; - }; - - pll_vdi: pll-vdi { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <1280000000>; - }; - - pll_per: pll-per { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <2000000000>; - }; - - pll_ddr0: pll-ddr0 { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <1857210000>; - }; - - pll_ddr1: pll-ddr1 { + xtal: xtal { compatible = "fixed-clock"; #clock-cells = <0>; - clock-frequency = <1857210000>; + clock-frequency = <30000000>; }; /* PLL_CPU derivatives */ occ_cpu: occ-cpu { compatible = "fixed-factor-clock"; - clocks = <&pll_cpu>; + clocks = <&olb EQ5C_PLL_CPU>; #clock-cells = <0>; clock-div = <1>; clock-mult = <1>; @@ -101,7 +79,7 @@ mem_clk: mem-clk { }; occ_isram: occ-isram { compatible = "fixed-factor-clock"; - clocks = <&pll_cpu>; + clocks = <&olb EQ5C_PLL_CPU>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; @@ -115,7 +93,7 @@ isram_clk: isram-clk { /* gate ClkRstGen_isram */ }; occ_dbu: occ-dbu { compatible = "fixed-factor-clock"; - clocks = <&pll_cpu>; + clocks = <&olb EQ5C_PLL_CPU>; #clock-cells = <0>; clock-div = <10>; clock-mult = <1>; @@ -130,7 +108,7 @@ si_dbu_tp_pclk: si-dbu-tp-pclk { /* gate ClkRstGen_dbu */ /* PLL_VDI derivatives */ occ_vdi: occ-vdi { compatible = "fixed-factor-clock"; - clocks = <&pll_vdi>; + clocks = <&olb EQ5C_PLL_VDI>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; @@ -144,7 +122,7 @@ vdi_clk: vdi-clk { /* gate ClkRstGen_vdi */ }; occ_can_ser: occ-can-ser { compatible = "fixed-factor-clock"; - clocks = <&pll_vdi>; + clocks = <&olb EQ5C_PLL_VDI>; #clock-cells = <0>; clock-div = <16>; clock-mult = <1>; @@ -158,7 +136,7 @@ can_ser_clk: can-ser-clk { /* gate ClkRstGen_can_ser */ }; i2c_ser_clk: i2c-ser-clk { compatible = "fixed-factor-clock"; - clocks = <&pll_vdi>; + clocks = <&olb EQ5C_PLL_VDI>; #clock-cells = <0>; clock-div = <20>; clock-mult = <1>; @@ -166,7 +144,7 @@ i2c_ser_clk: i2c-ser-clk { /* PLL_PER derivatives */ occ_periph: occ-periph { compatible = "fixed-factor-clock"; - clocks = <&pll_per>; + clocks = <&olb EQ5C_PLL_PER>; #clock-cells = <0>; clock-div = <16>; clock-mult = <1>; @@ -225,7 +203,7 @@ gpio_clk: gpio-clk { }; emmc_sys_clk: emmc-sys-clk { compatible = "fixed-factor-clock"; - clocks = <&pll_per>; + clocks = <&olb EQ5C_PLL_PER>; #clock-cells = <0>; clock-div = <10>; clock-mult = <1>; @@ -233,7 +211,7 @@ emmc_sys_clk: emmc-sys-clk { }; ccf_ctrl_clk: ccf-ctrl-clk { compatible = "fixed-factor-clock"; - clocks = <&pll_per>; + clocks = <&olb EQ5C_PLL_PER>; #clock-cells = <0>; clock-div = <4>; clock-mult = <1>; @@ -241,7 +219,7 @@ ccf_ctrl_clk: ccf-ctrl-clk { }; occ_mjpeg_core: occ-mjpeg-core { compatible = "fixed-factor-clock"; - clocks = <&pll_per>; + clocks = <&olb EQ5C_PLL_PER>; #clock-cells = <0>; clock-div = <2>; clock-mult = <1>; @@ -265,7 +243,7 @@ mjpeg_core_clk: mjpeg-core-clk { /* gate ClkRstGen_mjpeg_gen */ }; fcmu_a_clk: fcmu-a-clk { compatible = "fixed-factor-clock"; - clocks = <&pll_per>; + clocks = <&olb EQ5C_PLL_PER>; #clock-cells = <0>; clock-div = <20>; clock-mult = <1>; @@ -273,7 +251,7 @@ fcmu_a_clk: fcmu-a-clk { }; occ_pci_sys: occ-pci-sys { compatible = "fixed-factor-clock"; - clocks = <&pll_per>; + clocks = <&olb EQ5C_PLL_PER>; #clock-cells = <0>; clock-div = <8>; clock-mult = <1>; diff --git a/arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi b/arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi new file mode 100644 index 000000000000..0b3671013ab4 --- /dev/null +++ b/arch/mips/boot/dts/mobileye/eyeq5-pins.dtsi @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + +/* + * Default pin configuration for Mobileye EyeQ5 boards. We mostly create one + * pin configuration node per function. + */ + +&olb { + timer0_pins: timer0-pins { + function = "timer0"; + pins = "PA0", "PA1"; + }; + timer1_pins: timer1-pins { + function = "timer1"; + pins = "PA2", "PA3"; + }; + timer2_pins: timer2-pins { + function = "timer2"; + pins = "PA4", "PA5"; + }; + pps0_pins: pps0-pin { + function = "timer2"; + pins = "PA4"; + }; + pps1_pins: pps1-pin { + function = "timer2"; + pins = "PA5"; + }; + timer5_ext_pins: timer5-ext-pins { + function = "timer5"; + pins = "PA6", "PA7", "PA8", "PA9"; + }; + timer5_ext_input_pins: timer5-ext-input-pins { + function = "timer5"; + pins = "PA6", "PA7"; + }; + timer5_ext_incap_a_pins: timer5-ext-incap-a-pin { + function = "timer5"; + pins = "PA6"; + }; + timer5_ext_incap_b_pins: timer5-ext-incap-b-pin { + function = "timer5"; + pins = "PA7"; + }; + can0_pins: can0-pins { + function = "can0"; + pins = "PA14", "PA15"; + }; + can1_pins: can1-pins { + function = "can1"; + pins = "PA16", "PA17"; + }; + uart0_pins: uart0-pins { + function = "uart0"; + pins = "PA10", "PA11"; + }; + uart1_pins: uart1-pins { + function = "uart1"; + pins = "PA12", "PA13"; + }; + spi0_pins: spi0-pins { + function = "spi0"; + pins = "PA18", "PA19", "PA20", "PA21", "PA22"; + }; + spi1_pins: spi1-pins { + function = "spi1"; + pins = "PA23", "PA24", "PA25", "PA26", "PA27"; + }; + spi1_slave_pins: spi1-slave-pins { + function = "spi1"; + pins = "PA24", "PA25", "PA26"; + }; + refclk0_pins: refclk0-pin { + function = "refclk0"; + pins = "PA28"; + }; + timer3_pins: timer3-pins { + function = "timer3"; + pins = "PB0", "PB1"; + }; + timer4_pins: timer4-pins { + function = "timer4"; + pins = "PB2", "PB3"; + }; + timer6_ext_pins: timer6-ext-pins { + function = "timer6"; + pins = "PB4", "PB5", "PB6", "PB7"; + }; + timer6_ext_input_pins: timer6-ext-input-pins { + function = "timer6"; + pins = "PB4", "PB5"; + }; + timer6_ext_incap_a_pins: timer6-ext-incap-a-pin { + function = "timer6"; + pins = "PB4"; + }; + timer6_ext_incap_b_pins: timer6-ext-incap-b-pin { + function = "timer6"; + pins = "PB5"; + }; + can2_pins: can2-pins { + function = "can2"; + pins = "PB10", "PB11"; + }; + uart2_pins: uart2-pins { + function = "uart2"; + pins = "PB8", "PB9"; + }; + spi2_pins: spi2-pins { + function = "spi2"; + pins = "PB12", "PB13", "PB14", "PB15", "PB16"; + }; + spi3_pins: spi3-pins { + function = "spi3"; + pins = "PB17", "PB18", "PB19", "PB20", "PB21"; + }; + spi3_slave_pins: spi3-slave-pins { + function = "spi3"; + pins = "PB18", "PB19", "PB20"; + }; + mclk0_pins: mclk0-pin { + function = "mclk0"; + pins = "PB22"; + }; +}; diff --git a/arch/mips/boot/dts/mobileye/eyeq5.dtsi b/arch/mips/boot/dts/mobileye/eyeq5.dtsi index 6cc5980e2fa1..4f80ffdc2e60 100644 --- a/arch/mips/boot/dts/mobileye/eyeq5.dtsi +++ b/arch/mips/boot/dts/mobileye/eyeq5.dtsi @@ -5,7 +5,7 @@ #include -#include "eyeq5-fixed-clocks.dtsi" +#include "eyeq5-clocks.dtsi" / { #address-cells = <2>; @@ -78,6 +78,9 @@ uart0: serial@800000 { interrupts = ; clocks = <&uart_clk>, <&occ_periph>; clock-names = "uartclk", "apb_pclk"; + resets = <&olb 0 10>; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; }; uart1: serial@900000 { @@ -88,6 +91,9 @@ uart1: serial@900000 { interrupts = ; clocks = <&uart_clk>, <&occ_periph>; clock-names = "uartclk", "apb_pclk"; + resets = <&olb 0 11>; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; }; uart2: serial@a00000 { @@ -98,6 +104,18 @@ uart2: serial@a00000 { interrupts = ; clocks = <&uart_clk>, <&occ_periph>; clock-names = "uartclk", "apb_pclk"; + resets = <&olb 0 12>; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + }; + + olb: system-controller@e00000 { + compatible = "mobileye,eyeq5-olb", "syscon", "simple-mfd"; + reg = <0 0xe00000 0x0 0x400>; + #reset-cells = <2>; + #clock-cells = <1>; + clocks = <&xtal>; + clock-names = "ref"; }; gic: interrupt-controller@140000 { @@ -122,3 +140,5 @@ timer { }; }; }; + +#include "eyeq5-pins.dtsi"