From patchwork Fri Mar 15 18:48:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593885 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D188BC54E58 for ; Fri, 15 Mar 2024 18:49:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=XPcHjCbWo4jKIInyp0TgfuTngTvTei16DN9Z/wtE1Xs=; b=NM9q/k3AKIcAgH Vb5G+PZFykws2n882AmRkN+JVwp97FHtkp7DdyugqEymPLnusJR3M9WjU9yA//mqgIia/rKcHq4rD WZTcoUPNXo+YTzD8XXK1Xck2mfOro6WpcAhBS26agIWO6S5Fx8xssnHxE06k//01fnr4Q7qMnOPiU 4jFkYK0lAkxxBiNfQMFGGX/wQE4Q/R76qEi0LkokB26Djc8LZWiGxcMvGFiugDVdw+ePr0caG1ndl 7vRwYauf5m1UaY5s8l45gvXzWS0Gs/Cexl1lOw2ANt9puZAutknqnvrIU9gHyiCE2C7lbCKjzV1r3 MJ39YhlTF5N9kLNAYNPg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCch-00000001DGa-4A4v; Fri, 15 Mar 2024 18:49:43 +0000 Received: from mail-pf1-x430.google.com ([2607:f8b0:4864:20::430]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCcc-00000001DF2-0vXB for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:49:42 +0000 Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-6e6a9fafacdso2141725b3a.2 for ; Fri, 15 Mar 2024 11:49:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528577; x=1711133377; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ekuD/GR/ETK+oPLgoe3fsxeUCpWofF5b/ECIf7CXi9k=; b=lu+L3HwAcnqYDDSnUvddBXOaDDPUbllUyT7aV8lkKKH7KN2VwWbxL8VZaPo5ukDbLk vvLfDZJ0tVNltpN5HbbXyVh/hvu2vwEnI970P6t+U1Djo9dfMEp0Ar1EH+MczblEdLgL wyx4i0M7W6/lQX5LkPv7gcrDqxX8nq0dK5tNzT8CxpQ/uzfeqUvtc658b6eAHRWq0SiB iVOvn1VaMX+KdlQAx7LhfuxRObQo+lvHUbtRfd+FvXLlYwNu9f7oJdyPw5QtDTHcI+61 nJAS09SRpz9CibPvSNFJwpBvlWjKagecq5bbsQbL0m7mnkt6+nBgaGdtGjAN52Yt0iEk Z+rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528577; x=1711133377; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ekuD/GR/ETK+oPLgoe3fsxeUCpWofF5b/ECIf7CXi9k=; b=U0+qB8gKy5j0JZwW3GYxOs8+zdsB5GG9Ey5ZLcVdiK476XRZecJNmZlQgfrlQOiw/t BnLqWHyvDShAGZljAwUANtFIelBsh+ITRIE13sF8jqqOohYP0Iczj0NXhSLZuZUS0yYl GcGD0pyZ3w39wZpP2sBT2i3WSATL8LJzqBbXmBNrM2B6Q0qqeR4PmBVPQKGA5G92J9g6 fCogIj6dACcUYJtggFeyrn1opGkuGBwK/5SRyB3TpufDPYZN3boyA1/JNEcBjZ08ouII sDhmAXfS0spI4dbV+vvLwzJ4PtWXjOjxUMECbNeOVIHpG+R3PaRRgB04Gszp9i5pK1Hc 81bQ== X-Forwarded-Encrypted: i=1; AJvYcCU3pjaNBHjAm/LYIAVDofXez9LwG6DcqLKGTVGli9NXJcQNu79mIFNsI8LnonJYuEp7MZqdqyfyvNOHTolEx3CcaISUm5O8280HK+YSt1GYEegujrA= X-Gm-Message-State: AOJu0YxGrejcvt6UcekFnBplu95lCBMRqnxXVou9P8wxbjl1+dpZZZI7 y3gEY+JAfe5PHfTvI0DOOSkC6VEt4emEXVbRM4I2a72hQcy4SzOS X-Google-Smtp-Source: AGHT+IHqxtAsUgvo4NnLO1aRy+KdmDGkLoMtm8Lp1OEsLkEDiyduFba/9liT290O5AFXVR+nRAdYxw== X-Received: by 2002:a05:6a21:3990:b0:1a1:7711:cb4d with SMTP id ad16-20020a056a21399000b001a17711cb4dmr4993623pzc.36.1710528576938; Fri, 15 Mar 2024 11:49:36 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.49.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:49:36 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Ayush Singh , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org Subject: [PATCH v3 1/8] dt-bindings: misc: Add mikrobus-connector Date: Sat, 16 Mar 2024 00:18:59 +0530 Message-ID: <20240315184908.500352-2-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_114938_297301_CB996A84 X-CRM114-Status: GOOD ( 16.54 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add DT bindings for mikroBUS interface. MikroBUS is an open standard developed by MikroElektronika for connecting add-on boards to microcontrollers or microprocessors. Signed-off-by: Ayush Singh --- .../bindings/misc/mikrobus-connector.yaml | 110 ++++++++++++++++++ MAINTAINERS | 6 + 2 files changed, 116 insertions(+) create mode 100644 Documentation/devicetree/bindings/misc/mikrobus-connector.yaml diff --git a/Documentation/devicetree/bindings/misc/mikrobus-connector.yaml b/Documentation/devicetree/bindings/misc/mikrobus-connector.yaml new file mode 100644 index 000000000000..6eace2c0dddc --- /dev/null +++ b/Documentation/devicetree/bindings/misc/mikrobus-connector.yaml @@ -0,0 +1,110 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/misc/mikrobus-connector.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: mikroBUS add-on board socket + +maintainers: + - Ayush Singh + +properties: + compatible: + const: mikrobus-connector + + pinctrl-0: true + pinctrl-1: true + pinctrl-2: true + pinctrl-3: true + pinctrl-4: true + pinctrl-5: true + pinctrl-6: true + pinctrl-7: true + pinctrl-8: true + + pinctrl-names: + items: + - const: default + - const: pwm_default + - const: pwm_gpio + - const: uart_default + - const: uart_gpio + - const: i2c_default + - const: i2c_gpio + - const: spi_default + - const: spi_gpio + + mikrobus-gpios: + minItems: 11 + maxItems: 12 + + i2c-adapter: + description: i2c adapter attached to the mikrobus socket. + $ref: /schemas/types.yaml#/definitions/phandle + + spi-controller: + description: spi bus number of the spi-master attached to the mikrobus socket. + $ref: /schemas/types.yaml#/definitions/phandle + + uart: + description: uart port attached to the mikrobus socket + $ref: /schemas/types.yaml#/definitions/phandle + + pwms: + description: the pwm-controller corresponding to the mikroBUS PWM pin. + maxItems: 1 + + spi-cs: + description: spi chip-select numbers corresponding to the chip-selects on the mikrobus socket. + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: chip select corresponding to CS pin + - description: chip select corresponding to RST pin + +required: + - compatible + - pinctrl-0 + - pinctrl-1 + - pinctrl-2 + - pinctrl-3 + - pinctrl-4 + - pinctrl-5 + - pinctrl-6 + - pinctrl-7 + - pinctrl-8 + - i2c-adapter + - spi-controller + - spi-cs + - uart + - pwms + - mikrobus-gpios + +additionalProperties: false + +examples: + - | + mikrobus-0 { + compatible = "mikrobus-connector"; + status = "okay"; + pinctrl-names = "default", "pwm_default", "pwm_gpio","uart_default", "uart_gpio", "i2c_default", + "i2c_gpio", "spi_default", "spi_gpio"; + pinctrl-0 = <&P2_03_gpio_input_pin &P1_04_gpio_pin &P1_02_gpio_pin>; + pinctrl-1 = <&P2_01_pwm_pin>; + pinctrl-2 = <&P2_01_gpio_pin>; + pinctrl-3 = <&P2_05_uart_pin &P2_07_uart_pin>; + pinctrl-4 = <&P2_05_gpio_pin &P2_07_gpio_pin>; + pinctrl-5 = <&P2_09_i2c_pin &P2_11_i2c_pin>; + pinctrl-6 = <&P2_09_gpio_pin &P2_11_gpio_pin>; + pinctrl-7 = <&P1_12_spi_pin &P1_10_spi_pin &P1_08_spi_sclk_pin &P1_06_spi_cs_pin>; + pinctrl-8 = <&P1_12_gpio_pin &P1_10_gpio_pin &P1_08_gpio_pin &P1_06_gpio_pin>; + i2c-adapter = <&i2c1>; + spi-controller = <&spi1>; + spi-cs = <0 1>; + uart = <&uart1>; + pwms = <&ehrpwm1 0 500000 0>; + mikrobus-gpios = <&gpio1 18 0> , <&gpio0 23 0>, <&gpio0 30 0> , <&gpio0 31 0>, <&gpio0 15 0>, + <&gpio0 14 0>, <&gpio0 4 0> , <&gpio0 3 0>, <&gpio0 2 0>, <&gpio0 5 0>, + <&gpio2 25 0>, <&gpio2 3 0>; + }; + diff --git a/MAINTAINERS b/MAINTAINERS index 375d34363777..69418a058c6b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14767,6 +14767,12 @@ M: Oliver Neukum S: Maintained F: drivers/usb/image/microtek.* +MIKROBUS +M: Ayush Singh +M: Vaishnav M A +S: Maintained +F: Documentation/devicetree/bindings/misc/mikrobus-connector.yaml + MIKROTIK CRS3XX 98DX3236 BOARD SUPPORT M: Luka Kovacic M: Luka Perkov From patchwork Fri Mar 15 18:49:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593886 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A743EC54E67 for ; Fri, 15 Mar 2024 18:50:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Gkd9hlNSBgd1k0JjSBY3DVsxhI9QZvgu7ioiU7Yv02c=; b=j4MtDqG8aZWpCk 4b90Am2lpAygh7Ku+UBPDXh92yXFwXbNlNOi9YCs5RGQ+zDumJNc7QUDIkYdAQfXlvzdpE6mHx30M 70wW90zl9eKD6hjY5k9L4kDGP8haPSBkzr5QMSrNcPJtImR+aprZeqNYpwtKUoCFDw1plQm8513YL 2ygf2BHzkj4gRGS5rzwf1PQtdF1+qy2fjhjOLmMYDQhjgX+mZvwsNvOmc0sNgp+pLZkdVvrfatWDl rG6ot3KmBF1lMMrtCtwE+J8oeDmH9Ml49tlXuOcL62/Sgm6mywErlD8iXWT4KkK/6iKBs3sVUsyHe 8WAw8zHfVC8sVw70L3hg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCcq-00000001DK3-3y4h; Fri, 15 Mar 2024 18:49:52 +0000 Received: from mail-oo1-xc36.google.com ([2607:f8b0:4864:20::c36]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCck-00000001DHN-37FE for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:49:50 +0000 Received: by mail-oo1-xc36.google.com with SMTP id 006d021491bc7-5a1a069bd16so1374698eaf.3 for ; Fri, 15 Mar 2024 11:49:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528585; x=1711133385; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/0yWXrzwVMKSKKedkMOfXRJscJkRhDPTzhMhPeSYFEA=; b=akPdtHb+wMQIBEG17SIuTG9CDZJiihevyKkku/nps8sb1SRjGs6//xn66gGS4kv7u5 U/9tzvaJO2SHPl9ZFaC/uE0no0LH4WNLv47Inp9jjM53WdUcRYzZvQjrWRrmwofT795/ APib0ZJdkTLulcE5Jg7wYs3eH5XwmRMi6Z6D/sCpelafi/y9twCo0HEq0N92GZsdYDxu o1bjyceeiCrsaA75LUUmRhBndmiP0jWgXDhpdYdtyi4iJkfn+MRK/TwvD3Ym+my184Z4 Yq6HiJ+rZLivKmQdmXB4Z7BJ2/Ycv18Bh2oN9OLpEss5GkRhr3uNzvJejEmn1XWl2+Hz AhtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528585; x=1711133385; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/0yWXrzwVMKSKKedkMOfXRJscJkRhDPTzhMhPeSYFEA=; b=o7Vu6slABpnxW/88mLC5Jlg7/pCOJJIGSuoo5dFLUyq2sUe0Rw+57pqVfj23T1hhBa okwYDsJT3kvwa8gaAc9tQFXexF4iEBtaV49QsylNTSTd3QfnzTrKn3Ws+hRbqS+spqvW AW1/dfy3j545fMmCyB960S30n1y4SIKQrIG1xPqHPk8USli9ZUs59Bhwci2/Zdyh8ark 4TbzZKgDx56GduaEkyhxBlfSypDPPTcpmaQAaLcdPiQKJxNxjd6R9xwUWmC+AUcknnXA YGYDaXPmfuROvrhZOyLCOhcGiiZhh0HEUBmOQVhShxikRdbI/WL0Q9AQ2ucMjGgGsMZw 1nhw== X-Forwarded-Encrypted: i=1; AJvYcCW0Pf66dScQ9Z3I82aqcGHH7NhkHyEpAA9k1NZdGvo48jGo+NBsQlEJVCA0gF8EfkGYX/nYkZv/pGYizmaEZXOTKQ0GvQR+CBQ3DrPlMEmxl751whQ= X-Gm-Message-State: AOJu0YyHoTUcwEC+SSiZpmiZU7MiIV3rphBbzR9azZLrYBhTH4vLjc+f GdmPfSDJ92pIUcBltB2S7YeDMfUpeZBwVbPBMsHJaRGI9OmcM+9V X-Google-Smtp-Source: AGHT+IFg3xw+0ZVudlfm5n/W4rF1HiiD1YucYUMdRXsV4US1Q/BNo5ENea/QqSt1LEy1pQccA1e6fg== X-Received: by 2002:a05:6870:d251:b0:222:3792:d968 with SMTP id h17-20020a056870d25100b002223792d968mr5680859oac.4.1710528585135; Fri, 15 Mar 2024 11:49:45 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.49.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:49:44 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Ayush Singh , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org Subject: [PATCH v3 2/8] w1: Add w1_find_master_device Date: Sat, 16 Mar 2024 00:19:00 +0530 Message-ID: <20240315184908.500352-3-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_114946_820873_68EC87FD X-CRM114-Status: GOOD ( 15.55 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add helper to find w1_master from w1_bus_master, which is present in drvdata of platform device. Signed-off-by: Vaishnav M A Signed-off-by: Ayush Singh --- drivers/w1/w1.c | 6 +++--- drivers/w1/w1_int.c | 27 +++++++++++++++++++++++++++ include/linux/w1.h | 1 + 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index afb1cc4606c5..ce8a3f93f2ef 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -673,9 +673,9 @@ static int __w1_attach_slave_device(struct w1_slave *sl) sl->dev.of_node = of_find_matching_node(sl->master->dev.of_node, sl->family->of_match_table); - dev_set_name(&sl->dev, "%02x-%012llx", - (unsigned int) sl->reg_num.family, - (unsigned long long) sl->reg_num.id); + dev_set_name(&sl->dev, "%s-%02x-%012llx", sl->master->name, + (unsigned int)sl->reg_num.family, + (unsigned long long)sl->reg_num.id); snprintf(&sl->name[0], sizeof(sl->name), "%02x-%012llx", (unsigned int) sl->reg_num.family, diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c index 3a71c5eb2f83..2bfef8e67687 100644 --- a/drivers/w1/w1_int.c +++ b/drivers/w1/w1_int.c @@ -242,3 +242,30 @@ void w1_remove_master_device(struct w1_bus_master *bm) __w1_remove_master_device(found); } EXPORT_SYMBOL(w1_remove_master_device); + +/** + * w1_find_master_device() - find a master device + * @bm: master bus device to search + */ +struct w1_master *w1_find_master_device(struct w1_bus_master *bm) +{ + struct w1_master *dev, *found = NULL; + + list_for_each_entry(dev, &w1_masters, w1_master_entry) { + if (!dev->initialized) + continue; + + if (dev->bus_master->data == bm->data) { + found = dev; + break; + } + } + + if (!found) { + pr_err("device doesn't exist.\n"); + return ERR_PTR(-ENODEV); + } + + return found; +} +EXPORT_SYMBOL(w1_find_master_device); diff --git a/include/linux/w1.h b/include/linux/w1.h index 9a2a0ef39018..24269d0dd5d1 100644 --- a/include/linux/w1.h +++ b/include/linux/w1.h @@ -242,6 +242,7 @@ struct w1_master { int w1_add_master_device(struct w1_bus_master *master); void w1_remove_master_device(struct w1_bus_master *master); +struct w1_master *w1_find_master_device(struct w1_bus_master *master); /** * struct w1_family_ops - operations for a family type From patchwork Fri Mar 15 18:49:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593887 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EB846C54E67 for ; Fri, 15 Mar 2024 18:50:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=INEBEfLs0tFp9aO8fmC2fl2GKoIhAw5SWjukDkYiOyE=; b=Rmcjinx+XUuew5 VtZF/JJvzV7/wtA4egOjjt8vTgYGo5uWBlESXrwHedPrApOlweXfS4NNb1ZkHSM8nY2UxAEH/fWsL C3XtWKqtf06wftt8cqVtpZSiQSHQj+ey71mcfyx9BZ3MvJGaTBRGzz/40f8ZKk8z4uqXz2E678uPY B2w4siVw/NAg3VbrvhIAdMoqCnsgHqAU+1n42D8IQjp+Znm5AAEt0mNJSrDe6sXwE92ALhac4yLzi LUk9KHXolQimzr99KaE2WdxOkz3e8SCgQneYX73MIdG0Y4YAtijqhcOlHq1K8qBNO8SNdrbmbN9Oe T8tb6e8fthIksGLrH2wQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCcw-00000001DN3-3BYc; Fri, 15 Mar 2024 18:49:58 +0000 Received: from mail-pf1-x433.google.com ([2607:f8b0:4864:20::433]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCcs-00000001DKq-3Z1O for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:49:56 +0000 Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-6e6b54a28ebso2524973b3a.2 for ; Fri, 15 Mar 2024 11:49:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528594; x=1711133394; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zcNxWNH5QzToDPbBOtHvsfB896+SEBZGOEHaE/ifDKQ=; b=IZjcaOkS2oZnHhavBR6qz2MtUr33V1Tfv1/ol0i4WjXxOohNWFQz/Gt0GifKVgIVJM AGg//QADDv/TWq8b8Bjk6HPPXeyDZFNhOn1uP+za+rxsEUxOrQE4nIIaFKmmXw+NLETy 7EVgupi1v3vRvgPsWdMFEDsc+EulXWq6O2zISebtiJlrPYyTtfxlwKSHu/TQ4em0kbF0 MWCHLRuwy6E2zlYvKxhLtXYEs5VkGbaKp5EaNKQHRvNpPSvm1fH/fKhI8Hkozh4SU173 1yhxTF7y7Ow2M05Hu54/sIajVx+NHkGxvZYr3EJbhDLGddkMA6kUqo+PUoofTWX7kQAc wksQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528594; x=1711133394; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zcNxWNH5QzToDPbBOtHvsfB896+SEBZGOEHaE/ifDKQ=; b=AVlk8HvBNr19zmX+1h/pxngSSvcpIpIbuC5+QzxKWg6Nv5pfyEJ+r33gp2Y+Dk4vcF Jwbtm8mIVDguqxNa/yQart1MdADqmHUoB6UYGD3kaJPb6McSVqe1s+vukJy1TwFMgp9R pugLavYZ1vxQwHfl7L2qFCRuz+fr6QX/AsysEu6zwPayI0joLV2yZgQGzM8Fe7WYVpLu xdA5VfN0xHute9rBbd8ScklkYu8E0tE3sJUUzdzzDBABidY3Maq01CqOgr4u+tFKNSj9 jOYPO4sgysN05DZHpH4Ke5iX75/O+TehyBe4qMP+a/XZKnqrlGPflHlYnJhRDTY75OfA /lDQ== X-Forwarded-Encrypted: i=1; AJvYcCU+ibGL/S2QOvEKnfgsMb0BYkiAlmm5WXLR7GZL6tG5W3Jf+kq15vfpLlqKZ1TiPmrSghXvXB0Cvepg0q8KFAgS4+1wv2dQvRPmYfuZPzTjD0BKXwQ= X-Gm-Message-State: AOJu0YzdWC9Vy+PHEc/uUXzt3vPThv3ATgEk8pPQxJ2s2EiONx6WjsM3 FD/6/IP/4jBHMvqAIkXSXTTvzKQ0jnC3U3rGxNUPk+M73BUGuB0a X-Google-Smtp-Source: AGHT+IFUoqWC1HtQxdY7BvPQs9oM6UO/StxnSTV9tWAOOYsTsEYNfXK17Rt3JHJT1PSBQMF68CAHlw== X-Received: by 2002:a05:6a20:9f95:b0:1a3:51fc:a62d with SMTP id mm21-20020a056a209f9500b001a351fca62dmr2182876pzb.26.1710528593624; Fri, 15 Mar 2024 11:49:53 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.49.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:49:53 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Ayush Singh , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org Subject: [PATCH v3 3/8] spi: Make of_find_spi_controller_by_node() available Date: Sat, 16 Mar 2024 00:19:01 +0530 Message-ID: <20240315184908.500352-4-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_114954_990061_3438FDA0 X-CRM114-Status: GOOD ( 19.94 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This externalizes and exports the symbol of_find_spi_controller_by_node() from the SPI core akin to how of_find_i2c_adapter_by_node() is already available. As we will need this also for non-dynamic OF setups, we move it under a CONFIG_OF check. Signed-off-by: Ayush Singh --- drivers/spi/spi.c | 206 ++++++++++++++++++++-------------------- include/linux/spi/spi.h | 4 + 2 files changed, 108 insertions(+), 102 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index ba4d3fde2054..9ec507d92f80 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2320,6 +2320,93 @@ void spi_flush_queue(struct spi_controller *ctlr) /*-------------------------------------------------------------------------*/ +static void spi_controller_release(struct device *dev) +{ + struct spi_controller *ctlr; + + ctlr = container_of(dev, struct spi_controller, dev); + kfree(ctlr); +} + +static struct class spi_master_class = { + .name = "spi_master", + .dev_release = spi_controller_release, + .dev_groups = spi_master_groups, +}; + +static ssize_t slave_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct spi_controller *ctlr = container_of(dev, struct spi_controller, + dev); + struct device *child; + + child = device_find_any_child(&ctlr->dev); + return sysfs_emit(buf, "%s\n", child ? to_spi_device(child)->modalias : NULL); +} + +static ssize_t slave_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct spi_controller *ctlr = container_of(dev, struct spi_controller, + dev); + struct spi_device *spi; + struct device *child; + char name[32]; + int rc; + + rc = sscanf(buf, "%31s", name); + if (rc != 1 || !name[0]) + return -EINVAL; + + child = device_find_any_child(&ctlr->dev); + if (child) { + /* Remove registered slave */ + device_unregister(child); + put_device(child); + } + + if (strcmp(name, "(null)")) { + /* Register new slave */ + spi = spi_alloc_device(ctlr); + if (!spi) + return -ENOMEM; + + strscpy(spi->modalias, name, sizeof(spi->modalias)); + + rc = spi_add_device(spi); + if (rc) { + spi_dev_put(spi); + return rc; + } + } + + return count; +} + +static DEVICE_ATTR_RW(slave); + +static struct attribute *spi_slave_attrs[] = { + &dev_attr_slave.attr, + NULL, +}; + +static const struct attribute_group spi_slave_group = { + .attrs = spi_slave_attrs, +}; + +static const struct attribute_group *spi_slave_groups[] = { + &spi_controller_statistics_group, + &spi_slave_group, + NULL, +}; + +static struct class spi_slave_class = { + .name = "spi_slave", + .dev_release = spi_controller_release, + .dev_groups = spi_slave_groups, +}; + #if defined(CONFIG_OF) static void of_spi_parse_dt_cs_delay(struct device_node *nc, struct spi_delay *delay, const char *prop) @@ -2543,6 +2630,23 @@ static void of_register_spi_devices(struct spi_controller *ctlr) } } } + +/* The spi controllers are not using spi_bus, so we find it with another way */ +struct spi_controller *of_find_spi_controller_by_node(struct device_node *node) +{ + struct device *dev; + + dev = class_find_device_by_of_node(&spi_master_class, node); + if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) + dev = class_find_device_by_of_node(&spi_slave_class, node); + if (!dev) + return NULL; + + /* Reference got in class_find_device */ + return container_of(dev, struct spi_controller, dev); +} +EXPORT_SYMBOL_GPL(of_find_spi_controller_by_node); + #else static void of_register_spi_devices(struct spi_controller *ctlr) { } #endif @@ -2942,20 +3046,6 @@ static void acpi_register_spi_devices(struct spi_controller *ctlr) static inline void acpi_register_spi_devices(struct spi_controller *ctlr) {} #endif /* CONFIG_ACPI */ -static void spi_controller_release(struct device *dev) -{ - struct spi_controller *ctlr; - - ctlr = container_of(dev, struct spi_controller, dev); - kfree(ctlr); -} - -static struct class spi_master_class = { - .name = "spi_master", - .dev_release = spi_controller_release, - .dev_groups = spi_master_groups, -}; - #ifdef CONFIG_SPI_SLAVE /** * spi_slave_abort - abort the ongoing transfer request on an SPI slave @@ -2983,79 +3073,6 @@ int spi_target_abort(struct spi_device *spi) return -ENOTSUPP; } EXPORT_SYMBOL_GPL(spi_target_abort); - -static ssize_t slave_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct spi_controller *ctlr = container_of(dev, struct spi_controller, - dev); - struct device *child; - - child = device_find_any_child(&ctlr->dev); - return sysfs_emit(buf, "%s\n", child ? to_spi_device(child)->modalias : NULL); -} - -static ssize_t slave_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct spi_controller *ctlr = container_of(dev, struct spi_controller, - dev); - struct spi_device *spi; - struct device *child; - char name[32]; - int rc; - - rc = sscanf(buf, "%31s", name); - if (rc != 1 || !name[0]) - return -EINVAL; - - child = device_find_any_child(&ctlr->dev); - if (child) { - /* Remove registered slave */ - device_unregister(child); - put_device(child); - } - - if (strcmp(name, "(null)")) { - /* Register new slave */ - spi = spi_alloc_device(ctlr); - if (!spi) - return -ENOMEM; - - strscpy(spi->modalias, name, sizeof(spi->modalias)); - - rc = spi_add_device(spi); - if (rc) { - spi_dev_put(spi); - return rc; - } - } - - return count; -} - -static DEVICE_ATTR_RW(slave); - -static struct attribute *spi_slave_attrs[] = { - &dev_attr_slave.attr, - NULL, -}; - -static const struct attribute_group spi_slave_group = { - .attrs = spi_slave_attrs, -}; - -static const struct attribute_group *spi_slave_groups[] = { - &spi_controller_statistics_group, - &spi_slave_group, - NULL, -}; - -static struct class spi_slave_class = { - .name = "spi_slave", - .dev_release = spi_controller_release, - .dev_groups = spi_slave_groups, -}; #else extern struct class spi_slave_class; /* dummy */ #endif @@ -4749,21 +4766,6 @@ static struct spi_device *of_find_spi_device_by_node(struct device_node *node) return dev ? to_spi_device(dev) : NULL; } -/* The spi controllers are not using spi_bus, so we find it with another way */ -static struct spi_controller *of_find_spi_controller_by_node(struct device_node *node) -{ - struct device *dev; - - dev = class_find_device_by_of_node(&spi_master_class, node); - if (!dev && IS_ENABLED(CONFIG_SPI_SLAVE)) - dev = class_find_device_by_of_node(&spi_slave_class, node); - if (!dev) - return NULL; - - /* Reference got in class_find_device */ - return container_of(dev, struct spi_controller, dev); -} - static int of_spi_notify(struct notifier_block *nb, unsigned long action, void *arg) { diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index e400d454b3f0..f6fb7bad9a90 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1684,4 +1684,8 @@ spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer) return list_is_last(&xfer->transfer_list, &ctlr->cur_msg->transfers); } +#if IS_ENABLED(CONFIG_OF) +struct spi_controller *of_find_spi_controller_by_node(struct device_node *node); +#endif + #endif /* __LINUX_SPI_H */ From patchwork Fri Mar 15 18:49:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593888 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 177A3C54E58 for ; Fri, 15 Mar 2024 18:50:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=p1BtTsGHdKphD92fKHMfTdHZ60iuU6hHDgSf5LUS+yw=; b=WyKDP2GFS2cSfv Ivi27F/se6A9qmB7Q2nC0gfMyO/lfPe8q7nZKgiBDHKhJNu349x/VFaSm94UuKxoSPOoXAf6t+gNf V5jmOWRqR3IEdXFBAzoSeRjXDI45+DIylJYF2xOAhfWmJn8IzX8VBwTUa9udF2qv+YpxX/NWqdIRL NEwYVVPRuBdgvS2//z+kX9x4AW0uHXqlwUfb9n4ADmcKAGySFknGjQxzgPLbxsBNZ9d/TB6jaqOtu EoZ6zWNtutnUFdga9UJXShP3KIwF/P8wl3WFygkuhjfk3gNde/GUGUra86JHu1gu4YlTqGjtd6dXb VQuV4yH+tjCK0AmzUY8w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCd4-00000001DRQ-2M9s; Fri, 15 Mar 2024 18:50:06 +0000 Received: from mail-pf1-x431.google.com ([2607:f8b0:4864:20::431]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCd1-00000001DPQ-2E35 for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:50:04 +0000 Received: by mail-pf1-x431.google.com with SMTP id d2e1a72fcca58-6e6b729669bso2421147b3a.3 for ; Fri, 15 Mar 2024 11:50:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528602; x=1711133402; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=aRqivYuE7DcmOFFhwyqSkRwN4XtrqdDpfy8FtThn+Dk=; b=Tz27Fn2aD4ATaR+z1BeSNcC/CYXanpMI8XabJ26cM2gDBURpwDXQxx8R9iUPoq2NMq k6ciOWLfWUHIfYK8Xt0vRtfB6cVLyu+pze1S0UGRO2KWYzS3n5BrzPJY1oofgt0PQ0dv 3hvjUdsFQq68N1nnSlVxGmjZkg/NKFdVUo0HZ8JhiNAybDP5ZKkpyD/G1TvQ2EAGLiK4 3gFuYiKk7Qo+ZY7aQGJRVXvkCLXjqr3Q4aFAgWgSUSPZCpxKxup0jne9PE8VlDBWqJke bIUK6Ctm0FH5MdrVHJ1BkGdWEBqab0ym7TY/b7tIf+Ucum1xnLyQE5R0cAjFhmFk0Mww rl0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528602; x=1711133402; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=aRqivYuE7DcmOFFhwyqSkRwN4XtrqdDpfy8FtThn+Dk=; b=fI+FIwjPTZk/Y4U/gns21lbQknNBtaDsJfuzH5YUb48Pu1mlTXqQ3JUHs2nv+lkArn ti8NI5ZoLhCeX2SPDVr5YqKQqwnkC88eb0ZjalHbxrHWZ3kkIPR68s8zpm48CXrRuItm igz738qjaANjwT/lqPoLSjZhVLrAwGC9PP0CWc6RQ+Rd+tsXfwmhIkJkXcn1bYXQ3OmZ pkAaVzrJWQ8YOrypFyjoxUtmvjuuNPCqWYa1va6wpgq1AhYKWTBQFFFVyJdzq8PyhhBG penOtbxh8GkgVCDhhXOl4/FNkTZiNyvDUsDOyLwXeCXEL7ynxDXzrkZfZTdTlIuv5rVT XCDQ== X-Forwarded-Encrypted: i=1; AJvYcCWKuX2GO4PxWsulhSPqNUlqpjwYbasCVKapuGSVDyuazpVCl4yMbCIYbIjGyU+2xmttjIL7tYEGwNJUgPYgcW08r8nGDsICYy9wY2ytoLifVhvdqtM= X-Gm-Message-State: AOJu0YxS85k01QMuvuBpVM4oHlEvyD3eYo3G543Pk2L0wFtuvhXpqp5m 8NlHzF48jdiOE0/u6GxPQ76eIcX6fX3OuvLz26xatJY85GSiuK/m X-Google-Smtp-Source: AGHT+IHQbXiA7SVlIsgBVryvm0PGS1QFL0t3DlqmYIaIG83GvhramGbGJdZlO3EHZsPjHP3Bdwk5+g== X-Received: by 2002:a05:6a20:7d9c:b0:1a3:53a0:da1f with SMTP id v28-20020a056a207d9c00b001a353a0da1fmr1195976pzj.12.1710528602430; Fri, 15 Mar 2024 11:50:02 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.49.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:50:02 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Vaishnav M A , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org, Ayush Singh Subject: [PATCH v3 4/8] serdev: add of_ helper to get serdev controller Date: Sat, 16 Mar 2024 00:19:02 +0530 Message-ID: <20240315184908.500352-5-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_115003_608271_50C8346D X-CRM114-Status: GOOD ( 16.13 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Vaishnav M A add of_find_serdev_controller_by_node to obtain a serdev_controller from the device_node, which can help if the serdev_device is not described over device tree and instantiation of the device happens from a different driver, for the same purpose an option to not delete an empty serdev controller is added. Signed-off-by: Vaishnav M A Signed-off-by: Ayush Singh --- drivers/tty/serdev/core.c | 19 +++++++++++++++++++ include/linux/serdev.h | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c index 613cb356b918..5b5b3f2b2e42 100644 --- a/drivers/tty/serdev/core.c +++ b/drivers/tty/serdev/core.c @@ -555,6 +555,19 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl) return 0; } +#if defined(CONFIG_OF) +struct serdev_controller *of_find_serdev_controller_by_node(struct device_node *node) +{ + struct device *dev = bus_find_device_by_of_node(&serdev_bus_type, node); + + if (!dev) + return NULL; + + return (dev->type == &serdev_ctrl_type) ? to_serdev_controller(dev) : NULL; +} +EXPORT_SYMBOL_GPL(of_find_serdev_controller_by_node); +#endif + #ifdef CONFIG_ACPI #define SERDEV_ACPI_MAX_SCAN_DEPTH 32 @@ -785,6 +798,12 @@ int serdev_controller_add(struct serdev_controller *ctrl) pm_runtime_enable(&ctrl->dev); + /* provide option to not delete a serdev controller without devices + * if property is present + */ + if (device_property_present(&ctrl->dev, "force-empty-serdev-controller")) + return 0; + ret_of = of_serdev_register_devices(ctrl); ret_acpi = acpi_serdev_register_devices(ctrl); if (ret_of && ret_acpi) { diff --git a/include/linux/serdev.h b/include/linux/serdev.h index ff78efc1f60d..287d7b9bc10a 100644 --- a/include/linux/serdev.h +++ b/include/linux/serdev.h @@ -117,6 +117,10 @@ static inline struct serdev_controller *to_serdev_controller(struct device *d) return container_of(d, struct serdev_controller, dev); } +#if defined(CONFIG_OF) +struct serdev_controller *of_find_serdev_controller_by_node(struct device_node *node); +#endif + static inline void *serdev_device_get_drvdata(const struct serdev_device *serdev) { return dev_get_drvdata(&serdev->dev); From patchwork Fri Mar 15 18:49:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593889 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8CCA6C54E67 for ; Fri, 15 Mar 2024 18:50:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=FxrU09aGJDIvmvKrhbnzWpluBZfdE20B+tFEcbyN+lo=; b=ZSf7UFePM19n2a VH17GYACsQgq3cnI4b7gM7/uAY1bzsi0yVvBP0CB+nk3wG8VAA3ijtw3pYYBs4/Ae3IPEelG+bLXe EG6VaaqZzyz3ojjtBqrldcm68wckMBcZnkgxDg4odm3ZFzOyi4hE+xwyuNF9S07m4rt5HTjG+9HJ4 dkIPBjH5wkelBkX9W14DGKaeGFLdI9fZZ9VO27yVXDEKFXDfQ9Ar3n/skTcQHMHkEq3dcGVtG7aV9 7kZWJHTU51Xl1bSfoe0LJmS1vyow0WxeNi2Q1cMSL3zKshE5S5DbIas/vgAkctrOMo8XOq6Q2d6at PKUKgLdtqSra/SBscdjQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCdE-00000001DXv-38ls; Fri, 15 Mar 2024 18:50:16 +0000 Received: from mail-pg1-x534.google.com ([2607:f8b0:4864:20::534]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCdA-00000001DUp-3Q3b for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:50:15 +0000 Received: by mail-pg1-x534.google.com with SMTP id 41be03b00d2f7-517ab9a4a13so1963748a12.1 for ; Fri, 15 Mar 2024 11:50:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528611; x=1711133411; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1nbbG9YmsxAe8ShcpMeSH39B4N2p7H9qd49dYIKblRo=; b=D9gayotqQoVKJ3V9M+h6xnFBx31DrbtRLH34OTBfvOEkqCANFO2inz/iEE/VmElqhH UXU6DIE/dYwwyegNSf4UPZJSe0QhnUbtPBzdd5WVEq1tdjIlGUQDHtsoyN+FWjAiSymj 17MTcU7LtvRYFQf/zsnbfcWkT1jhyq1NCj7RcoqVZ/sCoujACOtSEN/fZuvKDwXvJHiM XdnkBRHTkt/Nlfj52s8uHIEPW2E4cI5V6PWc38I5AhvLEegUeRLJ8uMw1t0JMhDzqcnw 3YgWEUOun8EBJb8hzfInERuTWtCT8hP6rBU00GHV7aQQ1ELMPGXRwmzV4OPz5a9HWm39 6bkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528611; x=1711133411; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1nbbG9YmsxAe8ShcpMeSH39B4N2p7H9qd49dYIKblRo=; b=fOoC5+L+DjzFB1NyYfUe/eEGg0XcXO3o9nAzRDw04kqnszb5tAGSjXSq68+r5YbQ0N CS2siqALj5dPCcWcr1PBcl2NaaEsZv1U9UR8h+S1Q4Bs23ueNvTthAJx733EKLv/lcMr aGSVpFkqOlPgQFgl4iiGo9sybISjkfHO2l/SwmR1y8uoh43oPM1je+SJxMj7Jdqh4Ivx XvpgdVUMkhX4bDTmNKRiuuUU2ugmQC/7x5nvdi4WqtebQFiwzqkUJPL1eNg5C9t0lRvH ppmgCqayXFGZTACCnYpLH6qlaUC0ns5Qv6w1pT0BVWjB3oaPuP8vGgL6is4yI/h5uYd5 A2CQ== X-Forwarded-Encrypted: i=1; AJvYcCWTRTYdvyAlp2efhaX8zT5OSd5SQVUGqs+jgTVU/+hMUp3b8qeWJM+oQDqkFi0kEh1zy0RbIjNpbQbYOMUXGoqghV9EeqUoxryXwxxUanANvvR1YNw= X-Gm-Message-State: AOJu0YxlR1yNzZb0vIe0otUcF0V3lHt9PwZF3B11vE5pi2woLDjdkDlK 3hnpuSxCHXBjvDsD3spj6VuSLci4K15Aj/ICKZ9IFZuvyZ/DEU7o X-Google-Smtp-Source: AGHT+IFA9XzN2jLwuRUEijbwT8pIPy83qqcaER/RU0ti3qY2ElIKDW3ox6g28Xxuwh3Y/MTEOyOcvg== X-Received: by 2002:a05:6a20:1450:b0:1a1:4808:7c95 with SMTP id a16-20020a056a20145000b001a148087c95mr5266375pzi.37.1710528610773; Fri, 15 Mar 2024 11:50:10 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.50.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:50:10 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Ayush Singh , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org Subject: [PATCH v3 5/8] regulator: fixed-helper: export regulator_register_always_on Date: Sat, 16 Mar 2024 00:19:03 +0530 Message-ID: <20240315184908.500352-6-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_115012_877546_4F659BBE X-CRM114-Status: GOOD ( 10.52 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Export regulator_register_always_on() to allow use in kernel modules Signed-off-by: Ayush Singh --- drivers/regulator/fixed-helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c index 2d5a42b2b3d8..0e9784009c07 100644 --- a/drivers/regulator/fixed-helper.c +++ b/drivers/regulator/fixed-helper.c @@ -59,3 +59,4 @@ struct platform_device *regulator_register_always_on(int id, const char *name, return &data->pdev; } +EXPORT_SYMBOL_GPL(regulator_register_always_on); From patchwork Fri Mar 15 18:49:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593890 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 248A1C54E67 for ; Fri, 15 Mar 2024 18:50:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=UwZDKToJYTArAjX0fn4hHLO9c61f2Pu3C8pp75hQY0s=; b=gkd1jY+AbULfsF 5kwpknmYGo6eowHiyU6vI9nEodsfCYSVwicRQ5Z2WugpmUtiwWtIoq0olqjTG1pNN4XaLDIs3FUH7 8W34UDLdE8FxJ7wRiTgF8WvELKdXGp7xOdlmvukch+nQ/ARXWsSotmSc6hXfFMOB2AllUytDb/HCw byySIJE73MaHmyRH5L+NHA3E36qgvfuSqwvie3HVyaqtfC4mrd7l4nDWF+KrSMAQtBHAQKdogGh7w NTJ6whQnVhB4dT74Jj40ydWbc5O2hXGKAeVtuHrhxmAZsm7aI7dpDenMdM1gT/RERzshL6M6UNIpf 1L2Tmo1CCqBC5qfMb4MA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCdO-00000001Deo-1rj9; Fri, 15 Mar 2024 18:50:26 +0000 Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCdI-00000001DaR-4BM9 for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:50:23 +0000 Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-6e6082eab17so2237500b3a.1 for ; Fri, 15 Mar 2024 11:50:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528620; x=1711133420; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FJyaNPyqw2IdFqRfIn2kDaXxflGKfLH9sUwkufABDcs=; b=Iw+njkeM7tMNcIChcLgQqanSBWtkd6FAFbWnVyrBTxpkn5j6AyYweZMpuoZkdFudV4 DeaCZEChnmSVoewFonfDgKTb/ec2CM9wX8paPHvRCEDA0NmxAo0y/gVOGxjaXaehhssH iP8+zdPBsH88Z8H5GP7J/mdk6eJPov8QF2/klWdDQqrjquhSkHBKuyazce7EVEi7L3PI SiVNJzHM9EM4F/nvl52o+ZXEnllrgZh3bIH/w2ke/6WBasKNby2ZT/5lsGKY/6vF0nrf HKlpIJqmIsxjcKSdaK31KmO4QnVX03xPr7xIKmQTDlb2Y1xc4EHxhuAfo2hZQ6w5aMEy hCsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528620; x=1711133420; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FJyaNPyqw2IdFqRfIn2kDaXxflGKfLH9sUwkufABDcs=; b=b2T64RT0zsRhk0URngmUPoUYjLKxyuDj51+XzB3bHB56ktWJbMNuSVFUmoQbXHLMaN Vh9qlskoISVHTGfjS0cdKa3bmqcpJu5LlCoLh6AOnFoFxk9nEmeOKiZOMx5FRuwK5agR /W1z6h8EkG+27thF9mlesgMq5D/Cf3nzBYr9XsJWCxrKUryLuWpfePnS6M4JiZUslbnN G+dFFgU2X4y1J1J355w2A7vg8PIty3Fs2hvH5+jEeAibZSSSTTjBi2NJE8suoN5OufcS 3q7PTzECxk3B54/UGnnEFc8s/FrSpBwz5naA1j14LxO2gCa4BG2PyQTvRcbeY8SZgTL2 kCvQ== X-Forwarded-Encrypted: i=1; AJvYcCXUbreed0aKLmvFoukVz6xiCpEea3XP9sOhxB+czofSLYB43PH8A8lGGxYyCUXLtvDjJQu15GHO7cdPxQ2IcNnLCUjaG5H6bqOc9c4LQTzUIDgs8x4= X-Gm-Message-State: AOJu0YzZ4em2/7GQwXNue2O/s6B/J/R88AboHf/08IQtiqqrBrk2jgZm kp/ZGf1ZwWt3vLhiivgQ9Rrsct9Hm5OcTgIXGYpE0JJhB+Dixbhq X-Google-Smtp-Source: AGHT+IHc7+H5cEGXqrctyaczStsb2ofp2iqgC06SmJk8JFddX4axEu63mOXWmXYSgCe6j/iNGhO5GQ== X-Received: by 2002:a05:6a00:841:b0:6e6:8c49:f2f6 with SMTP id q1-20020a056a00084100b006e68c49f2f6mr6144160pfk.24.1710528619634; Fri, 15 Mar 2024 11:50:19 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.50.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:50:19 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Ayush Singh , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org Subject: [PATCH v3 6/8] greybus: Add mikroBUS manifest types Date: Sat, 16 Mar 2024 00:19:04 +0530 Message-ID: <20240315184908.500352-7-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_115021_182366_42A5BC5A X-CRM114-Status: GOOD ( 13.74 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add data structures for parsing mikroBUS manifests, which are based on greybus manifest. Signed-off-by: Ayush Singh --- include/linux/greybus/greybus_manifest.h | 49 ++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/include/linux/greybus/greybus_manifest.h b/include/linux/greybus/greybus_manifest.h index bef9eb2093e9..83241e19d9b3 100644 --- a/include/linux/greybus/greybus_manifest.h +++ b/include/linux/greybus/greybus_manifest.h @@ -23,6 +23,9 @@ enum greybus_descriptor_type { GREYBUS_TYPE_STRING = 0x02, GREYBUS_TYPE_BUNDLE = 0x03, GREYBUS_TYPE_CPORT = 0x04, + GREYBUS_TYPE_MIKROBUS = 0x05, + GREYBUS_TYPE_PROPERTY = 0x06, + GREYBUS_TYPE_DEVICE = 0x07, }; enum greybus_protocol { @@ -151,6 +154,49 @@ struct greybus_descriptor_cport { __u8 protocol_id; /* enum greybus_protocol */ } __packed; +/* + * A mikrobus descriptor is used to describe the details + * about the bus ocnfiguration for the add-on board + * connected to the mikrobus port. + */ +struct greybus_descriptor_mikrobus { + __u8 pin_state[12]; +} __packed; + +/* + * A property descriptor is used to pass named properties + * to device drivers through the unified device properties + * interface under linux/property.h + */ +struct greybus_descriptor_property { + __u8 length; + __u8 id; + __u8 propname_stringid; + __u8 type; + __u8 value[]; +} __packed; + +/* + * A device descriptor is used to describe the + * details required by a add-on board device + * driver. + */ +struct greybus_descriptor_device { + __u8 id; + __u8 driver_stringid; + __u8 protocol; + __u8 reg; + __le32 max_speed_hz; + __u8 irq; + __u8 irq_type; + __u8 mode; + __u8 prop_link; + __u8 gpio_link; + __u8 reg_link; + __u8 clock_link; + __u8 pad[1]; +} __packed; + struct greybus_descriptor_header { __le16 size; __u8 type; /* enum greybus_descriptor_type */ @@ -164,6 +210,9 @@ struct greybus_descriptor { struct greybus_descriptor_interface interface; struct greybus_descriptor_bundle bundle; struct greybus_descriptor_cport cport; + struct greybus_descriptor_mikrobus mikrobus; + struct greybus_descriptor_property property; + struct greybus_descriptor_device device; }; } __packed; From patchwork Fri Mar 15 18:49:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593892 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C05EBC54E58 for ; Fri, 15 Mar 2024 18:51:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Kkj5CUwOWwYr9bY2H+tu34pCa7pRZDgSWiOA4l5rogg=; b=02WIuVW5o/xWJb tGnRiOQ0z1AyI2hV/3i5JhNfl9n2LIdJXPOZ4BD98daEXLUpUebNifh9jQvE1ouLpY5d9EOpKichG JoWGRzw6x1i1Ye3rtkOetnzT2W5fDyAsmHAdGzZD9F2eXWYqBX6dMUIZiby04qbb3pJZBrGGN9Bnw ESiLYOO0UJndot32dqyWHa387F1HeqKD1cyiFaVcSWia6IyxWWQTezQew6Iv1A5w2M0/RWeSFBGuj 7ilaf6gcbuEESiazxyBu7qwwsQbwMU2A6CTTIFBcA4SXdgrXWxrSied0hZZl4Dq7pzsO/pyb1LQeh NkO/cJHQ4w9FRdZEYA9w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCdm-00000001Ds3-1XiT; Fri, 15 Mar 2024 18:50:50 +0000 Received: from mail-pf1-x436.google.com ([2607:f8b0:4864:20::436]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCdS-00000001DgZ-14xo for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:50:45 +0000 Received: by mail-pf1-x436.google.com with SMTP id d2e1a72fcca58-6e70193efa3so488494b3a.0 for ; Fri, 15 Mar 2024 11:50:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528629; x=1711133429; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=I9UjJ7GsfcyWYu7K9Rx0VvyWCR0FVADYowXJP0DCHdw=; b=XEm8mT9lL0T31fx6IfZe8IDo0dIZMnUef5yHoJv3/Z1fNFUqC5t9VbIDv1+wA7HQ+g r5wlt0gbBnsGAJCwMjTDGdGUWrvI90VmlxkoknzHYWGnEzaJpRJhmtmJZFn80xIVrQ/c o/eiwmZa4v9GlQxNZBVvlzi+mAQhBomj0aJYavbc3eXQtj0kaWXUuWmOA/yrGLH2KSnp kgfLhG2z59g2OHk/5xlN/uJ0hRC9mm8MBISA8EBfqYYXNjqG+74oCAb2+siXx43sxYpr 0OvNg2IskwRPDfDwvOXqq0PnaZyl4zESRe6BA18Ygxh0Pt0Hr865Y0Sha3jNZ4JFsMg8 qPPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528629; x=1711133429; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=I9UjJ7GsfcyWYu7K9Rx0VvyWCR0FVADYowXJP0DCHdw=; b=hToLtIIkAOv4xoKuiL7t6X9Z5sgwgE/CV0YCfIvsdAm+ydRKrGdrvO683NBt9ZhGtE T0ZW+d7YRwQbAzkSaO5XbpT5+V66uvLrG1z8eD06inL06y1OVtZwHla9KGOvcGL8iNdA G3NSUpJxfInngD5lhfoXmqjWSSWLRByUg9S3AU1DXO+t3+pzDBZjoe/JUGbIAf3CQby4 b8Xhs4lvYXkbNzGn8r0CmWXGvt9lASg4A1VIW4pm6xWTOq3KpkXHvgEc+EwwxneOxvMd fQqrBhunmPVbRVgq6qGh5qtSrxNtB1IhG3zzq36ZFj1ZmrpmCYIPMdkbfj97duNLprwj FVXA== X-Forwarded-Encrypted: i=1; AJvYcCWUNvP3LwhpnT9O1H/jWQ2/XTLqjBJTEIiqxW5kj827dwXdHm2t3en48deApw4+qfuh0mJEBvabJk1QcPzRk6ozOXE8U3cM1WHLgfjSs4Mz8n/R+30= X-Gm-Message-State: AOJu0YzCKlMuJkib1lm0DVu9fPj3l/abAn9+7NyiF0X2ezRPdoqhtxva WnrOneIjUHPvAdHIQnhHVdGxRzUr2Cca0z26ib2o7xkqq+WHuS9U X-Google-Smtp-Source: AGHT+IHIK2oeyfiUn0JBesE1uDiyFTvFVanUxllwDGEKH8lwSZ7ATWmd7nm7r8oEXCgcS5WKonCljw== X-Received: by 2002:a05:6a20:8e19:b0:1a3:49e9:1b6f with SMTP id y25-20020a056a208e1900b001a349e91b6fmr5070984pzj.8.1710528628351; Fri, 15 Mar 2024 11:50:28 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:50:27 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Ayush Singh , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org Subject: [PATCH v3 7/8] mikrobus: Add mikrobus driver Date: Sat, 16 Mar 2024 00:19:05 +0530 Message-ID: <20240315184908.500352-8-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_115031_221967_25BF634C X-CRM114-Status: GOOD ( 29.13 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org - Setup I2C, SPI, serdev controllers associated with mikrobus connector - Check if a board with valid mikroBUS manifest is connected - Parse the manifest and register the device to kernel Signed-off-by: Vaishnav M A Signed-off-by: Ayush Singh --- MAINTAINERS | 1 + drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/mikrobus/Kconfig | 19 + drivers/misc/mikrobus/Makefile | 6 + drivers/misc/mikrobus/mikrobus_core.c | 942 ++++++++++++++++++++++ drivers/misc/mikrobus/mikrobus_core.h | 201 +++++ drivers/misc/mikrobus/mikrobus_id.c | 229 ++++++ drivers/misc/mikrobus/mikrobus_manifest.c | 502 ++++++++++++ drivers/misc/mikrobus/mikrobus_manifest.h | 20 + 10 files changed, 1922 insertions(+) create mode 100644 drivers/misc/mikrobus/Kconfig create mode 100644 drivers/misc/mikrobus/Makefile create mode 100644 drivers/misc/mikrobus/mikrobus_core.c create mode 100644 drivers/misc/mikrobus/mikrobus_core.h create mode 100644 drivers/misc/mikrobus/mikrobus_id.c create mode 100644 drivers/misc/mikrobus/mikrobus_manifest.c create mode 100644 drivers/misc/mikrobus/mikrobus_manifest.h diff --git a/MAINTAINERS b/MAINTAINERS index 69418a058c6b..83bc5e48bef9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14772,6 +14772,7 @@ M: Ayush Singh M: Vaishnav M A S: Maintained F: Documentation/devicetree/bindings/misc/mikrobus-connector.yaml +F: drivers/misc/mikrobus/* MIKROTIK CRS3XX 98DX3236 BOARD SUPPORT M: Luka Kovacic diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 4fb291f0bf7c..3d5c36205c6c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -591,4 +591,5 @@ source "drivers/misc/cardreader/Kconfig" source "drivers/misc/uacce/Kconfig" source "drivers/misc/pvpanic/Kconfig" source "drivers/misc/mchp_pci1xxxx/Kconfig" +source "drivers/misc/mikrobus/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index ea6ea5bbbc9c..b9ac88055b87 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -68,3 +68,4 @@ obj-$(CONFIG_TMR_INJECT) += xilinx_tmr_inject.o obj-$(CONFIG_TPS6594_ESM) += tps6594-esm.o obj-$(CONFIG_TPS6594_PFSM) += tps6594-pfsm.o obj-$(CONFIG_NSM) += nsm.o +obj-y += mikrobus/ diff --git a/drivers/misc/mikrobus/Kconfig b/drivers/misc/mikrobus/Kconfig new file mode 100644 index 000000000000..f0770006b4fe --- /dev/null +++ b/drivers/misc/mikrobus/Kconfig @@ -0,0 +1,19 @@ +menuconfig MIKROBUS + tristate "Module for instantiating devices on mikroBUS ports" + depends on GPIOLIB + depends on W1 + depends on W1_MASTER_GPIO + help + This option enables the mikroBUS driver. mikroBUS is an add-on + board socket standard that offers maximum expandability with + the smallest number of pins. The mikroBUS driver instantiates + devices on a mikroBUS port described by identifying data present + in an add-on board resident EEPROM, more details on the mikroBUS + driver support and discussion can be found in this eLinux wiki : + elinux.org/Mikrobus + + + Say Y here to enable support for this driver. + + To compile this code as a module, chose M here: the module + will be called mikrobus.ko diff --git a/drivers/misc/mikrobus/Makefile b/drivers/misc/mikrobus/Makefile new file mode 100644 index 000000000000..c89ff2abb80e --- /dev/null +++ b/drivers/misc/mikrobus/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# mikroBUS Core + +obj-$(CONFIG_MIKROBUS) += mikrobus.o +mikrobus-y := mikrobus_core.o mikrobus_manifest.o +obj-$(CONFIG_MIKROBUS) += mikrobus_id.o diff --git a/drivers/misc/mikrobus/mikrobus_core.c b/drivers/misc/mikrobus/mikrobus_core.c new file mode 100644 index 000000000000..17718ed315b9 --- /dev/null +++ b/drivers/misc/mikrobus/mikrobus_core.c @@ -0,0 +1,942 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mikroBUS driver for instantiating add-on + * board devices with an identifier EEPROM + * + * Copyright 2020 Vaishnav M A, BeagleBoard.org Foundation. + * Copyright 2024 Ayush Singh + */ + +#define pr_fmt(fmt) "mikrobus:%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mikrobus_core.h" +#include "mikrobus_manifest.h" + +#define MIKROBUS_ID_EEPROM_MANIFEST_ADDR 0x20 + +static DEFINE_MUTEX(core_lock); +static DEFINE_IDR(mikrobus_port_idr); +static struct class_compat *mikrobus_port_compat_class; +int __mikrobus_first_dynamic_bus_num; +static bool is_registered; +static int mikrobus_port_id_eeprom_probe(struct mikrobus_port *port); + +const char *MIKROBUS_PINCTRL_STR[] = { "pwm", "uart", "i2c", "spi" }; + +const struct bus_type mikrobus_bus_type = { + .name = "mikrobus", +}; +EXPORT_SYMBOL_GPL(mikrobus_bus_type); + +int mikrobus_port_scan_eeprom(struct mikrobus_port *port) +{ + const u16 manifest_start_addr = MIKROBUS_ID_EEPROM_MANIFEST_ADDR; + struct addon_board_info *board; + int manifest_size, retval; + char header[12], *buf; + + if (port->skip_scan) + return -EINVAL; + + retval = nvmem_device_read(port->eeprom, manifest_start_addr, 12, header); + if (retval != 12) { + return dev_err_probe(&port->dev, -EINVAL, "failed to fetch manifest header %d\n", + retval); + } + + manifest_size = mikrobus_manifest_header_validate(header, 12); + if (manifest_size < 0) { + return dev_err_probe(&port->dev, -EINVAL, "invalid manifest size %d\n", + manifest_size); + } + + buf = kzalloc(manifest_size, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + retval = nvmem_device_read(port->eeprom, manifest_start_addr, manifest_size, buf); + if (retval != manifest_size) { + retval = + dev_err_probe(&port->dev, -EINVAL, "failed to fetch manifest %d\n", retval); + goto err_free_buf; + } + + board = kzalloc(sizeof(*board), GFP_KERNEL); + if (!board) { + retval = -ENOMEM; + goto err_free_buf; + } + + w1_reset_bus(port->w1_master); + /* set RST HIGH */ + gpiod_direction_output(port->gpios->desc[MIKROBUS_PIN_RST], 1); + set_bit(W1_ABORT_SEARCH, &port->w1_master->flags); + + INIT_LIST_HEAD(&board->manifest_descs); + INIT_LIST_HEAD(&board->devices); + retval = mikrobus_manifest_parse(board, buf, manifest_size); + if (!retval) { + retval = dev_err_probe(&port->dev, -EINVAL, "failed to parse manifest, size %d\n", + manifest_size); + goto err_free_board; + } + + retval = mikrobus_board_register(port, board); + if (retval) { + dev_err(&port->dev, "failed to register board %s\n", board->name); + goto err_free_board; + } + + kfree(buf); + return 0; + +err_free_board: + kfree(board); +err_free_buf: + kfree(buf); + return retval; +} +EXPORT_SYMBOL_GPL(mikrobus_port_scan_eeprom); + +static ssize_t name_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%s\n", to_mikrobus_port(dev)->name); +} +static DEVICE_ATTR_RO(name); + +static ssize_t new_device_store(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + struct mikrobus_port *port = to_mikrobus_port(dev); + struct addon_board_info *board; + int retval; + + if (port->board) + return dev_err_probe(dev, -EBUSY, "already has board registered\n"); + + board = kzalloc(sizeof(*board), GFP_KERNEL); + if (!board) + return -ENOMEM; + + INIT_LIST_HEAD(&board->manifest_descs); + INIT_LIST_HEAD(&board->devices); + retval = mikrobus_manifest_parse(board, (void *)buf, count); + if (!retval) { + retval = dev_err_probe(dev, -EINVAL, "failed to parse manifest\n"); + goto err_free_board; + } + + retval = mikrobus_board_register(port, board); + if (retval) { + retval = dev_err_probe(dev, -EINVAL, "failed to register board %s\n", board->name); + goto err_free_board; + } + + return count; + +err_free_board: + kfree(board); + return retval; +} +static DEVICE_ATTR_WO(new_device); + +static ssize_t delete_device_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct mikrobus_port *port = to_mikrobus_port(dev); + unsigned long id; + + if (kstrtoul(buf, 0, &id)) + return dev_err_probe(dev, -EINVAL, "cannot parse board id"); + + if (!port->board) + return dev_err_probe(dev, -ENODEV, "does not have registered boards"); + + mikrobus_board_unregister(port, port->board); + return count; +} +static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, 0200, NULL, delete_device_store); + +static struct attribute *mikrobus_port_attrs[] = { &dev_attr_new_device.attr, + &dev_attr_delete_device.attr, + &dev_attr_name.attr, NULL }; +ATTRIBUTE_GROUPS(mikrobus_port); + +static void mikrobus_port_release(struct device *dev) +{ + struct mikrobus_port *port = to_mikrobus_port(dev); + + mutex_lock(&core_lock); + idr_remove(&mikrobus_port_idr, port->id); + mutex_unlock(&core_lock); + + kfree(port); +} + +const struct device_type mikrobus_port_type = { + .groups = mikrobus_port_groups, + .release = mikrobus_port_release, +}; +EXPORT_SYMBOL_GPL(mikrobus_port_type); + +static int mikrobus_w1_master_match(struct device *dev, const void *data) +{ + struct mikrobus_port *port; + + if (dev->type != &mikrobus_port_type) + return 0; + + port = to_mikrobus_port(dev); + + return port->w1_master == data; +} + +struct mikrobus_port *mikrobus_find_port_by_w1_master(struct w1_master *master) +{ + struct device *dev; + + dev = bus_find_device(&mikrobus_bus_type, NULL, master, mikrobus_w1_master_match); + if (!dev) + return NULL; + + return (dev->type == &mikrobus_port_type) ? to_mikrobus_port(dev) : NULL; +} +EXPORT_SYMBOL(mikrobus_find_port_by_w1_master); + +int mikrobus_port_pinctrl_select(struct mikrobus_port *port) +{ + struct pinctrl_state *state; + int retval, i; + + for (i = 0; i < MIKROBUS_NUM_PINCTRL_STATE; i++) { + state = pinctrl_lookup_state(port->pinctrl, port->pinctrl_selected[i]); + if (!IS_ERR(state)) { + retval = pinctrl_select_state(port->pinctrl, state); + if (retval) { + return dev_err_probe(&port->dev, retval, + "failed to select state %s\n", + port->pinctrl_selected[i]); + } + dev_dbg(&port->dev, "setting pinctrl %s\n", port->pinctrl_selected[i]); + } else { + return dev_err_probe(&port->dev, PTR_ERR(state), + "failed to find state %s\n", + port->pinctrl_selected[i]); + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(mikrobus_port_pinctrl_select); + +static int mikrobus_port_pinctrl_setup(struct mikrobus_port *port, struct addon_board_info *board) +{ + int retval; + + if (board->pin_state[MIKROBUS_PIN_PWM] == MIKROBUS_STATE_PWM) + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_PWM], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_PWM], PINCTRL_STATE_DEFAULT); + else + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_PWM], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_PWM], MIKROBUS_PINCTRL_STATE_GPIO); + + if (board->pin_state[MIKROBUS_PIN_RX] == MIKROBUS_STATE_UART) + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_UART], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_UART], PINCTRL_STATE_DEFAULT); + else + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_UART], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_UART], MIKROBUS_PINCTRL_STATE_GPIO); + + if (board->pin_state[MIKROBUS_PIN_SCL] == MIKROBUS_STATE_I2C) + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_I2C], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_I2C], PINCTRL_STATE_DEFAULT); + else + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_I2C], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_I2C], MIKROBUS_PINCTRL_STATE_GPIO); + + if (board->pin_state[MIKROBUS_PIN_MOSI] == MIKROBUS_STATE_SPI) + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_SPI], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_SPI], PINCTRL_STATE_DEFAULT); + else + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_SPI], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_SPI], MIKROBUS_PINCTRL_STATE_GPIO); + + retval = mikrobus_port_pinctrl_select(port); + if (retval) + dev_err(&port->dev, "failed to select pinctrl states [%d]", retval); + + return retval; +} + +static int mikrobus_irq_get(struct mikrobus_port *port, int irqno, int irq_type) +{ + int irq; + + if (irqno > port->gpios->ndescs - 1) + return dev_err_probe(&port->dev, -ENODEV, "GPIO %d does not exist", irqno); + + irq = gpiod_to_irq(port->gpios->desc[irqno]); + if (irq < 0) + return dev_err_probe(&port->dev, -EINVAL, "could not get irq %d", irqno); + + irq_set_irq_type(irq, irq_type); + + return irq; +} + +static int mikrobus_gpio_setup(struct gpio_desc *gpio, int gpio_state) +{ + switch (gpio_state) { + case MIKROBUS_STATE_INPUT: + return gpiod_direction_input(gpio); + case MIKROBUS_STATE_OUTPUT_HIGH: + return gpiod_direction_output(gpio, 1); + case MIKROBUS_STATE_OUTPUT_LOW: + return gpiod_direction_output(gpio, 0); + case MIKROBUS_STATE_PWM: + case MIKROBUS_STATE_SPI: + case MIKROBUS_STATE_I2C: + default: + return 0; + } +} + +static char *mikrobus_gpio_chip_name_get(struct mikrobus_port *port, int gpio) +{ + struct gpio_chip *gpiochip; + + if (gpio > port->gpios->ndescs - 1) + return NULL; + + gpiochip = gpiod_to_chip(port->gpios->desc[gpio]); + return kmemdup(gpiochip->label, MIKROBUS_NAME_SIZE, GFP_KERNEL); +} + +static int mikrobus_gpio_hwnum_get(struct mikrobus_port *port, int gpio) +{ + struct gpio_chip *gpiochip; + + if (gpio > port->gpios->ndescs - 1) + return -ENODEV; + + gpiochip = gpiod_to_chip(port->gpios->desc[gpio]); + return desc_to_gpio(port->gpios->desc[gpio]) - gpiochip->base; +} + +static void mikrobus_board_device_release_all(struct addon_board_info *info) +{ + struct board_device_info *dev, *next; + + list_for_each_entry_safe(dev, next, &info->devices, links) { + list_del(&dev->links); + kfree(dev); + } +} + +static int mikrobus_device_register(struct mikrobus_port *port, struct board_device_info *dev, + char *board_name) +{ + struct regulator_consumer_supply regulator; + struct gpiod_lookup_table *lookup; + char devname[MIKROBUS_NAME_SIZE]; + struct spi_board_info *spi_info; + struct i2c_board_info *i2c_info; + struct serdev_device *serdev; + struct platform_device *pdev; + struct fwnode_handle *fwnode; + struct spi_device *spi; + int i, retval; + u64 *val; + + dev_info(&port->dev, "registering device : %s", dev->drv_name); + + if (dev->gpio_lookup) { + lookup = dev->gpio_lookup; + + switch (dev->protocol) { + case GREYBUS_PROTOCOL_SPI: + snprintf(devname, sizeof(devname), "%s.%u", dev_name(&port->spi_ctrl->dev), + port->chip_select[dev->reg]); + lookup->dev_id = kmemdup(devname, MIKROBUS_NAME_SIZE, GFP_KERNEL); + break; + case GREYBUS_PROTOCOL_RAW: + snprintf(devname, sizeof(devname), "%s.%u", dev->drv_name, dev->reg); + lookup->dev_id = kmemdup(devname, MIKROBUS_NAME_SIZE, GFP_KERNEL); + break; + default: + lookup->dev_id = dev->drv_name; + } + + dev_info(&port->dev, "adding lookup table : %s", lookup->dev_id); + + for (i = 0; i < dev->num_gpio_resources; i++) { + lookup->table[i].key = + mikrobus_gpio_chip_name_get(port, lookup->table[i].chip_hwnum); + lookup->table[i].chip_hwnum = + mikrobus_gpio_hwnum_get(port, lookup->table[i].chip_hwnum); + } + + gpiod_add_lookup_table(lookup); + } + + if (dev->regulators) { + if (dev->protocol == GREYBUS_PROTOCOL_SPI) { + snprintf(devname, sizeof(devname), "%s.%u", dev_name(&port->spi_ctrl->dev), + port->chip_select[dev->reg]); + regulator.dev_name = kmemdup(devname, MIKROBUS_NAME_SIZE, GFP_KERNEL); + } else if (dev->protocol == GREYBUS_PROTOCOL_RAW) { + snprintf(devname, sizeof(devname), "%s.%u", dev->drv_name, dev->reg); + regulator.dev_name = kmemdup(devname, MIKROBUS_NAME_SIZE, GFP_KERNEL); + } else { + regulator.dev_name = dev->drv_name; + } + + for (i = 0; i < dev->num_regulators; i++) { + val = dev->regulators[i].value.u64_data; + regulator.supply = + kmemdup(dev->regulators[i].name, MIKROBUS_NAME_SIZE, GFP_KERNEL); + dev_info(&port->dev, "adding fixed regulator %llu uv, %s for %s", *val, + regulator.supply, regulator.dev_name); + regulator_register_always_on(0, dev->regulators[i].name, ®ulator, 1, + *val); + } + } + + switch (dev->protocol) { + case GREYBUS_PROTOCOL_SPI: + spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL); + strscpy_pad(spi_info->modalias, dev->drv_name, sizeof(spi_info->modalias) - 1); + if (dev->irq) + spi_info->irq = mikrobus_irq_get(port, dev->irq, dev->irq_type); + if (dev->properties) { + fwnode = fwnode_create_software_node(dev->properties, NULL); + spi_info->swnode = to_software_node(fwnode); + } + spi_info->chip_select = port->chip_select[dev->reg]; + spi_info->max_speed_hz = dev->max_speed_hz; + spi_info->mode = dev->mode; + + spi = spi_new_device(port->spi_ctrl, spi_info); + if (!spi) + return dev_err_probe(&port->dev, -ENOMEM, "failed to create spi device"); + + if (dev->clocks) { + for (i = 0; i < dev->num_clocks; i++) { + val = dev->clocks[i].value.u64_data; + dev_info(&port->dev, "adding fixed clock %s, %llu hz", + dev->clocks[i].name, *val); + clk_register_fixed_rate(&spi->dev, dev->clocks[i].name, devname, 0, + *val); + } + } + + dev->dev_client = (void *)spi; + break; + case GREYBUS_PROTOCOL_I2C: + i2c_info = kzalloc(sizeof(*i2c_info), GFP_KERNEL); + if (!i2c_info) + return -ENOMEM; + + strscpy_pad(i2c_info->type, dev->drv_name, sizeof(i2c_info->type) - 1); + if (dev->irq) + i2c_info->irq = mikrobus_irq_get(port, dev->irq, dev->irq_type); + if (dev->properties) { + fwnode = fwnode_create_software_node(dev->properties, NULL); + i2c_info->swnode = to_software_node(fwnode); + } + i2c_info->addr = dev->reg; + dev->dev_client = (void *)i2c_new_client_device(port->i2c_adap, i2c_info); + break; + case GREYBUS_PROTOCOL_RAW: + pdev = platform_device_alloc(dev->drv_name, 0); + if (!pdev) + return -ENOMEM; + + if (dev->properties) { + retval = device_create_managed_software_node(&pdev->dev, dev->properties, + NULL); + if (retval) + return dev_err_probe(&port->dev, retval, + "failed to create software node"); + } + dev->dev_client = pdev; + platform_device_add(dev->dev_client); + break; + case GREYBUS_PROTOCOL_UART: + serdev = serdev_device_alloc(port->ser_ctrl); + if (!serdev) + return -ENOMEM; + + if (dev->properties) + device_create_managed_software_node(&serdev->dev, dev->properties, NULL); + + dev->dev_client = serdev; + serdev_device_add(serdev); + break; + default: + return -EINVAL; + } + + return 0; +} + +static void mikrobus_device_unregister(struct mikrobus_port *port, struct board_device_info *dev, + char *board_name) +{ + dev_info(&port->dev, "removing device %s\n", dev->drv_name); + if (dev->gpio_lookup) { + gpiod_remove_lookup_table(dev->gpio_lookup); + kfree(dev->gpio_lookup); + } + + kfree(dev->properties); + + switch (dev->protocol) { + case GREYBUS_PROTOCOL_SPI: + spi_unregister_device((struct spi_device *)dev->dev_client); + break; + case GREYBUS_PROTOCOL_I2C: + i2c_unregister_device((struct i2c_client *)dev->dev_client); + break; + case GREYBUS_PROTOCOL_RAW: + platform_device_unregister((struct platform_device *)dev->dev_client); + break; + case GREYBUS_PROTOCOL_UART: + serdev_device_remove((struct serdev_device *)dev->dev_client); + break; + } +} + +int mikrobus_board_register(struct mikrobus_port *port, struct addon_board_info *board) +{ + struct board_device_info *devinfo, *next; + int retval, i; + + if (WARN_ON(list_empty(&board->devices))) + return false; + + if (port->pinctrl) { + retval = mikrobus_port_pinctrl_setup(port, board); + if (retval) + dev_err(&port->dev, "failed to setup pinctrl state [%d]", retval); + } + + if (port->gpios) { + for (i = 0; i < port->gpios->ndescs; i++) { + retval = mikrobus_gpio_setup(port->gpios->desc[i], board->pin_state[i]); + if (retval) + dev_err(&port->dev, "failed to setup gpio %d, state %d", i, + board->pin_state[i]); + + gpiochip_free_own_desc(port->gpios->desc[i]); + } + } + + list_for_each_entry_safe(devinfo, next, &board->devices, links) + mikrobus_device_register(port, devinfo, board->name); + + port->board = board; + return 0; +} +EXPORT_SYMBOL_GPL(mikrobus_board_register); + +void mikrobus_board_unregister(struct mikrobus_port *port, struct addon_board_info *board) +{ + struct board_device_info *devinfo, *next; + + if (WARN_ON(list_empty(&board->devices))) + return; + + list_for_each_entry_safe(devinfo, next, &board->devices, links) + mikrobus_device_unregister(port, devinfo, board->name); + + mikrobus_board_device_release_all(board); + kfree(board); + port->board = NULL; +} +EXPORT_SYMBOL_GPL(mikrobus_board_unregister); + +static int mikrobus_port_id_eeprom_probe(struct mikrobus_port *port) +{ + static const char drvname[MIKROBUS_NAME_SIZE] = "w1-gpio\0"; + struct platform_device *mikrobus_id_eeprom_w1_device; + struct gpiod_lookup_table *lookup; + char devname[MIKROBUS_NAME_SIZE]; + struct w1_bus_master *bm; + int retval; + + sprintf(port->pinctrl_selected[MIKROBUS_PINCTRL_SPI], "%s_%s", + MIKROBUS_PINCTRL_STR[MIKROBUS_PINCTRL_SPI], MIKROBUS_PINCTRL_STATE_GPIO); + + retval = mikrobus_port_pinctrl_select(port); + + /* set RST LOW */ + gpiod_direction_output(port->gpios->desc[MIKROBUS_PIN_RST], 0); + + lookup = kzalloc(struct_size(lookup, table, 1), GFP_KERNEL); + if (!lookup) + return -ENOMEM; + + retval = snprintf(devname, sizeof(devname), "%s.%u", drvname, port->id); + lookup->dev_id = kmemdup(devname, retval + 1, GFP_KERNEL); + lookup->table[0].key = mikrobus_gpio_chip_name_get(port, MIKROBUS_PIN_CS); + lookup->table[0].flags = GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN; + lookup->table[0].chip_hwnum = mikrobus_gpio_hwnum_get(port, MIKROBUS_PIN_CS); + + gpiochip_free_own_desc(port->gpios->desc[MIKROBUS_PIN_CS]); + gpiod_add_lookup_table(lookup); + + mikrobus_id_eeprom_w1_device = platform_device_register_simple(drvname, port->id, NULL, 0); + if (IS_ERR(mikrobus_id_eeprom_w1_device)) { + retval = PTR_ERR(mikrobus_id_eeprom_w1_device); + dev_err(&port->dev, "failed to register w1-gpio device %d", retval); + goto early_exit; + } + + port->w1_gpio = mikrobus_id_eeprom_w1_device; + + bm = (struct w1_bus_master *)platform_get_drvdata(mikrobus_id_eeprom_w1_device); + if (!bm) { + dev_err(&port->dev, "failed to get w1_bus_master"); + return 0; + } + + port->w1_master = w1_find_master_device(bm); + if (!port->w1_master) { + dev_err(&port->dev, "failed to find W1 GPIO master, port [%s]", port->name); + goto early_exit; + } + + port->w1_master->search_count = 4; + + return 0; + +early_exit: + gpiod_remove_lookup_table(lookup); + kfree(lookup); + return -ENODEV; +} + +int mikrobus_port_register(struct mikrobus_port *port) +{ + struct device *dev = &port->dev; + int retval, id; + + if (WARN_ON(!is_registered)) + return -EAGAIN; + + if (dev->of_node) { + id = of_alias_get_id(dev->of_node, "mikrobus"); + if (id >= 0) { + port->id = id; + mutex_lock(&core_lock); + id = idr_alloc(&mikrobus_port_idr, port, port->id, port->id + 1, + GFP_KERNEL); + mutex_unlock(&core_lock); + if (WARN(id < 0, "couldn't get idr")) + return id == -ENOSPC ? -EBUSY : id; + } + } else { + mutex_lock(&core_lock); + id = idr_alloc(&mikrobus_port_idr, port, __mikrobus_first_dynamic_bus_num, 0, + GFP_KERNEL); + mutex_unlock(&core_lock); + if (id < 0) + return id; + + port->id = id; + } + + port->dev.bus = &mikrobus_bus_type; + port->dev.type = &mikrobus_port_type; + strscpy_pad(port->name, "mikrobus-port", sizeof(port->name) - 1); + dev_set_name(&port->dev, "mikrobus-%d", port->id); + dev_info(&port->dev, "registering port mikrobus-%d ", port->id); + + retval = device_register(&port->dev); + if (retval) { + dev_err(&port->dev, "port '%d': can't register device (%d)", port->id, retval); + put_device(&port->dev); + return retval; + } + + retval = class_compat_create_link(mikrobus_port_compat_class, &port->dev, port->dev.parent); + if (retval) + dev_warn(&port->dev, "failed to create compatibility class link"); + + if (!port->w1_master) { + dev_info(&port->dev, "mikrobus port %d eeprom empty probing default eeprom", + port->id); + mutex_lock(&core_lock); + retval = mikrobus_port_id_eeprom_probe(port); + mutex_unlock(&core_lock); + } + + return retval; +} +EXPORT_SYMBOL_GPL(mikrobus_port_register); + +void mikrobus_port_delete(struct mikrobus_port *port) +{ + struct mikrobus_port *found; + + mutex_lock(&core_lock); + found = idr_find(&mikrobus_port_idr, port->id); + mutex_unlock(&core_lock); + if (found != port) { + pr_err("port [%s] not registered", port->name); + return; + } + + if (port->board) { + dev_err(&port->dev, "attempting to delete port with registered boards, port [%s]\n", + port->name); + return; + } + + if (port->eeprom) { + nvmem_device_put(port->eeprom); + platform_device_unregister(port->w1_gpio); + } + + class_compat_remove_link(mikrobus_port_compat_class, &port->dev, port->dev.parent); + device_unregister(&port->dev); + mutex_lock(&core_lock); + idr_remove(&mikrobus_port_idr, port->id); + mutex_unlock(&core_lock); + memset(&port->dev, 0, sizeof(port->dev)); +} +EXPORT_SYMBOL_GPL(mikrobus_port_delete); + +static int mikrobus_port_probe_pinctrl_setup(struct mikrobus_port *port) +{ + struct device *dev = port->dev.parent; + struct pinctrl_state *state; + int retval, i; + + state = pinctrl_lookup_state(port->pinctrl, PINCTRL_STATE_DEFAULT); + if (!IS_ERR(state)) { + retval = pinctrl_select_state(port->pinctrl, state); + if (retval) { + return dev_err_probe(dev, retval, "Failed to select state %s\n", + PINCTRL_STATE_DEFAULT); + } + } else { + return dev_err_probe(dev, PTR_ERR(state), "failed to find state %s\n", + PINCTRL_STATE_DEFAULT); + } + + for (i = 0; i < MIKROBUS_NUM_PINCTRL_STATE; i++) { + port->pinctrl_selected[i] = kmalloc(MIKROBUS_PINCTRL_NAME_SIZE, GFP_KERNEL); + sprintf(port->pinctrl_selected[i], "%s_%s", MIKROBUS_PINCTRL_STR[i], + PINCTRL_STATE_DEFAULT); + } + + retval = mikrobus_port_pinctrl_select(port); + if (retval) + dev_err(dev, "failed to select pinctrl states [%d]", retval); + + return retval; +} + +static int mikrobus_port_probe(struct platform_device *pdev) +{ + struct device_node *i2c_adap_np, *uart_np, *spi_np; + struct device *dev = &pdev->dev; + struct mikrobus_port *port; + int retval; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return -ENOMEM; + + /* I2C setup */ + i2c_adap_np = of_parse_phandle(dev->of_node, "i2c-adapter", 0); + if (!i2c_adap_np) { + retval = dev_err_probe(dev, -ENODEV, "cannot parse i2c-adapter"); + goto err_port; + } + port->i2c_adap = of_find_i2c_adapter_by_node(i2c_adap_np); + of_node_put(i2c_adap_np); + + /* GPIO setup */ + port->gpios = gpiod_get_array(dev, "mikrobus", GPIOD_OUT_LOW); + if (IS_ERR(port->gpios)) { + retval = PTR_ERR(port->gpios); + dev_err(dev, "failed to get gpio array [%d]", retval); + goto err_port; + } + + /* SPI setup */ + spi_np = of_parse_phandle(dev->of_node, "spi-controller", 0); + if (!spi_np) { + retval = dev_err_probe(dev, -ENODEV, "cannot parse spi-controller"); + goto err_port; + } + port->spi_ctrl = of_find_spi_controller_by_node(spi_np); + of_node_put(spi_np); + if (!port->spi_ctrl) { + retval = dev_err_probe(dev, -ENODEV, "cannot find spi controller"); + goto err_port; + } + retval = device_property_read_u32_array(dev, "spi-cs", port->chip_select, MIKROBUS_NUM_CS); + if (retval) { + dev_err(dev, "failed to get spi-cs [%d]", retval); + goto err_port; + } + + /* UART setup */ + uart_np = of_parse_phandle(dev->of_node, "uart", 0); + if (!uart_np) { + retval = dev_err_probe(dev, -ENODEV, "cannot parse uart"); + goto err_port; + } + port->ser_ctrl = of_find_serdev_controller_by_node(uart_np); + of_node_put(uart_np); + if (!port->ser_ctrl) { + retval = dev_err_probe(dev, -ENODEV, "cannot find uart controller"); + goto err_port; + } + + /* PWM setup */ + port->pwm = devm_pwm_get(dev, NULL); + if (!port->pwm) { + retval = dev_err_probe(dev, -ENODEV, "cannot find pwm controller"); + goto err_port; + } + + /* pinctrl setup */ + port->pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(port->pinctrl)) { + retval = PTR_ERR(port->pinctrl); + dev_err(dev, "failed to get pinctrl [%d]", retval); + goto err_port; + } + port->dev.parent = dev; + port->dev.of_node = pdev->dev.of_node; + retval = mikrobus_port_probe_pinctrl_setup(port); + if (retval) { + dev_err(dev, "failed to setup pinctrl [%d]", retval); + goto err_port; + } + + retval = mikrobus_port_register(port); + if (retval) { + dev_err(dev, "port : can't register port [%d]", retval); + goto err_port; + } + + platform_set_drvdata(pdev, port); + + return 0; + +err_port: + kfree(port); + return retval; +} + +static int mikrobus_port_remove(struct platform_device *pdev) +{ + struct mikrobus_port *port = platform_get_drvdata(pdev); + + mikrobus_port_delete(port); + return 0; +} + +static const struct of_device_id mikrobus_port_of_match[] = { + { .compatible = "mikrobus-connector" }, + {}, +}; +MODULE_DEVICE_TABLE(of, mikrobus_port_of_match); + +static struct platform_driver mikrobus_port_driver = { + .probe = mikrobus_port_probe, + .remove = mikrobus_port_remove, + .driver = { + .name = "mikrobus", + .of_match_table = of_match_ptr(mikrobus_port_of_match), + }, +}; + +static int mikrobus_init(void) +{ + int retval; + + retval = bus_register(&mikrobus_bus_type); + if (retval) { + pr_err("bus_register failed (%d)\n", retval); + return retval; + } + + mikrobus_port_compat_class = class_compat_register("mikrobus-port"); + if (!mikrobus_port_compat_class) { + pr_err("class_compat register failed (%d)\n", retval); + retval = -ENOMEM; + goto class_err; + } + + retval = of_alias_get_highest_id("mikrobus"); + if (retval >= __mikrobus_first_dynamic_bus_num) + __mikrobus_first_dynamic_bus_num = retval + 1; + + is_registered = true; + retval = platform_driver_register(&mikrobus_port_driver); + if (retval) + pr_err("driver register failed [%d]\n", retval); + + return retval; + +class_err: + bus_unregister(&mikrobus_bus_type); + idr_destroy(&mikrobus_port_idr); + is_registered = false; + return retval; +} +subsys_initcall(mikrobus_init); + +static void mikrobus_exit(void) +{ + platform_driver_unregister(&mikrobus_port_driver); + bus_unregister(&mikrobus_bus_type); + class_compat_unregister(mikrobus_port_compat_class); + idr_destroy(&mikrobus_port_idr); +} +module_exit(mikrobus_exit); + +MODULE_AUTHOR("Vaishnav M A "); +MODULE_AUTHOR("Ayush Singh "); +MODULE_DESCRIPTION("mikroBUS main module"); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mikrobus/mikrobus_core.h b/drivers/misc/mikrobus/mikrobus_core.h new file mode 100644 index 000000000000..8bd101828964 --- /dev/null +++ b/drivers/misc/mikrobus/mikrobus_core.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mikroBUS Driver for instantiating add-on + * board devices with an identifier EEPROM + * + * Copyright 2020 Vaishnav M A, BeagleBoard.org Foundation. + */ + +#ifndef __MIKROBUS_H +#define __MIKROBUS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIKROBUS_VERSION_MAJOR 0x00 +#define MIKROBUS_VERSION_MINOR 0x03 + +#define MIKROBUS_NAME_SIZE 40 +#define MIKROBUS_PINCTRL_NAME_SIZE 20 + +#define MIKROBUS_NUM_PINCTRL_STATE 4 +#define MIKROBUS_NUM_CS 2 + +#define MIKROBUS_PINCTRL_PWM 0 +#define MIKROBUS_PINCTRL_UART 1 +#define MIKROBUS_PINCTRL_I2C 2 +#define MIKROBUS_PINCTRL_SPI 3 + +#define MIKROBUS_PINCTRL_STATE_GPIO "gpio" + +#define MIKROBUS_EEPROM_EXIT_ID_CMD 0xD2 + +extern const struct bus_type mikrobus_bus_type; +extern const struct device_type mikrobus_port_type; +extern const char *MIKROBUS_PINCTRL_STR[]; + +enum mikrobus_property_type { + MIKROBUS_PROPERTY_TYPE_MIKROBUS = 0x00, + MIKROBUS_PROPERTY_TYPE_PROPERTY = 0x01, + MIKROBUS_PROPERTY_TYPE_GPIO = 0x02, + MIKROBUS_PROPERTY_TYPE_U8 = 0x03, + MIKROBUS_PROPERTY_TYPE_U16 = 0x04, + MIKROBUS_PROPERTY_TYPE_U32 = 0x05, + MIKROBUS_PROPERTY_TYPE_U64 = 0x06, + MIKROBUS_PROPERTY_TYPE_REGULATOR = 0x07, + MIKROBUS_PROPERTY_TYPE_CLOCK = 0x08, +}; + +enum mikrobus_pin { + MIKROBUS_PIN_PWM = 0x00, + MIKROBUS_PIN_INT = 0x01, + MIKROBUS_PIN_RX = 0x02, + MIKROBUS_PIN_TX = 0x03, + MIKROBUS_PIN_SCL = 0x04, + MIKROBUS_PIN_SDA = 0x05, + MIKROBUS_PIN_MOSI = 0x06, + MIKROBUS_PIN_MISO = 0x07, + MIKROBUS_PIN_SCK = 0x08, + MIKROBUS_PIN_CS = 0x09, + MIKROBUS_PIN_RST = 0x0A, + MIKROBUS_PIN_AN = 0x0B, + MIKROBUS_PORT_PIN_COUNT = 0x0C, +}; + +enum mikrobus_pin_state { + MIKROBUS_STATE_INPUT = 0x01, + MIKROBUS_STATE_OUTPUT_HIGH = 0x02, + MIKROBUS_STATE_OUTPUT_LOW = 0x03, + MIKROBUS_STATE_PWM = 0x04, + MIKROBUS_STATE_SPI = 0x05, + MIKROBUS_STATE_I2C = 0x06, + MIKROBUS_STATE_UART = 0x07, +}; + +/* + * board_device_info describes a single device on a mikrobus add-on + * board, an add-on board can present one or more device to the host + * + * @gpio_lookup: used to provide the GPIO lookup table for + * passing the named GPIOs to device drivers. + * @properties: used to provide the property_entry to pass named + * properties to device drivers, applicable only when driver uses + * device_property_read_* calls to fetch the properties. + * @num_gpio_resources: number of named gpio resources for the device, + * used mainly for gpiod_lookup_table memory allocation. + * @num_properties: number of custom properties for the device, + * used mainly for property_entry memory allocation. + * @protocol: used to know the type of the device and it should + * contain one of the values defined under 'enum greybus_class_type' + * under linux/greybus/greybus_manifest.h + * @reg: I2C address for the device, for devices on the SPI bus + * this field is the chip select address relative to the mikrobus + * port:0->device chip select connected to CS pin on mikroBUS port + * 1->device chip select connected to RST Pin on mikroBUS port + * @mode: SPI mode + * @max_speed_hz: SPI max speed(Hz) + * @drv_name: device_id to match with the driver + * @irq_type: type of IRQ trigger , match with defines in linux/interrupt.h + * @irq: irq number relative to the mikrobus port should contain one of the + * values defined under 'enum mikrobus_pin' + * @id: device id starting from 1 + */ +struct board_device_info { + struct gpiod_lookup_table *gpio_lookup; + struct property_entry *properties; + struct property_entry *regulators; + struct property_entry *clocks; + struct list_head links; + unsigned short num_gpio_resources; + unsigned short num_properties; + unsigned short num_regulators; + unsigned short num_clocks; + unsigned short protocol; + unsigned short reg; + unsigned int mode; + void *dev_client; + u32 max_speed_hz; + char *drv_name; + int irq_type; + int irq; + int id; +}; + +/* + * addon_board_info describes a mikrobus add-on device the add-on + * board, an add-on board can present one or more device to the host + * + * @manifest_descs: list of manifest descriptors + * @devices: list of devices on the board + * @pin_state: the state of each pin on the mikrobus port required + * for the add-on board should contain one of the values defined under + * 'enum mikrobus_pin_state' restrictions are as per mikrobus standard + * specifications. + * @name: add-on board name + */ +struct addon_board_info { + struct list_head manifest_descs; + struct list_head devices; + u8 pin_state[MIKROBUS_PORT_PIN_COUNT]; + char *name; +}; + +/* + * mikrobus_port describes the peripherals mapped to a + * mikrobus port. + * + * @eeprom_client: i2c_client corresponding to the eeprom + * on the add-on board. + * @board: pointer to the attached add-on board. + * @i2c_adap: I2C adapter attached to the mikrobus port. + * @spi_mstr: SPI master attached to the mikrobus port. + * @eeprom: nvmem_device for the eeprom on the add-on board. + * @pwm: pwm_device attached to the mikrobus port PWM pin. + * @pinctrl_selected: current pinctrl_selected state. + * @chip_select: chip select number mapped to the SPI + * CS pin on the mikrobus port and the RST pin on the mikrobus + * port + * @id: port id starting from 1 + */ +struct mikrobus_port { + struct addon_board_info *board; + struct nvmem_device *eeprom; + struct i2c_adapter *i2c_adap; + struct spi_controller *spi_ctrl; + struct w1_master *w1_master; + struct platform_device *w1_gpio; + struct serdev_controller *ser_ctrl; + struct gpio_descs *gpios; + struct pwm_device *pwm; + struct pinctrl *pinctrl; + struct module *owner; + struct device dev; + char name[MIKROBUS_NAME_SIZE]; + char *pinctrl_selected[MIKROBUS_NUM_PINCTRL_STATE]; + unsigned int chip_select[MIKROBUS_NUM_CS]; + int skip_scan; + int id; +}; + +#define to_mikrobus_port(d) container_of(d, struct mikrobus_port, dev) + +void mikrobus_board_unregister(struct mikrobus_port *port, struct addon_board_info *board); +int mikrobus_board_register(struct mikrobus_port *port, struct addon_board_info *board); +int mikrobus_port_register(struct mikrobus_port *port); +int mikrobus_port_pinctrl_select(struct mikrobus_port *port); +void mikrobus_port_delete(struct mikrobus_port *port); +int mikrobus_port_scan_eeprom(struct mikrobus_port *port); +struct mikrobus_port *mikrobus_find_port_by_w1_master(struct w1_master *master); +#endif /* __MIKROBUS_H */ diff --git a/drivers/misc/mikrobus/mikrobus_id.c b/drivers/misc/mikrobus/mikrobus_id.c new file mode 100644 index 000000000000..42a0a558785d --- /dev/null +++ b/drivers/misc/mikrobus/mikrobus_id.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * mikrobus_id.c - w1 mikroBUS ID family EEPROM driver + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mikrobus_core.h" + +#define W1_EEPROM_MIKROBUS_ID 0xCC +#define W1_MIKROBUS_ID_EEPROM_SIZE 0x0200 +#define W1_MIKROBUS_ID_EEPROM_PAGE_SIZE 32 +#define W1_MIKROBUS_ID_READ_EEPROM 0x69 +#define W1_MIKROBUS_ID_WRITE_EEPROM 0x96 +#define W1_MIKROBUS_ID_RELEASE_EEPROM 0xAA +#define W1_MIKROBUS_ID_EEPROM_READ_RETRIES 10 + +#define W1_MIKROBUS_EEPROM_MANIFEST_START_PAGE 1 + +static ssize_t mikrobus_manifest_store(struct device *device, struct device_attribute *attr, + const char *buf, size_t count) +{ + u8 write_request[] = { W1_MIKROBUS_ID_WRITE_EEPROM, + W1_MIKROBUS_EEPROM_MANIFEST_START_PAGE }; + u8 release_command = W1_MIKROBUS_ID_RELEASE_EEPROM; + struct w1_slave *sl = dev_to_w1_slave(device); + u16 crc, crc_read, pos = 0; + u8 status = 0; + int cnt; + + if (count > W1_MIKROBUS_ID_EEPROM_SIZE) + return -ENOMEM; + + mutex_lock(&sl->master->bus_mutex); + + pr_info("mikrobus_id: writing manifest size = %lu bytes", count); + while (pos < count) { + if (w1_reset_select_slave(sl)) + break; + + w1_write_block(sl->master, write_request, sizeof(write_request)); + crc = crc16(0, write_request, sizeof(write_request)) ^ 0xFFFF; + w1_read_block(sl->master, (u8 *)&crc_read, sizeof(crc_read)); + + if (crc != crc_read) + break; + + for (cnt = 0; cnt < W1_MIKROBUS_ID_EEPROM_PAGE_SIZE; cnt++) + w1_write_8(sl->master, (u8)buf[cnt]); + + crc = crc16(0, buf, W1_MIKROBUS_ID_EEPROM_PAGE_SIZE) ^ 0xFFFF; + usleep_range(1 * USEC_PER_MSEC, 2 * USEC_PER_MSEC); + w1_read_block(sl->master, (u8 *)&crc_read, sizeof(crc_read)); + + if (crc != crc_read) + break; + + w1_write_8(sl->master, release_command); + usleep_range(10 * USEC_PER_MSEC, 15 * USEC_PER_MSEC); + status = w1_read_8(sl->master); + w1_read_block(sl->master, (u8 *)&crc_read, sizeof(crc_read)); + crc = crc16(0, (u8 *)&release_command, sizeof(release_command)) ^ 0xFFFF; + + if (status != W1_MIKROBUS_ID_RELEASE_EEPROM) + break; + + if (crc != crc_read) + break; + + buf += W1_MIKROBUS_ID_EEPROM_PAGE_SIZE; + pos += W1_MIKROBUS_ID_EEPROM_PAGE_SIZE; + write_request[1]++; + } + + pr_info("mikrobus_id: manifest written bytes: %d", pos); + mutex_unlock(&sl->master->bus_mutex); + + return count > pos ? count : pos; +} +static DEVICE_ATTR_WO(mikrobus_manifest); + +static struct attribute *w1_mikrobus_attrs[] = { &dev_attr_mikrobus_manifest.attr, NULL }; + +ATTRIBUTE_GROUPS(w1_mikrobus); + +static int w1_mikrobus_id_readpage(struct w1_slave *sl, int pageaddr, char *buf) +{ + u8 crc_rdbuf[2]; + + if (w1_reset_select_slave(sl)) + return -1; + + w1_write_8(sl->master, W1_MIKROBUS_ID_READ_EEPROM); + w1_write_8(sl->master, pageaddr); + w1_read_block(sl->master, crc_rdbuf, 2); + w1_write_8(sl->master, W1_MIKROBUS_ID_RELEASE_EEPROM); + usleep_range(10 * USEC_PER_MSEC, 15 * USEC_PER_MSEC); + w1_read_block(sl->master, crc_rdbuf, 1); + w1_read_block(sl->master, buf, W1_MIKROBUS_ID_EEPROM_PAGE_SIZE); + w1_read_block(sl->master, crc_rdbuf, 2); + + return 0; +} + +static int w1_mikrobus_id_readbuf(struct w1_slave *sl, int count, int off, char *buf) +{ + int len = count - (count % W1_MIKROBUS_ID_EEPROM_PAGE_SIZE); + u8 pageaddr = off / W1_MIKROBUS_ID_EEPROM_PAGE_SIZE; + u8 temp_rdbuf[W1_MIKROBUS_ID_EEPROM_PAGE_SIZE]; + int iter, index, ret; + + while (len > 0) { + ret = w1_mikrobus_id_readpage( + sl, pageaddr, buf + (W1_MIKROBUS_ID_EEPROM_PAGE_SIZE * pageaddr - off)); + pageaddr += 1; + len -= W1_MIKROBUS_ID_EEPROM_PAGE_SIZE; + } + + if (count % W1_MIKROBUS_ID_EEPROM_PAGE_SIZE) { + ret = w1_mikrobus_id_readpage(sl, pageaddr, temp_rdbuf); + for (iter = W1_MIKROBUS_ID_EEPROM_PAGE_SIZE * pageaddr - off, index = 0; + iter < count; iter++, index++) + buf[iter] = temp_rdbuf[index]; + } + + return ret; +} + +static int w1_mikrobus_id_readblock(struct w1_slave *sl, int off, int count, char *buf) +{ + int tries = W1_MIKROBUS_ID_EEPROM_READ_RETRIES; + int ret = -EINVAL; + u8 *cmp; + + cmp = kzalloc(count, GFP_KERNEL); + if (!cmp) + return -ENOMEM; + + do { + w1_mikrobus_id_readbuf(sl, count, off, buf); + + w1_mikrobus_id_readbuf(sl, count, off, cmp); + if (!memcmp(cmp, buf, count)) { + ret = 0; + break; + } + } while (--tries); + + kfree(cmp); + return ret; +} + +static int w1_mikrobus_id_nvmem_read(void *priv, unsigned int off, void *buf, size_t count) +{ + struct w1_slave *sl = priv; + int ret; + + mutex_lock(&sl->master->bus_mutex); + ret = w1_mikrobus_id_readblock(sl, off, count, buf); + mutex_unlock(&sl->master->bus_mutex); + + return ret; +} + +static int w1_mikrobus_id_add_slave(struct w1_slave *sl) +{ + struct nvmem_device *nvmem; + struct mikrobus_port *port; + struct nvmem_config nvmem_cfg = { + .dev = &sl->dev, + .reg_read = w1_mikrobus_id_nvmem_read, + .type = NVMEM_TYPE_EEPROM, + .read_only = true, + .word_size = 1, + .stride = 1, + .size = W1_MIKROBUS_ID_EEPROM_SIZE, + .priv = sl, + }; + + port = mikrobus_find_port_by_w1_master(sl->master); + if (!port) + return -ENODEV; + + nvmem_cfg.name = port->name; + nvmem = devm_nvmem_register(&sl->dev, &nvmem_cfg); + if (IS_ERR(nvmem)) + return PTR_ERR(nvmem); + + port->eeprom = nvmem; + mikrobus_port_scan_eeprom(port); + + return 0; +} + +static const struct w1_family_ops w1_family_mikrobus_id_fops = { .add_slave = + w1_mikrobus_id_add_slave, + .groups = w1_mikrobus_groups }; + +static struct w1_family w1_family_mikrobus_id = { + .fid = W1_EEPROM_MIKROBUS_ID, + .fops = &w1_family_mikrobus_id_fops, +}; + +static int w1_mikrobusid_init(void) +{ + return w1_register_family(&w1_family_mikrobus_id); +} + +static void w1_mikrobusid_exit(void) +{ + w1_unregister_family(&w1_family_mikrobus_id); +} + +module_init(w1_mikrobusid_init); +module_exit(w1_mikrobusid_exit); + +MODULE_AUTHOR("Vaishnav M A "); +MODULE_DESCRIPTION("w1 family CC driver for mikroBUS ID EEPROM"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_MIKROBUS_ID)); diff --git a/drivers/misc/mikrobus/mikrobus_manifest.c b/drivers/misc/mikrobus/mikrobus_manifest.c new file mode 100644 index 000000000000..3121a1d01b8b --- /dev/null +++ b/drivers/misc/mikrobus/mikrobus_manifest.c @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * mikroBUS manifest parsing, an + * extension to Greybus Manifest Parsing + * under drivers/greybus/manifest.c + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + */ + +#define pr_fmt(fmt) "mikrobus_manifest:%s: " fmt, __func__ + +#include +#include +#include +#include + +#include "mikrobus_manifest.h" + +struct manifest_desc { + struct list_head links; + size_t size; + void *data; + enum greybus_descriptor_type type; +}; + +static void manifest_descriptor_release_all(struct addon_board_info *board) +{ + struct manifest_desc *descriptor, *next; + + list_for_each_entry_safe(descriptor, next, &board->manifest_descs, links) { + list_del(&descriptor->links); + kfree(descriptor); + } +} + +static int board_descriptor_add(struct addon_board_info *board, struct greybus_descriptor *desc, + size_t size) +{ + struct greybus_descriptor_header *desc_header = &desc->header; + struct manifest_desc *descriptor; + size_t desc_size, expected_size; + + if (size < sizeof(*desc_header)) { + pr_err("short descriptor (%zu < %zu)", size, sizeof(*desc_header)); + return -EINVAL; + } + + desc_size = le16_to_cpu(desc_header->size); + if (desc_size > size) { + pr_err("incorrect descriptor size (%zu != %zu)", size, desc_size); + return -EINVAL; + } + + expected_size = sizeof(*desc_header); + switch (desc_header->type) { + case GREYBUS_TYPE_STRING: + expected_size += sizeof(struct greybus_descriptor_string); + expected_size += desc->string.length; + expected_size = ALIGN(expected_size, 4); + break; + case GREYBUS_TYPE_PROPERTY: + expected_size += sizeof(struct greybus_descriptor_property); + expected_size += desc->property.length; + expected_size = ALIGN(expected_size, 4); + break; + case GREYBUS_TYPE_DEVICE: + expected_size += sizeof(struct greybus_descriptor_device); + break; + case GREYBUS_TYPE_MIKROBUS: + expected_size += sizeof(struct greybus_descriptor_mikrobus); + break; + case GREYBUS_TYPE_INTERFACE: + expected_size += sizeof(struct greybus_descriptor_interface); + break; + case GREYBUS_TYPE_CPORT: + expected_size += sizeof(struct greybus_descriptor_cport); + break; + case GREYBUS_TYPE_BUNDLE: + expected_size += sizeof(struct greybus_descriptor_bundle); + break; + case GREYBUS_TYPE_INVALID: + default: + pr_err("invalid descriptor type %d", desc_header->type); + return -EINVAL; + } + + descriptor = kzalloc(sizeof(*descriptor), GFP_KERNEL); + if (!descriptor) + return -ENOMEM; + + descriptor->size = desc_size; + descriptor->data = (char *)desc + sizeof(*desc_header); + descriptor->type = desc_header->type; + list_add_tail(&descriptor->links, &board->manifest_descs); + + return desc_size; +} + +static char *mikrobus_string_get(struct addon_board_info *board, u8 string_id) +{ + struct greybus_descriptor_string *desc_string; + struct manifest_desc *descriptor; + bool found = false; + char *string; + + if (!string_id) + return NULL; + + list_for_each_entry(descriptor, &board->manifest_descs, links) { + if (descriptor->type != GREYBUS_TYPE_STRING) + continue; + + desc_string = descriptor->data; + if (desc_string->id == string_id) { + found = true; + break; + } + } + + if (!found) + return ERR_PTR(-ENOENT); + + string = kmemdup(&desc_string->string, desc_string->length + 1, GFP_KERNEL); + if (!string) + return ERR_PTR(-ENOMEM); + + string[desc_string->length] = '\0'; + + return string; +} + +static void mikrobus_state_get(struct addon_board_info *board) +{ + struct greybus_descriptor_mikrobus *mikrobus; + struct greybus_descriptor_interface *interface; + struct manifest_desc *descriptor; + bool found = false; + size_t i; + + list_for_each_entry(descriptor, &board->manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_MIKROBUS) { + mikrobus = descriptor->data; + found = true; + break; + } + } + + if (!found) { + pr_err("mikrobus descriptor not found"); + return; + } + + for (i = 0; i < MIKROBUS_PORT_PIN_COUNT; i++) + board->pin_state[i] = mikrobus->pin_state[i]; + + found = false; + list_for_each_entry(descriptor, &board->manifest_descs, links) { + if (descriptor->type == GREYBUS_TYPE_INTERFACE) { + interface = descriptor->data; + found = true; + break; + } + } + + if (!found) { + pr_err("interface descriptor not found"); + return; + } + + board->name = mikrobus_string_get(board, interface->product_stringid); +} + +static struct property_entry *mikrobus_property_entry_get(struct addon_board_info *board, + u8 *prop_link, int num_properties) +{ + struct greybus_descriptor_property *desc_property; + struct manifest_desc *descriptor; + struct property_entry *properties; + bool found = false; + char *prop_name; + int i, retval; + u64 *val_u64; + u32 *val_u32; + u16 *val_u16; + u8 *val_u8; + + properties = kcalloc(num_properties, sizeof(*properties), GFP_KERNEL); + if (!properties) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < num_properties; i++) { + list_for_each_entry(descriptor, &board->manifest_descs, links) { + if (descriptor->type != GREYBUS_TYPE_PROPERTY) + continue; + + desc_property = descriptor->data; + if (desc_property->id == prop_link[i]) { + found = true; + break; + } + } + + if (!found) { + retval = -ENOENT; + goto early_exit; + } + + prop_name = mikrobus_string_get(board, desc_property->propname_stringid); + if (!prop_name) { + retval = -ENOENT; + goto early_exit; + } + + switch (desc_property->type) { + case MIKROBUS_PROPERTY_TYPE_U8: + val_u8 = kmemdup(&desc_property->value, + (desc_property->length) * sizeof(u8), GFP_KERNEL); + if (desc_property->length == 1) + properties[i] = PROPERTY_ENTRY_U8(prop_name, *val_u8); + else + properties[i] = PROPERTY_ENTRY_U8_ARRAY_LEN( + prop_name, (void *)desc_property->value, + desc_property->length); + break; + case MIKROBUS_PROPERTY_TYPE_U16: + val_u16 = kmemdup(&desc_property->value, + (desc_property->length) * sizeof(u16), GFP_KERNEL); + if (desc_property->length == 1) + properties[i] = PROPERTY_ENTRY_U16(prop_name, *val_u16); + else + properties[i] = PROPERTY_ENTRY_U16_ARRAY_LEN( + prop_name, (void *)desc_property->value, + desc_property->length); + break; + case MIKROBUS_PROPERTY_TYPE_U32: + val_u32 = kmemdup(&desc_property->value, + (desc_property->length) * sizeof(u32), GFP_KERNEL); + if (desc_property->length == 1) + properties[i] = PROPERTY_ENTRY_U32(prop_name, *val_u32); + else + properties[i] = PROPERTY_ENTRY_U32_ARRAY_LEN( + prop_name, (void *)desc_property->value, + desc_property->length); + break; + case MIKROBUS_PROPERTY_TYPE_U64: + val_u64 = kmemdup(&desc_property->value, + (desc_property->length) * sizeof(u64), GFP_KERNEL); + if (desc_property->length == 1) + properties[i] = PROPERTY_ENTRY_U64(prop_name, *val_u64); + else + properties[i] = PROPERTY_ENTRY_U64_ARRAY_LEN( + prop_name, (void *)desc_property->value, + desc_property->length); + break; + default: + retval = -EINVAL; + goto early_exit; + } + } + return properties; + +early_exit: + kfree(properties); + return ERR_PTR(retval); +} + +static u8 *mikrobus_property_link_get(struct addon_board_info *board, u8 prop_id, + struct board_device_info *board_dev, u8 prop_type) +{ + struct greybus_descriptor_property *desc_property; + struct manifest_desc *descriptor; + bool found = false; + u8 *val_u8; + + if (!prop_id) + return NULL; + + list_for_each_entry(descriptor, &board->manifest_descs, links) { + if (descriptor->type != GREYBUS_TYPE_PROPERTY) + continue; + + desc_property = descriptor->data; + if (desc_property->id == prop_id && desc_property->type == prop_type) { + found = true; + break; + } + } + + if (!found) + return ERR_PTR(-ENOENT); + + val_u8 = kmemdup(&desc_property->value, desc_property->length, GFP_KERNEL); + if (prop_type == MIKROBUS_PROPERTY_TYPE_GPIO) + board_dev->num_gpio_resources = desc_property->length; + else if (prop_type == MIKROBUS_PROPERTY_TYPE_PROPERTY) + board_dev->num_properties = desc_property->length; + else if (prop_type == MIKROBUS_PROPERTY_TYPE_REGULATOR) + board_dev->num_regulators = desc_property->length; + else if (prop_type == MIKROBUS_PROPERTY_TYPE_CLOCK) + board_dev->num_clocks = desc_property->length; + + return val_u8; +} + +static int mikrobus_manifest_attach_device(struct addon_board_info *board, + struct greybus_descriptor_device *dev_desc) +{ + u8 *gpio_desc_link, *prop_link, *gpioval, *reg_link, *clock_link; + struct greybus_descriptor_property *desc_property; + struct board_device_info *board_dev; + struct gpiod_lookup_table *lookup; + struct manifest_desc *descriptor; + int retval, i; + + board_dev = kzalloc(sizeof(*board_dev), GFP_KERNEL); + if (!board_dev) + return -ENOMEM; + + board_dev->id = dev_desc->id; + board_dev->drv_name = mikrobus_string_get(board, dev_desc->driver_stringid); + if (!board_dev->drv_name) { + retval = -ENOENT; + goto err_free_board_dev; + } + + board_dev->protocol = dev_desc->protocol; + board_dev->reg = dev_desc->reg; + board_dev->irq = dev_desc->irq; + board_dev->irq_type = dev_desc->irq_type; + board_dev->max_speed_hz = le32_to_cpu(dev_desc->max_speed_hz); + board_dev->mode = dev_desc->mode; + pr_info("parsed device %d, driver=%s", board_dev->id, board_dev->drv_name); + + if (dev_desc->prop_link > 0) { + prop_link = mikrobus_property_link_get(board, dev_desc->prop_link, board_dev, + MIKROBUS_PROPERTY_TYPE_PROPERTY); + if (!prop_link) { + retval = -ENOENT; + goto err_free_board_dev; + } + + pr_info("device %d, number of properties=%d", board_dev->id, + board_dev->num_properties); + board_dev->properties = + mikrobus_property_entry_get(board, prop_link, board_dev->num_properties); + } + + if (dev_desc->gpio_link > 0) { + gpio_desc_link = mikrobus_property_link_get(board, dev_desc->gpio_link, board_dev, + MIKROBUS_PROPERTY_TYPE_GPIO); + if (!gpio_desc_link) { + retval = -ENOENT; + goto err_free_board_dev; + } + + pr_info("device %d, number of gpio resource=%d", board_dev->id, + board_dev->num_gpio_resources); + lookup = kzalloc(struct_size(lookup, table, board_dev->num_gpio_resources), + GFP_KERNEL); + if (!lookup) { + retval = -ENOMEM; + goto err_free_board_dev; + } + + for (i = 0; i < board_dev->num_gpio_resources; i++) { + list_for_each_entry(descriptor, &board->manifest_descs, links) { + if (descriptor->type != GREYBUS_TYPE_PROPERTY) + continue; + + desc_property = descriptor->data; + if (desc_property->id == gpio_desc_link[i]) { + gpioval = desc_property->value; + lookup->table[i].chip_hwnum = gpioval[0]; + lookup->table[i].flags = gpioval[1]; + lookup->table[i].con_id = mikrobus_string_get( + board, desc_property->propname_stringid); + break; + } + } + } + board_dev->gpio_lookup = lookup; + } + + if (dev_desc->reg_link > 0) { + reg_link = mikrobus_property_link_get(board, dev_desc->reg_link, board_dev, + MIKROBUS_PROPERTY_TYPE_REGULATOR); + if (!reg_link) { + retval = -ENOENT; + goto err_free_board_dev; + } + pr_info("device %d, number of regulators=%d", board_dev->id, + board_dev->num_regulators); + board_dev->regulators = + mikrobus_property_entry_get(board, reg_link, board_dev->num_regulators); + } + + if (dev_desc->clock_link > 0) { + clock_link = mikrobus_property_link_get(board, dev_desc->clock_link, board_dev, + MIKROBUS_PROPERTY_TYPE_CLOCK); + if (!clock_link) { + retval = -ENOENT; + goto err_free_board_dev; + } + pr_info("device %d, number of clocks=%d", board_dev->id, board_dev->num_clocks); + board_dev->clocks = + mikrobus_property_entry_get(board, clock_link, board_dev->num_clocks); + } + + list_add_tail(&board_dev->links, &board->devices); + return 0; + +err_free_board_dev: + kfree(board_dev); + return retval; +} + +static int mikrobus_manifest_parse_devices(struct addon_board_info *board) +{ + struct greybus_descriptor_device *desc_device; + struct manifest_desc *desc, *next; + int retval, devcount = 0; + + list_for_each_entry_safe(desc, next, &board->manifest_descs, links) { + if (desc->type != GREYBUS_TYPE_DEVICE) + continue; + + desc_device = desc->data; + retval = mikrobus_manifest_attach_device(board, desc_device); + devcount++; + } + + return devcount; +} + +int mikrobus_manifest_parse(struct addon_board_info *board, void *data, size_t size) +{ + struct greybus_manifest_header *header; + struct greybus_manifest *manifest; + struct greybus_descriptor *desc; + int dev_count, desc_size; + u16 manifest_size; + + if (size < sizeof(*header)) { + pr_err("short manifest (%zu < %zu)", size, sizeof(*header)); + return -EINVAL; + } + + manifest = data; + header = &manifest->header; + manifest_size = le16_to_cpu(header->size); + + if (manifest_size != size) { + pr_err("invalid manifest size(%zu < %u)", size, manifest_size); + return -EINVAL; + } + + if (header->version_major > MIKROBUS_VERSION_MAJOR) { + pr_err("manifest version too new (%u.%u > %u.%u)", header->version_major, + header->version_minor, MIKROBUS_VERSION_MAJOR, MIKROBUS_VERSION_MINOR); + return -EINVAL; + } + + desc = manifest->descriptors; + size -= sizeof(*header); + while (size) { + desc_size = board_descriptor_add(board, desc, size); + if (desc_size < 0) { + pr_err("invalid manifest descriptor, size: %u", desc_size); + return -EINVAL; + } + + desc = (void *)desc + desc_size; + size -= desc_size; + } + + mikrobus_state_get(board); + dev_count = mikrobus_manifest_parse_devices(board); + pr_info(" %s manifest parsed with %d devices", board->name, dev_count); + manifest_descriptor_release_all(board); + + return true; +} + +size_t mikrobus_manifest_header_validate(void *data, size_t size) +{ + struct greybus_manifest_header *header = data; + u16 manifest_size = le16_to_cpu(header->size); + + if (manifest_size < sizeof(*header)) { + pr_err("short manifest (%zu < %zu)", size, sizeof(*header)); + return -EINVAL; + } + + if (header->version_major > MIKROBUS_VERSION_MAJOR) { + pr_err("manifest version too new (%u.%u > %u.%u)", header->version_major, + header->version_minor, MIKROBUS_VERSION_MAJOR, MIKROBUS_VERSION_MINOR); + return -EINVAL; + } + + return manifest_size; +} diff --git a/drivers/misc/mikrobus/mikrobus_manifest.h b/drivers/misc/mikrobus/mikrobus_manifest.h new file mode 100644 index 000000000000..36b64b2093f5 --- /dev/null +++ b/drivers/misc/mikrobus/mikrobus_manifest.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mikroBUS manifest definition + * extension to Greybus Manifest Definition + * + * Copyright 2014-2015 Google Inc. + * Copyright 2014-2015 Linaro Ltd. + * + * Released under the GPLv2 and BSD licenses. + */ + +#ifndef __MIKROBUS_MANIFEST_H +#define __MIKROBUS_MANIFEST_H + +#include "mikrobus_core.h" + +int mikrobus_manifest_parse(struct addon_board_info *info, void *data, size_t size); +size_t mikrobus_manifest_header_validate(void *data, size_t size); + +#endif /* __MIKROBUS_MANIFEST_H */ From patchwork Fri Mar 15 18:49:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 13593891 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3DEFFC54E67 for ; Fri, 15 Mar 2024 18:51:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=FfmDHTEkgNJzw1LwUItB3XBTul9a7m+LPcU4I529uSg=; b=UYskomBT8hfpxg ElPzO3QwErP8pT885AUlXiEwAHRsBsDINotUBbgEL0VDRNY6Q2nViqEjPkV4qnvL0sEPvoHWJfKfo pkQFrbgj5BmuZtfKSCT8T9ZivHILjtP4x8eBMZ9rUFGwQAAkvZKUqCG1rjWNl+bnzAkvA84Sln2FE n23cOcp1LE2NwFtp3p0WkcLd8b4x/aPXJOs+1AsDQtzOFuN8n/OacNmp70XsSW0Psf0K8ZZFyIWUa lLTBayXy7CN860EpSOlJ8LoW1T493NLKr5V3pQKSFJbA7JJoEIXrryL7p+uQVqCooekZIttLn8Wq1 lFx1N7TTXpXV1aabiQ/w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCdi-00000001Dqi-3yOk; Fri, 15 Mar 2024 18:50:46 +0000 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1rlCda-00000001DlF-3cYh for linux-arm-kernel@lists.infradead.org; Fri, 15 Mar 2024 18:50:45 +0000 Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-6e6b5aa0b52so2216204b3a.3 for ; Fri, 15 Mar 2024 11:50:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710528636; x=1711133436; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kCkB7IphGBPGl1w/S0psqC8P5Um5bt65HZvq4RRR00Y=; b=l0QdDjmeG2fG+Eskz59EJfPkAdDFJwTuotTboJz6hdgSLdzl0kww8nY7gyjLhaFM8D 6w/CM07xabukwgnIlZbmTUTXQe9whwHZOMcdCwBaVSP7Vilj6J/W6FySrA6lTjLm73Hx 0mLPYJFM+DNBqqMzsIZ+zhbejX2lz2i0GFUXJ9RjrbxDqyLeNK3ohfPGdgzLqGOdHdHW kJ5VUeNJXZONOX02DbayaIE02GKtugIIfZZ1MNAJKdh+mMhHwXmXLckVc1KpHO15owmx tR6UcVdiKe/pv14bcVmWzIy8O8RhImj60CVSGwxXOB8OmkoE7aHQHDhJiNY9Za4kMyNu 0tmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710528636; x=1711133436; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kCkB7IphGBPGl1w/S0psqC8P5Um5bt65HZvq4RRR00Y=; b=MWszRPnNeV8CJxJxFA1SKUOj1zakSMFH13TGAB57jGVQ1RmBpi2Aq23gxwHndRAjD4 qskLWDVGasvUBjsczqrtMnYtnPB6fT/wzE9TWQ/YRiA5+/kMoh6hqfJlsloDOUQ4xhDV 2BuC31rO/ai3j71lkApBPc/qmcrnWfJAv6ae75NFLzjXclrkGkA2panD9dDEKX/Z7bJ9 oBfoyhjj0jxu9RuC40svNoUBQgDZvSYUxQ+fZwcOxNLU3sWYuhFFVqtA0iRDMGkfQVOw 9+C4Y2zUBXeqhcnpKR0koj9U3uEl5atXRsO7WH4ps2O6ae6fnzPX+51awCrN1UFC52L5 qWfw== X-Forwarded-Encrypted: i=1; AJvYcCVsAdURLDP07uEvY1LuDuL41vUh3l3HIj9js0IZ86UDRtNHEvrMs53Db/5vHhjwdPL9xVapbxePZFdJ1Ud0jefteSsF10cHZ2geQ7ppEh5d9m3Arlk= X-Gm-Message-State: AOJu0YwhgBKDYzzzDMgd8SJF+ptkhk58Id7ncuWTanS2zYmkbf1Vxj5+ N/HwhQjnXjnPDS6LrrLYwU6MWJlzhIed7Mu4vrTpCNRuALW6h9/v X-Google-Smtp-Source: AGHT+IFR9Rz9QYZm4Zrmj3QCj98EeqjLoIF4d8U8fx/cYS6Sv51WOwxOGnn90k4PIrka569oMmxqXw== X-Received: by 2002:a05:6a20:2585:b0:1a3:504d:c064 with SMTP id k5-20020a056a20258500b001a3504dc064mr2238027pzd.55.1710528636650; Fri, 15 Mar 2024 11:50:36 -0700 (PDT) Received: from toolbox.iitism.net ([103.15.228.94]) by smtp.gmail.com with ESMTPSA id f17-20020a056a0022d100b006e6cc998be8sm3580784pfj.207.2024.03.15.11.50.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Mar 2024 11:50:36 -0700 (PDT) From: Ayush Singh To: linux-kernel@vger.kernel.org Cc: Ayush Singh , jkridner@beagleboard.org, robertcnelson@beagleboard.org, Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Liam Girdwood , Mark Brown , Jiri Slaby , Johan Hovold , Alex Elder , devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-spi@vger.kernel.org, linux-serial@vger.kernel.org, greybus-dev@lists.linaro.org Subject: [PATCH v3 8/8] dts: ti: k3-am625-beagleplay: Add mikroBUS Date: Sat, 16 Mar 2024 00:19:06 +0530 Message-ID: <20240315184908.500352-9-ayushdevel1325@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240315184908.500352-1-ayushdevel1325@gmail.com> References: <20240315184908.500352-1-ayushdevel1325@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240315_115039_255067_CD51FB95 X-CRM114-Status: GOOD ( 13.02 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mikroBUS connector support for Beagleplay. Signed-off-by: Ayush Singh --- .../arm64/boot/dts/ti/k3-am625-beagleplay.dts | 76 +++++++++++++++++-- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts index a34e0df2ab86..886308f99d1a 100644 --- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts +++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts @@ -29,6 +29,7 @@ aliases { i2c3 = &main_i2c3; i2c4 = &wkup_i2c0; i2c5 = &mcu_i2c0; + mikrobus0 = &mikrobus0; mmc0 = &sdhci0; mmc1 = &sdhci1; mmc2 = &sdhci2; @@ -230,6 +231,33 @@ simple-audio-card,codec { }; }; + mikrobus0: linux-mikrobus { + compatible = "mikrobus-connector"; + pinctrl-names = "default", "pwm_default", "pwm_gpio", + "uart_default", "uart_gpio", "i2c_default", + "i2c_gpio", "spi_default", "spi_gpio"; + pinctrl-0 = <&mikrobus_gpio_pins_default>; + pinctrl-1 = <&mikrobus_pwm_pins_default>; + pinctrl-2 = <&mikrobus_pwm_pins_gpio>; + pinctrl-3 = <&mikrobus_uart_pins_default>; + pinctrl-4 = <&mikrobus_uart_pins_gpio>; + pinctrl-5 = <&mikrobus_i2c_pins_default>; + pinctrl-6 = <&mikrobus_i2c_pins_gpio>; + pinctrl-7 = <&mikrobus_spi_pins_default>; + pinctrl-8 = <&mikrobus_spi_pins_gpio>; + i2c-adapter = <&main_i2c3>; + spi-controller = <&main_spi2>; + spi-cs = <0 1>; + uart = <&main_uart5>; + pwms = <&ecap2 0 500000 0>; + mikrobus-gpios = + <&main_gpio1 11 GPIO_ACTIVE_HIGH>, <&main_gpio1 9 GPIO_ACTIVE_HIGH>, + <&main_gpio1 24 GPIO_ACTIVE_HIGH>, <&main_gpio1 25 GPIO_ACTIVE_HIGH>, + <&main_gpio1 22 GPIO_ACTIVE_HIGH>, <&main_gpio1 23 GPIO_ACTIVE_HIGH>, + <&main_gpio1 7 GPIO_ACTIVE_HIGH>, <&main_gpio1 8 GPIO_ACTIVE_HIGH>, + <&main_gpio1 14 GPIO_ACTIVE_HIGH>, <&main_gpio1 13 GPIO_ACTIVE_HIGH>, + <&main_gpio1 12 GPIO_ACTIVE_HIGH>, <&main_gpio1 10 GPIO_ACTIVE_HIGH>; + }; }; &main_pmx0 { @@ -389,6 +417,18 @@ AM62X_IOPAD(0x01f0, PIN_OUTPUT, 5) /* (A18) EXT_REFCLK1.CLKOUT0 */ >; }; + mikrobus_pwm_pins_default: mikrobus-pwm-default-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01a4, PIN_INPUT, 2) /* (B20) MCASP0_ACLKX.ECAP2_IN_APWM_OUT */ + >; + }; + + mikrobus_pwm_pins_gpio: mikrobus-pwm-gpio-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01a4, PIN_INPUT, 7) /* (B20) MCASP0_ACLKX.GPIO1_11 */ + >; + }; + mikrobus_i2c_pins_default: mikrobus-i2c-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01d0, PIN_INPUT_PULLUP, 2) /* (A15) UART0_CTSn.I2C3_SCL */ @@ -396,6 +436,13 @@ AM62X_IOPAD(0x01d4, PIN_INPUT_PULLUP, 2) /* (B15) UART0_RTSn.I2C3_SDA */ >; }; + mikrobus_i2c_pins_gpio: mikrobus-i2c-gpio-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01d0, PIN_INPUT, 7) /* (A15) UART0_CTSn.GPIO1_22 */ + AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */ + >; + }; + mikrobus_uart_pins_default: mikrobus-uart-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01d8, PIN_INPUT, 1) /* (C15) MCAN0_TX.UART5_RXD */ @@ -403,6 +450,13 @@ AM62X_IOPAD(0x01dc, PIN_OUTPUT, 1) /* (E15) MCAN0_RX.UART5_TXD */ >; }; + mikrobus_uart_pins_gpio: mikrobus-uart-gpio-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x01d8, PIN_INPUT, 7) /* (C15) MCAN0_TX.GPIO1_24 */ + AM62X_IOPAD(0x01dc, PIN_INPUT, 7) /* (E15) MCAN0_RX.GPIO1_25 */ + >; + }; + mikrobus_spi_pins_default: mikrobus-spi-default-pins { pinctrl-single,pins = < AM62X_IOPAD(0x01b0, PIN_INPUT, 1) /* (A20) MCASP0_ACLKR.SPI2_CLK */ @@ -412,6 +466,15 @@ AM62X_IOPAD(0x0198, PIN_INPUT, 1) /* (A19) MCASP0_AXR2.SPI2_D1 */ >; }; + mikrobus_spi_pins_gpio: mikrobus-spi-gpio-pins { + pinctrl-single,pins = < + AM62X_IOPAD(0x0194, PIN_INPUT, 7) /* (B19) MCASP0_AXR3.GPIO1_7 */ + AM62X_IOPAD(0x0198, PIN_INPUT, 7) /* (A19) MCASP0_AXR2.GPIO1_8 */ + AM62X_IOPAD(0x01ac, PIN_INPUT, 7) /* (E19) MCASP0_AFSR.GPIO1_13 */ + AM62X_IOPAD(0x01b0, PIN_INPUT, 7) /* (A20) MCASP0_ACLKR.GPIO1_14 */ + >; + }; + mikrobus_gpio_pins_default: mikrobus-gpio-default-pins { bootph-all; pinctrl-single,pins = < @@ -629,8 +692,6 @@ &main_gpio0 { &main_gpio1 { bootph-all; - pinctrl-names = "default"; - pinctrl-0 = <&mikrobus_gpio_pins_default>; gpio-line-names = "", "", "", "", "", /* 0-4 */ "SPE_RSTN", "SPE_INTN", "MIKROBUS_GPIO1_7", /* 5-7 */ "MIKROBUS_GPIO1_8", "MIKROBUS_GPIO1_9", /* 8-9 */ @@ -803,15 +864,11 @@ it66121_out: endpoint { }; &main_i2c3 { - pinctrl-names = "default"; - pinctrl-0 = <&mikrobus_i2c_pins_default>; clock-frequency = <400000>; status = "okay"; }; &main_spi2 { - pinctrl-names = "default"; - pinctrl-0 = <&mikrobus_spi_pins_default>; status = "okay"; }; @@ -875,9 +932,8 @@ &main_uart1 { }; &main_uart5 { - pinctrl-names = "default"; - pinctrl-0 = <&mikrobus_uart_pins_default>; status = "okay"; + force-empty-serdev-controller; }; &main_uart6 { @@ -926,3 +982,7 @@ &mcasp1 { tx-num-evt = <32>; rx-num-evt = <32>; }; + +&ecap2 { + status = "okay"; +};