From patchwork Thu Jun 27 16:26:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 808104 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 704C2199EB9 for ; Thu, 27 Jun 2024 16:29:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719505741; cv=none; b=phawY1UmvzXBO1umb7dzCA0EjqMqVbxkSSXSkJtYuZVWwbRX/rpi0CQ1iZOSJnu1jiXYd7QT49ESTkDFY3LPoLd/lhyllzpJ9jg3+UGXakk5MLRvrs9Oy9m+3NMqZytpOg6zOLfZJM1T00iAhrUaWz/FRRNpkpRRktEzLqYf1qE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719505741; c=relaxed/simple; bh=Qx+Gj82f7/BC0AtS5BoDh2/utfcW2CADbnoJO4Ly0ms=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hHD7MuOOg9zrHQrbQWJw+F7qxFEP8DJba2mvS9n9marugXB2bgQ2nfMsn/5cq5rY3TXV1a4BlCzom8hr3y0RXO5eI4mT6GKfbHB8gJsTw8X8eT4MeyTa7++pa8ftNxMEyF/VhuyBppjLuEVHj9Hz0iBSYfiHFmlG7NNmgdoXfjU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=beagleboard.org; spf=fail smtp.mailfrom=beagleboard.org; dkim=pass (2048-bit key) header.d=beagleboard-org.20230601.gappssmtp.com header.i=@beagleboard-org.20230601.gappssmtp.com header.b=xCrfPee2; arc=none smtp.client-ip=209.85.215.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=beagleboard.org Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=beagleboard.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=beagleboard-org.20230601.gappssmtp.com header.i=@beagleboard-org.20230601.gappssmtp.com header.b="xCrfPee2" Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-7241292c26bso171311a12.2 for ; Thu, 27 Jun 2024 09:29:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=beagleboard-org.20230601.gappssmtp.com; s=20230601; t=1719505740; x=1720110540; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=+ccOqRF95rvK7M/qswICcqSLYl9oR0H6qjszvfV+fi4=; b=xCrfPee2lXYTjSHZjTc0ooYg8z+TJOcI2qQMWWj0snBl4Xe2/2JZQ5rYvcNDXKwutZ x0TbfNGth4ntbaTejprwam5KhiKcc4iLpbIZ8LPa7gJVEIkm70CR5aPo/1WDVufleWNh +Fds+L45Kdeu1c3U7ZxekYtGJjNBCwHl1b+E4iD2AjBJlNli88yE0Sb5SW7Tyi3TKrIZ mtk99wd6LZ+9Oho8Xu3FvNSl9SCLBdSJoc1/Oe4KuFc24tKXND6jV08YZQ8w1/1oj4y8 wjaA6UzX9xWbV005mCRqOSFSpbf1A9/QsWBZBQhXPh7d4m7hIUXGHmdJJiY6cgA1kXsL Yj/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719505740; x=1720110540; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+ccOqRF95rvK7M/qswICcqSLYl9oR0H6qjszvfV+fi4=; b=Vm9968jeWB4xF67s6H3IfUSkOWUfEYi96bggjYTjrSQ1XTsoyIZTtzr/cFYEyMlFiv /6AtLpHhJvCwj3LkN9qRcHkKkoMiD0eBd6lktWC1mlEVdfFzrmA16GNS4t2icLwzSi65 zVRPbVO0mcuT7FFVu9+m+jcqZOVSTQvXAVreqCh7XLJ+jRw+ZoMEP+zvog51b/EJjPPO L7oNXXDef84Hry7jggpYg2IehWBjh5mXeBuOvSoCwHPffIJX4vyr3EkGpW5AgZ7EuHE2 Yf1Nsx+hBT4Cs12NxzC9gh/wNOVGniWSMD5kOkmLrCSufL3+Kog3hP4SG/RIrLjmR4MJ f7mg== X-Gm-Message-State: AOJu0YxzBf5V2GPZJssyfmQGs74Gr4uIR7IhW629riPI3A40Zu2RhPMB CNACQwIuVNkAITWARF+KPYJOrmSSIw4OMnCschtTc95PY891kp7a1C1RNARqhQ== X-Google-Smtp-Source: AGHT+IFk7HX+UKAgfs/mOuNh+uAKaBrAUQCaRjadcUs82yFBm92OurvtId01tZ+4k4Mj1CxjuWO1vw== X-Received: by 2002:a05:6a00:6085:b0:705:d60f:e64e with SMTP id d2e1a72fcca58-70667e2b1cfmr16013801b3a.1.1719505739742; Thu, 27 Jun 2024 09:28:59 -0700 (PDT) Received: from [127.0.0.1] ([2401:4900:1f3e:18b0:e4e6:ed1:4c03:dcec]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-706b4a58dbdsm1560739b3a.198.2024.06.27.09.28.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Jun 2024 09:28:59 -0700 (PDT) From: Ayush Singh Date: Thu, 27 Jun 2024 21:56:12 +0530 Subject: [PATCH v5 2/7] dt-bindings: mikrobus: Add mikrobus board base Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240627-mikrobus-scratch-spi-v5-2-9e6c148bf5f0@beagleboard.org> References: <20240627-mikrobus-scratch-spi-v5-0-9e6c148bf5f0@beagleboard.org> In-Reply-To: <20240627-mikrobus-scratch-spi-v5-0-9e6c148bf5f0@beagleboard.org> To: Mark Brown , Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Michael Walle , Andrew Lunn , jkridner@beagleboard.org, robertcnelson@beagleboard.org Cc: linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Ayush Singh X-Mailer: b4 0.14.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1971; i=ayush@beagleboard.org; h=from:subject:message-id; bh=Qx+Gj82f7/BC0AtS5BoDh2/utfcW2CADbnoJO4Ly0ms=; b=owEBbQKS/ZANAwAIAQXO9ceJ5Vp0AcsmYgBmfZM386HpYhQNB0PpqxdYqTINwd7DNpxa1qpT3 BXwROSootiJAjMEAAEIAB0WIQTfzBMe8k8tZW+lBNYFzvXHieVadAUCZn2TNwAKCRAFzvXHieVa dI77EAContjZVyred1K/HQTl7UUY2WxuOSylfSAEp/dre8J2S0HEpt2NJE9MFdKzEVzBvp+0euk VpHNC/jIngtHlWsnOs+Hgy4VahO/Ohkxix1aM4YJhm6rXAi4I1E8mw3tVtro2+AAdqwh4ZzQ91Q J/bofN5cTWytbgd9BawV7HIE1aoi1q2jK7oE/uKCrLCi75zfUWRDwPcPj0T9DLrt36lnRRFwF39 BefYCRZcgN60wjf/QDdDG4r5mueY3yUZiRe8VV7reVnA+mjft7r+HTOd/FDHokZSIJK8NGm0AlX elUbHGmlgGHCnUAY3zraeyy21giGTjAUL1S+F3yuYBGW06FK4Sh5xRXkcvve/MgjDADLqEaN1IB uL62G8on4ywN8I3bZznwBDTocmUots1B/MCFu6uftT2wgIFWjv66SkSHx1GNFDnD9Lx0f7JeovI nmTOrQ0aUtRBP6THY+5D4tMGbo0P9L/UPbP+nMtc2Bf9hzW10m03fbv0TNO8kPtAY/nfPOCg4vn L4aZ8c2zeLASNtG4osr4DTBRcJUHdpsSPA+oj+9qC+2MmDpBtP+V8neKEMIsNNqA/Ubbwgq/cf4 4knrbpAh8IekyYZBmneWz4gxXGIrPu4UwaOjXPVklytAKWvlOtfJ/tllwAtaITp0qyMM/9TSU/i bQczVjt5RwcnSEA== X-Developer-Key: i=ayush@beagleboard.org; a=openpgp; fpr=DFCC131EF24F2D656FA504D605CEF5C789E55A74 Base dt bindings for mikrobus addon boards. Contains properties that are part of all types of boards (SPI, I2C, etc). Each pin in mikroBUS connector can either be used for it's original purpose (UART, I2C, SPI, etc) or as a normal GPIO. Introducing `pinctrl-apply` allows selecting the pin configuration by name. Note: Some mikrobus-connectors might not support all valid pinctrl. Signed-off-by: Ayush Singh --- .../devicetree/bindings/mikrobus/mikrobus-board.yaml | 20 ++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 21 insertions(+) diff --git a/Documentation/devicetree/bindings/mikrobus/mikrobus-board.yaml b/Documentation/devicetree/bindings/mikrobus/mikrobus-board.yaml new file mode 100644 index 000000000000..42e2219c596f --- /dev/null +++ b/Documentation/devicetree/bindings/mikrobus/mikrobus-board.yaml @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mikrobus/mikrobus-board.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: mikroBUS add-on board properties + +maintainers: + - Ayush Singh + +properties: + pinctrl-apply: + minItems: 1 + maxItems: 9 + items: + enum: [default, pwm_default, pwm_gpio, uart_default, uart_gpio, i2c_default, i2c_gpio, spi_default, + spi_gpio] + +additionalProperties: false diff --git a/MAINTAINERS b/MAINTAINERS index 8e4115e93aeb..14eba18832d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15113,6 +15113,7 @@ M: Ayush Singh M: Vaishnav M A S: Maintained F: Documentation/devicetree/bindings/connector/mikrobus-connector.yaml +F: Documentation/devicetree/bindings/mikrobus/mikrobus-board.yaml MIKROTIK CRS3XX 98DX3236 BOARD SUPPORT M: Luka Kovacic From patchwork Thu Jun 27 16:26:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 808103 Received: from mail-pf1-f170.google.com (mail-pf1-f170.google.com [209.85.210.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 56A7B19A298 for ; Thu, 27 Jun 2024 16:29:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719505755; cv=none; b=q+d3hSgd0KH+yp6NaHBEjFRNezNkB27nhPiOTY463vywXUsetqag7dMsNQQy/AQzxwjcrzWMjFxNisUaB0vsVblyxA/zJhDm5aziqv0abWffbhluAYDtuNNwJlniQ7fgiUVWaSjwQ4XPK8lRSnm4uoP7fmfxrohRqU9s/ZN2toI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719505755; c=relaxed/simple; bh=cw+l2A4wgT8PtcMywBx+9XFt3yIbM2+46AeAyO5wlr4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JwvcwRtYlDB0pZKiT6IibVJJlzHW/oQWnpR7BkbrMrlsn/8Vg54mR2MvJFPtM9Cc0EU6e/IAbqpHVBkHiERfQuKPaPKIvtsqhwDY1GbSZBS0XK2OdghhGSSt5A0ov8I2F/TOz4t5Q8/IzNz4EviIpM2AILrFng8aPfXLr690MEM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=beagleboard.org; spf=fail smtp.mailfrom=beagleboard.org; dkim=pass (2048-bit key) header.d=beagleboard-org.20230601.gappssmtp.com header.i=@beagleboard-org.20230601.gappssmtp.com header.b=0O0fDBKd; arc=none smtp.client-ip=209.85.210.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=beagleboard.org Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=beagleboard.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=beagleboard-org.20230601.gappssmtp.com header.i=@beagleboard-org.20230601.gappssmtp.com header.b="0O0fDBKd" Received: by mail-pf1-f170.google.com with SMTP id d2e1a72fcca58-706638d392cso480952b3a.1 for ; Thu, 27 Jun 2024 09:29:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=beagleboard-org.20230601.gappssmtp.com; s=20230601; t=1719505752; x=1720110552; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=dJ1Q8KLXbBvPejPRGDLYr/bC1HXbn69hKei2CLRD37M=; b=0O0fDBKdt/BWcT4cQbhFlGY2JfeMP4fV/P2l7kka/Ca1yM5ODNTGromlGd3Sa4EdxX Tg2bl1XtVcMfRRUdkdWK0RyPUsJXxNno+/T/1FwWWqC7KhNPJX2AHieQOIaIQVn1DBBi CaIhgWUH9V66XLU1kDf8jGA18rcIGYhc442J37xefjhJDOuY7k7V+O2X1N5au+xGeVtu fh3/Nnzi1e8AC8anD7L5B3NsmNqTtnLtBM9iVP1MkbAN+qWixefPWHCzbQTSx4kP8JM9 yWiTnphAsDTdTIsyGOlAsFQu532RcxC27TXbBzQ4Tg7l+XS7xLYvqHiMehYFBKI4Aij5 Y1Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719505752; x=1720110552; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dJ1Q8KLXbBvPejPRGDLYr/bC1HXbn69hKei2CLRD37M=; b=QQaXqqvU6WRO7f6opW8XXV11lR6RYEEKAATEd2Vlw4E1ctmvO1ZOFCZJvtB04/GEFt ydQwY4+0WPUIMjAshkE9p2g2hAy1/7rL3IRWOxOtAl5LiYBD7ycV4a3++Yp32p0V85rq 2Q9fXZm8jD91JGr4jmkry70eCBBepMXzevoMbJVu+zLXlQsvKgBYEROBdIRygVhATlxP Vc+NF24RSw5kra66+PxAEWQPKQcIZjUyLcVgkuvD2R8du52KiOHYm4IocH1n7VpjWZIK KmB7SN8GtlDsauwGk++M5+apZ9T5TR29WlGYN9G18YXvMbnIYHV88Qesz+LrQHAQQ9TW BcbQ== X-Gm-Message-State: AOJu0YwPetI2e3qlQb0KG1v1xDSP3LBpL2TTxoUyXlFI9NkozLZtqfjX 6Jd4654jtw1QHhCc4LU3ZB1DUL1PoHeJvs0KsPdWGwXuFvgv/E3L/UjvCP5yqw== X-Google-Smtp-Source: AGHT+IH3omPFHGGPxV7skDlndGJ9S2ClJpc2MTVM8kooRW3+wAtdW3I1lvFLR5DYyPEFczJdm/1zgg== X-Received: by 2002:a05:6a00:8c0d:b0:704:21c2:ae92 with SMTP id d2e1a72fcca58-706649a6b01mr16098893b3a.2.1719505752619; Thu, 27 Jun 2024 09:29:12 -0700 (PDT) Received: from [127.0.0.1] ([2401:4900:1f3e:18b0:e4e6:ed1:4c03:dcec]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-706b4a58dbdsm1560739b3a.198.2024.06.27.09.29.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Jun 2024 09:29:12 -0700 (PDT) From: Ayush Singh Date: Thu, 27 Jun 2024 21:56:14 +0530 Subject: [PATCH v5 4/7] spi: Make of_find_spi_controller_by_node() available Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240627-mikrobus-scratch-spi-v5-4-9e6c148bf5f0@beagleboard.org> References: <20240627-mikrobus-scratch-spi-v5-0-9e6c148bf5f0@beagleboard.org> In-Reply-To: <20240627-mikrobus-scratch-spi-v5-0-9e6c148bf5f0@beagleboard.org> To: Mark Brown , Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Michael Walle , Andrew Lunn , jkridner@beagleboard.org, robertcnelson@beagleboard.org Cc: linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Ayush Singh , Ayush Singh X-Mailer: b4 0.14.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7524; i=ayush@beagleboard.org; h=from:subject:message-id; bh=Q5G1t+bBT76IayXqh+ct3R0Xwy8Q7gI2MQZpDn6U4Tw=; b=owEBbQKS/ZANAwAIAQXO9ceJ5Vp0AcsmYgBmfZM39ts1Hz8di1m0tcwk+aba8fgbKzU2sWFfL dDxLIgR2WOJAjMEAAEIAB0WIQTfzBMe8k8tZW+lBNYFzvXHieVadAUCZn2TNwAKCRAFzvXHieVa dM2AD/93OV2TFiw4AdubUbDptdezyFQRUOt4vbb1yBRSJbVpqw0STGvI8pwCR6VRNxbd8NrQtX8 kuxOz63jbSsu6ob+kNVJjeH6wHJB4nelVuf7T3JhjBMv0qTdAc/75f2pklRQx6gJVYTNNmCgfHU 9Oid495FxS1D8AHZCTp7Ungr+CwIdqTTUyTsUaav9tvrSSoVFqgGDso3URiVi86Xyraa6+aGjbW pI2d03Iua9sZOaQ2fmjsoi0mh7+zJzfhDlYLHmRIR+pqPR07zgv4MXoKwPtG+I3mEdLOcBKi7wg ZO9d3j0hZFcSqOIpey4mmMrtfT1DpckFEb0smR3mb3p6cmSkgZ53z4ALiIxW+g9NtQhtlBRQT11 RpAaRWVoRq4jrrqLxrG5/QtA7+begIYPCKmueTZgN6blJ//gU93cOctHEU+MmtptAmPjhNtB9oT HCVLZ7vvlZcckDE8i/YP/VKepTVKrkgNxOw21DMYkZo+Pa7uWUjHH6CTtgmNFa0XmeRCEIUqM1v BDFmWAhz7lTAxCm2ZMuc/+NxaJCg4/3uhrd5zScJKtS8intFDwaAMKK3NbZKGxX0gZK3G91PHvV AB4xqkIebulFZvYJg9kevmPttx3R7mLHeVOMyWednW8m+kQhTGKx6Q5qPqa6RbkQ3o4LS27e5mk YOdbHuiZ3uUdyiw== X-Developer-Key: i=ayush@beagleboard.org; a=openpgp; fpr=DFCC131EF24F2D656FA504D605CEF5C789E55A74 From: Ayush Singh DONOTMERGE Externalize and export the symbol of_find_spi_controller_by_node() from the SPI core akin to how of_find_i2c_adapter_by_node() is already available. Also, move it under a CONFIG_OF. 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 54cbe652a4df..565b2e2dd5b9 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2340,6 +2340,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) @@ -2549,6 +2636,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 @@ -2917,20 +3021,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 @@ -2958,79 +3048,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 @@ -4720,21 +4737,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 85785bcd20c1..58e692226475 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 Thu Jun 27 16:26:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ayush Singh X-Patchwork-Id: 808102 Received: from mail-il1-f172.google.com (mail-il1-f172.google.com [209.85.166.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC2C719AA5E for ; Thu, 27 Jun 2024 16:29:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719505770; cv=none; b=JRWZNk0aaKM6/aOmOUqOCzyONgJuzyDrfKjufS8sfA8YMUz8NMgaAgDrbg2I4hw63+dntO1SjtApOuH5Ka512N8WSzBLlIHxTVHWaAiUNNeIPQbkUoQpPnSliOCLJk08p5jgVox/e5fZxhY9v5dUkAjiULM3wnQe987XVsbksCA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719505770; c=relaxed/simple; bh=WoVhoW5NvKUcUTYxClHtsBC4qaRwvpudUw/hgpnVaAc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cOC7ac5Jklg/x9daTiJtsvfvcrtJEi0mP2T2akTAf8wk5g0yGAqcet2ZThid20VUn49hBprFHMwZ4cBxnO8/i0pegxvyUU5W9IfqL12RqIN35vvABCwxvmwHVD5wQC6px/cQ+Z7jq324D9AgJf6gBid3weXqyuC/Q3I6EMOxoCk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=beagleboard.org; spf=fail smtp.mailfrom=beagleboard.org; dkim=pass (2048-bit key) header.d=beagleboard-org.20230601.gappssmtp.com header.i=@beagleboard-org.20230601.gappssmtp.com header.b=pf/N52Ok; arc=none smtp.client-ip=209.85.166.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=beagleboard.org Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=beagleboard.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=beagleboard-org.20230601.gappssmtp.com header.i=@beagleboard-org.20230601.gappssmtp.com header.b="pf/N52Ok" Received: by mail-il1-f172.google.com with SMTP id e9e14a558f8ab-3745eeedc76so3200935ab.0 for ; Thu, 27 Jun 2024 09:29:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=beagleboard-org.20230601.gappssmtp.com; s=20230601; t=1719505766; x=1720110566; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=+bfrOPZFpalSMaAS4PqOt0l9wak2sxgz4QQtL4YtP3I=; b=pf/N52OkwjcT0qO6Da/+NqmukBGiqcYZzyrxm6YLvD+PS6hyZQHx/UqrfPB82aXHXn aV5l/8vcveIDGXgTtTi+F56cMZ7CaNfxac/qa6LCf0pQSJi33zTw9hrq6EQLD0tWbFHo b6E2n8PCon5Ru6Qp8C/9CnJDVEWrZqmlJq/VE/UH7yGkETYHV5CZobGIraPwvBq7ecC6 bYfPS5EYgv/9gR28EWxnlcXWGO8Wa9YJWUe1O3aQGNWgs6P14G6r19cjgaHyGB1+Dekl pNGGYGXwBblE87uTkkR6dkhokB+P40mZ7HfpKTcp0MDX/kYxmlAblwjj6AySBuVP2Hj2 uwTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719505766; x=1720110566; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+bfrOPZFpalSMaAS4PqOt0l9wak2sxgz4QQtL4YtP3I=; b=PooHexZdgtrdIQsG3oqCdATDRivFEWbCc1KnzoV/+yZoUH5zeONrDZDEWvf2MdgWQx InfxlLJPuC+Qm57lsKJogSVyGyyhBN6LWo+d29KW3mcRmPZOwO9s6ORujQb5qO349Tin gjwhXIySEkvmIk2jSXtDudpJ+2nfeQJyLKD/4RUF7hDYnWf9JnHG388dxdWg8ISp50Mb Q7n+lAhTuJbIhlj1uR1gp/95d5gJjwoHZQQEGlS+2Ty9lBYN5lMfFHZKl6WMOnuqERFH 8XCvd7WSVJlRZBtsMZ3GXuBqSDqcNUDZsk8awRnbKNKgey8rg0go7auSK5iff1BLN+dD DwnQ== X-Gm-Message-State: AOJu0YwhBYqPPQBgE5v3AehZd2Gy4mGFpKWoAoqSKge3qdpFqggKe5QE 87n2OURxYQeNWh4o+w0hk+arIbq6K5xRYQHvBpJAANYj+ToqsuW2MNlh6NUlXg== X-Google-Smtp-Source: AGHT+IFGYU63T/oSxgM+A/eQpByDC/Ouyy7zftKpv3HGC+fCi8ImTDpADN0e5OgU0x+zSxAjYtwXCA== X-Received: by 2002:a05:6e02:1303:b0:376:38c5:5cf2 with SMTP id e9e14a558f8ab-37638c55fcfmr140649355ab.1.1719505765939; Thu, 27 Jun 2024 09:29:25 -0700 (PDT) Received: from [127.0.0.1] ([2401:4900:1f3e:18b0:e4e6:ed1:4c03:dcec]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-706b4a58dbdsm1560739b3a.198.2024.06.27.09.29.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 27 Jun 2024 09:29:25 -0700 (PDT) From: Ayush Singh Date: Thu, 27 Jun 2024 21:56:16 +0530 Subject: [PATCH v5 6/7] mikrobus: Add mikroBUS driver Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240627-mikrobus-scratch-spi-v5-6-9e6c148bf5f0@beagleboard.org> References: <20240627-mikrobus-scratch-spi-v5-0-9e6c148bf5f0@beagleboard.org> In-Reply-To: <20240627-mikrobus-scratch-spi-v5-0-9e6c148bf5f0@beagleboard.org> To: Mark Brown , Vaishnav M A , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Derek Kiernan , Dragan Cvetic , Arnd Bergmann , Greg Kroah-Hartman , Nishanth Menon , Vignesh Raghavendra , Tero Kristo , Michael Walle , Andrew Lunn , jkridner@beagleboard.org, robertcnelson@beagleboard.org Cc: linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Ayush Singh X-Mailer: b4 0.14.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=11731; i=ayush@beagleboard.org; h=from:subject:message-id; bh=WoVhoW5NvKUcUTYxClHtsBC4qaRwvpudUw/hgpnVaAc=; b=owEBbQKS/ZANAwAIAQXO9ceJ5Vp0AcsmYgBmfZM4R0dGTAnMs7uGqJCgVYKtNuon/Ak3JVoC9 m7HsTKtHP6JAjMEAAEIAB0WIQTfzBMe8k8tZW+lBNYFzvXHieVadAUCZn2TOAAKCRAFzvXHieVa dDM2EADlgFfHuVhxzRAUFXYWHUVshXFxWppVaI2v5v3WGzmcm7zvWzdbsomUorOAM4w2QFCwsDN PJZej/v53j1864dRgzEt//OCLG0Aml64rVd+A18JSeWFilp2+8IqsCWCC49xieiGaKAjnR9/FXi GAk11s6XWPPCFd1vEnja3OE1Kp6TZcNaIf9jsYW6LKRYYDEh89rEqiLAWf0agyxJQMO+1OavFx+ 6Hdtkf/HlsY+H73meaETjIVWM1AXvt988Yu0kvkhida8VG4/+kVWKijsCtx+cdXkWOTD1BsGftQ euSOSzywcmO2/KIiLCmKxBxbHjB1dbmh4af3EJsLGPfn+TYpVjzl8cD0XKPs1lihcKpBDZ37uQC 2CIdQtSUaEAhEyT1+/HGqKcy+dh+yOaUSS4ZhBLQqzJ57Xay5MdPdJaXqoTwgW25EC+zhNvHZHH 8nmOg2DG2sX/x4efwlJREEYyn3xyI/qJwrtAcGnq+pUcH3p2uMkw8HZZ7lbSk6VSPdkV70BARQB HDZJn9s81iYNlOXQ9jIs0G6/PdCGpDKccBo+YhRrTQs3TxT40N42FRHWkGVw4+AmwQyMx5hzg7c P+KRXpRdpDc7U2qHN//R/Fhmgo1UKO0Mys4bonya867dRAYlX/GsHCjVMOzi6a6d7nhxWhgrEaH 4XGDW5tOTotTdbg== X-Developer-Key: i=ayush@beagleboard.org; a=openpgp; fpr=DFCC131EF24F2D656FA504D605CEF5C789E55A74 Adds support for SPI mikroBUS addon boards with configuration based on device tree. The goal is to get a minimal version in mainline to sort out the device tree structure that should be used. A mikroBUS board can use any combination of the following based protocols: I2C, SPI, UART, PWM, Analog, GPIO with possibility of all pins being used as GPIO instead of their original purpose. This requires the driver to be flexible and identify the type of board based on the compatible string. Signed-off-by: Ayush Singh --- MAINTAINERS | 1 + drivers/misc/Kconfig | 16 +++ drivers/misc/Makefile | 1 + drivers/misc/mikrobus.c | 361 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 379 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 88f2b3adc824..01a0ac261e6c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15115,6 +15115,7 @@ S: Maintained F: Documentation/devicetree/bindings/connector/mikrobus-connector.yaml F: Documentation/devicetree/bindings/mikrobus/mikrobus-board.yaml F: Documentation/devicetree/bindings/mikrobus/mikrobus-spi.yaml +F: drivers/misc/mikrobus.c MIKROTIK CRS3XX 98DX3236 BOARD SUPPORT M: Luka Kovacic diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index faf983680040..320f408cc612 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -585,6 +585,22 @@ config NSM To compile this driver as a module, choose M here. The module will be called nsm. +menuconfig MIKROBUS + tristate "Module for instantiating devices on mikroBUS ports" + depends on GPIOLIB + 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 mikroBUS manifest which is + passed using a sysfs interface. + + + 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 + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 153a3f4837e8..f10f1414270b 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -69,3 +69,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-$(CONFIG_MIKROBUS) += mikrobus.o diff --git a/drivers/misc/mikrobus.c b/drivers/misc/mikrobus.c new file mode 100644 index 000000000000..bf160a0e8903 --- /dev/null +++ b/drivers/misc/mikrobus.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0: +/* + * Copyright 2024 Ayush Singh + */ + +#define pr_fmt(fmt) "mikrobus:%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct mikrobus_spi_cs_item { + const char *cs_name; + u32 cs; +}; + +/** + * struct mikrobus_port - MikroBUS Driver + * + * @dev: underlying platform_device + * @board_ocs: board device tree changeset + * @pinctrl: mikroBUS pinctrl + * @mikrobus_spi_cs: list of supported chipselect address and name + * @mikrobus_spi_cs_count: length of mikrobus_spi_cs + * @spi_ctrl: spi controller of mikroBUS connector + * @spi_dev: spi mikroBUS board + */ +struct mikrobus_port { + struct platform_device *dev; + struct of_changeset board_ocs; + struct pinctrl *pctrl; + + struct mikrobus_spi_cs_item *spi_cs; + int spi_cs_count; + struct spi_controller *spi_ctrl; + struct spi_device *spi_dev; +}; + +/* + * mikrobus_pinctrl_select: Select pinctrl state for mikrobus pin + * + * @port: mikrobus port + * @pinctrl_selected: pinctrl state to be selected + */ +static int mikrobus_pinctrl_select(struct device *dev, + const char *pinctrl_selected) +{ + int ret; + struct pinctrl_state *state; + struct mikrobus_port *mb = dev_get_drvdata(dev); + + state = pinctrl_lookup_state(mb->pctrl, pinctrl_selected); + if (IS_ERR(state)) + return dev_err_probe(dev, PTR_ERR(state), + "failed to find state %s", + pinctrl_selected); + + ret = pinctrl_select_state(mb->pctrl, state); + if (ret) + return dev_err_probe(dev, ret, "failed to select state %s", + pinctrl_selected); + + dev_dbg_ratelimited(dev, "setting pinctrl %s", pinctrl_selected); + + return 0; +} + +/* + * mikrobus_lookup_cs - lookup mikroBUS SPI chipselect by name + * + * @mb: mikroBUS port + * @cs_name: chipselect name + */ +static int mikrobus_lookup_cs(const struct mikrobus_port *mb, + const char *cs_name) +{ + for (int i = 0; i < mb->spi_cs_count; ++i) { + if (strcmp(cs_name, mb->spi_cs[i].cs_name) == 0) + return mb->spi_cs[i].cs; + } + + return -1; +} + +static int mikrobus_spi_set_cs(struct device *dev, struct device_node *np) +{ + struct mikrobus_port *mb = dev_get_drvdata(dev); + const char *temp_str; + int reg_len; + int ret, i; + u32 *reg = NULL; + + reg_len = of_property_count_strings(np, "spi-cs"); + /* Use default cs if spi-cs property not present */ + if (reg_len <= 0) { + reg_len = 1; + reg = devm_kmalloc_array(dev, reg_len, sizeof(*reg), + GFP_KERNEL); + if (!reg) + return -ENOMEM; + + ret = mikrobus_lookup_cs(mb, "default"); + if (ret < 0) + goto free_reg; + + reg[0] = ret; + } else { + reg = devm_kmalloc_array(dev, reg_len, sizeof(*reg), + GFP_KERNEL); + if (!reg) + return -ENOMEM; + + for (i = 0; i < reg_len; ++i) { + ret = of_property_read_string_index(np, "spi-cs", i, + &temp_str); + if (ret < 0) + goto free_reg; + + ret = mikrobus_lookup_cs(mb, temp_str); + if (ret < 0) + goto free_reg; + + reg[i] = ret; + } + } + + ret = of_changeset_add_prop_u32_array(&mb->board_ocs, np, "reg", reg, + reg_len); + if (ret < 0) + goto free_reg; + + ret = of_changeset_apply(&mb->board_ocs); + if (ret < 0) + goto free_reg; + + devm_kfree(dev, reg); + return 0; + +free_reg: + devm_kfree(dev, reg); + return ret; +} + +static int of_register_mikrobus_device(struct mikrobus_port *mb, + struct device_node *np) +{ + const char *temp_str; + int i, pinctrl_count, ret; + struct spi_device *spi_dev; + struct device *dev = &mb->dev->dev; + + pinctrl_count = of_property_count_strings(np, "pinctrl-apply"); + if (pinctrl_count < 0) + return dev_err_probe(dev, pinctrl_count, + "Missing required property pinctrl-apply"); + + for (i = 0; i < pinctrl_count; ++i) { + ret = of_property_read_string_index(np, "pinctrl-apply", i, + &temp_str); + if (ret < 0) + return ret; + + ret = mikrobus_pinctrl_select(dev, temp_str); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to set pinctrl"); + } + + if (mb->spi_ctrl && !mb->spi_dev && + of_device_is_compatible(np, "mikrobus-spi")) { + ret = mikrobus_spi_set_cs(dev, np); + if (ret < 0) + return dev_err_probe(dev, ret, + "Failed to set SPI chipselect"); + + spi_dev = of_register_spi_device(mb->spi_ctrl, np); + if (IS_ERR(spi_dev)) + return dev_err_probe(dev, PTR_ERR(spi_dev), + "Failed to register SPI device"); + mb->spi_dev = spi_dev; + } + + return 0; +} + +static int of_register_mikrobus_board(struct mikrobus_port *mb) +{ + struct device *dev = &mb->dev->dev; + int board_len, i, ret; + struct device_node *np; + + board_len = of_count_phandle_with_args(dev->of_node, "board", NULL); + for (i = 0; i < board_len; ++i) { + np = of_parse_phandle(dev->of_node, "board", i); + if (!np) { + ret = dev_err_probe(dev, -ENODEV, "Board not found"); + goto free_np; + } + + ret = of_register_mikrobus_device(mb, np); + if (ret < 0) + goto free_np; + + of_node_put(np); + } + + return 0; +free_np: + of_node_put(np); + return ret; +} + +static int mikrobus_port_probe(struct platform_device *pdev) +{ + int ret, i; + struct mikrobus_port *mb; + struct device_node *np; + struct device *dev = &pdev->dev; + + mb = devm_kmalloc(dev, sizeof(*mb), GFP_KERNEL); + if (!mb) + return -ENOMEM; + + dev_set_drvdata(dev, mb); + + of_changeset_init(&mb->board_ocs); + mb->dev = pdev; + mb->pctrl = NULL; + mb->spi_ctrl = NULL; + mb->spi_dev = NULL; + mb->spi_cs = NULL; + mb->spi_cs_count = 0; + + mb->pctrl = devm_pinctrl_get(dev); + if (IS_ERR(mb->pctrl)) + return dev_err_probe(dev, PTR_ERR(mb->pctrl), + "failed to get pinctrl [%ld]", + PTR_ERR(mb->pctrl)); + + np = of_parse_phandle(dev->of_node, "spi-controller", 0); + if (np) { + mb->spi_ctrl = of_find_spi_controller_by_node(np); + if (mb->spi_ctrl) { + ret = of_property_count_u32_elems(dev->of_node, + "spi-cs"); + if (ret < 0) { + dev_err(dev, "Missing property spi-cs"); + goto free_np; + } + + mb->spi_cs_count = ret; + + ret = of_property_count_strings(dev->of_node, + "spi-cs-names"); + if (ret < 0) { + dev_err(dev, "Missing property spi-cs-names"); + goto free_np; + } + + if (mb->spi_cs_count != ret) { + ret = dev_err_probe( + dev, -EINVAL, + "spi-cs and spi-cs-names out of sync"); + goto free_np; + } + + mb->spi_cs = devm_kmalloc_array(dev, mb->spi_cs_count, + sizeof(*mb->spi_cs), + GFP_KERNEL); + if (!mb->spi_cs) { + ret = -ENOMEM; + goto free_np; + } + + for (i = 0; i < mb->spi_cs_count; ++i) { + of_property_read_u32_index(dev->of_node, + "spi-cs", i, + &mb->spi_cs->cs); + of_property_read_string_index( + dev->of_node, "spi-cs-names", i, + &mb->spi_cs->cs_name); + } + } + } + of_node_put(np); + + ret = of_register_mikrobus_board(mb); + if (ret < 0) + return dev_err_probe(dev, -EINVAL, + "Failed to register mikrobus board"); + + return 0; + +free_np: + of_node_put(np); + return ret; +} + +static void mikrobus_port_remove(struct platform_device *pdev) +{ + struct mikrobus_port *mb = dev_get_drvdata(&pdev->dev); + + spi_unregister_device(mb->spi_dev); + + of_changeset_revert(&mb->board_ocs); +} + +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 = mikrobus_port_of_match, + }, +}; + +static const struct bus_type mikrobus_bus_type = { + .name = "mikrobus", +}; + +static int mikrobus_init(void) +{ + int ret; + + ret = bus_register(&mikrobus_bus_type); + if (ret) { + pr_err("bus_register failed (%d)", ret); + return ret; + } + + ret = platform_driver_register(&mikrobus_port_driver); + if (ret) + pr_err("driver register failed [%d]", ret); + + return 0; +} + +module_init(mikrobus_init); + +static void mikrobus_exit(void) +{ + platform_driver_unregister(&mikrobus_port_driver); + bus_unregister(&mikrobus_bus_type); +} + +module_exit(mikrobus_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ayush Singh "); +MODULE_DESCRIPTION("mikroBUS driver for linux"); +MODULE_VERSION("0.1");