From patchwork Thu Aug 23 10:33:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 144901 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp24116ljw; Thu, 23 Aug 2018 03:33:53 -0700 (PDT) X-Google-Smtp-Source: AA+uWPwEu7exai04XwUO3VMQC5wjASihESR9KqgFMP7uC2X50BGMpgOTSIZlhtLMeligIMrt3eRv X-Received: by 2002:a65:448c:: with SMTP id l12-v6mr54907111pgq.277.1535020432879; Thu, 23 Aug 2018 03:33:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535020432; cv=none; d=google.com; s=arc-20160816; b=j5bFSto9Tix/1ZQvX2Ocpfp1A5RvZCdA2qEBZNpZw1FsikaxqdJj8LYPRYjOXbc+s1 V9/C7oY3nTSUUiicOaBaT5co71xXWRGoGtF+UKSSAC5l9JvgtNmSD5iKLo6WDusU/xCX 2ta3DjE1BcedXl9hNOdDtRPeWfGqyC1jXkzJkGEGU78O2uylhUva0pz5i9wlDWySHxFM /mYSsCYws87c1AKcsI5hVPw0GAm9MNrCfhC1ksDa2fUgtTZ/AjoKpOLLJetdMYz3nTlH TxruCu8sLwik4q4RQjvNrs7pDzbok4SmAOG9swjofksNKn9e5nh7pc3PL2C6FYCW8ADL WHAA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=6Ph8FOTe30oWA9DunxxoHHQkqbM6/3H5VfapCYKHjz8=; b=klfAt8n2bf+IG4MObI4VGOCiv7jDafcjBNMeJvE253iNJ+j8YVr8jXKaXR3CsftkK/ ubreMs9L5j1ZaRMvm/QMrTPtsrPsXcu284CEosDA+gS0CapWLBB77DVHEa81zWyaS4pf ELjvjq2oyNU+b9op+a3jvW6Y1hSa0c5d5F3B4sa3SNYql1MYdyMSEvHpU+WtV9AMEG6v p5yfvyHp5evQ3iIKHRI/Xviiejyxp5ny9wnv0LZyRrjC1mwZ1A5wrzUu7wK9YDoRK4O3 dBo6D6MwEvS1ttyn/5VHofWFKD03blIJ5zBbANz1YJN8Ny40pShhUjIy/gnAzoCb3Msd a+AA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BJ5p2eeZ; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 5-v6si4040393pls.431.2018.08.23.03.33.52; Thu, 23 Aug 2018 03:33:52 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=BJ5p2eeZ; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727823AbeHWOCz (ORCPT + 6 others); Thu, 23 Aug 2018 10:02:55 -0400 Received: from mail-lj1-f196.google.com ([209.85.208.196]:38019 "EHLO mail-lj1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728110AbeHWOCz (ORCPT ); Thu, 23 Aug 2018 10:02:55 -0400 Received: by mail-lj1-f196.google.com with SMTP id p6-v6so3761140ljc.5 for ; Thu, 23 Aug 2018 03:33:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6Ph8FOTe30oWA9DunxxoHHQkqbM6/3H5VfapCYKHjz8=; b=BJ5p2eeZvSyIc0FV9hey+AybPljaO2vN/E8U0iNBNtBFRIzBE1+kVLk4rebb3Cmm99 kkuJ8AZZZmuSEtvLfC46rntJNB94gUeEXtKhWh9B1lzn+9GiIzKpw7TibRLtEBtoIQcm 1r3fubglzqMR6h6o0x2EmdnZ3/qV1gKOGhH4w= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6Ph8FOTe30oWA9DunxxoHHQkqbM6/3H5VfapCYKHjz8=; b=q3+STOlweLf2IR8TPXGbAq8iuxJGir33xMqZLyiNKx7RM3qWsDPMIsHaZ0e15z25P8 ONMWTQm7FFeWF83jYXYLVddfOUDnFKChpB1Ot5ObZrrWSRLG06RshhKo4AK79qrLBHvu WHNV76HqvCyfbPpkg1VywUch6qgWxJ7gejoVYjiLXEESskU+oPLFmgHjP4X7GtRpFjaf kuMby+hppzP2CNOkTJ5cuCN7GQvGwooElLh443fw5z5Mot68fcHkYl3wFd+pv3pXG36W qKjtqjLcsAIjuFGVOKfgG2EjYSqxqihjegymXqvpSPBYbL7FMRNluVz1zSsEFmHPRSn1 jl0A== X-Gm-Message-State: APzg51BQr37sEttkO4lLJf5SHpuUw93278/j5pbzq4Df+Md4Qu9GWV2D G32mdkzoz2Eb+t/wkjy1Uxz3bg== X-Received: by 2002:a2e:8807:: with SMTP id x7-v6mr5290625ljh.98.1535020429925; Thu, 23 Aug 2018 03:33:49 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id s74-v6sm556898lfg.79.2018.08.23.03.33.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 23 Aug 2018 03:33:48 -0700 (PDT) From: Linus Walleij To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, dev@lists.96boards.org Cc: John Stultz , Manivannan Sadhasivam , Rob Herring , Mark Rutland , Frank Rowand , Mark Brown , Michal Simek , Andy Shevchenko , Mika Westerberg , Arnd Bergmann , Linus Walleij , Bartosz Golaszewski , linux-i2c@vger.kernel.org Subject: [PATCH 1/4] eeprom: at24: Allow passing gpiodesc from pdata Date: Thu, 23 Aug 2018 12:33:29 +0200 Message-Id: <20180823103332.32047-2-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180823103332.32047-1-linus.walleij@linaro.org> References: <20180823103332.32047-1-linus.walleij@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This makes it possible to pass an initialized GPIO descriptor to the driver through platform data. This is useful when we are dealing with EEPROMs on expansion boards where the GPIO has to be looked up indirectly using a connector abstraction (several systems using the same connector) so the machine descriptor tables cannot be used to associate the descriptor with the device and we then want to pass this descriptor on to the EEPROM driver this way instead. Cc: Bartosz Golaszewski Cc: linux-i2c@vger.kernel.org Signed-off-by: Linus Walleij --- ChangeLog v1->v2: - No changes - Requesting an ACK from the EEPROM maintainer (Bartosz) so we can apply this to the ARM SoC tree with the series depending on it. --- drivers/misc/eeprom/at24.c | 6 +++++- include/linux/platform_data/at24.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) -- 2.17.0 diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index f5cc517d1131..d577cdbe221e 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -662,7 +662,11 @@ static int at24_probe(struct i2c_client *client) at24->client[0].client = client; at24->client[0].regmap = regmap; - at24->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH); + if (pdata.wp_gpiod) + at24->wp_gpio = pdata.wp_gpiod; + else + at24->wp_gpio = + devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH); if (IS_ERR(at24->wp_gpio)) return PTR_ERR(at24->wp_gpio); diff --git a/include/linux/platform_data/at24.h b/include/linux/platform_data/at24.h index 63507ff464ee..5606fb2ef76c 100644 --- a/include/linux/platform_data/at24.h +++ b/include/linux/platform_data/at24.h @@ -11,6 +11,7 @@ #include #include #include +#include /** * struct at24_platform_data - data to set up at24 (generic eeprom) driver @@ -55,6 +56,7 @@ struct at24_platform_data { void (*setup)(struct nvmem_device *nvmem, void *context); void *context; + struct gpio_desc *wp_gpiod; }; #endif /* _LINUX_AT24_H */ From patchwork Thu Aug 23 10:33:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 144904 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp24238ljw; Thu, 23 Aug 2018 03:34:04 -0700 (PDT) X-Google-Smtp-Source: AA+uWPx4E6VdRYhFO4/X33oP/mKhWn33EquRv89JPMZRoJZD8yusaVJoljpQqu0epltvi8eVZFAw X-Received: by 2002:a63:5a50:: with SMTP id k16-v6mr19001952pgm.143.1535020444048; Thu, 23 Aug 2018 03:34:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535020444; cv=none; d=google.com; s=arc-20160816; b=R3OJcPlzTUVTHSjzMEu8Qg932lc7jLMcgNjuWOo2nu4aW+s0Mve0OFAKE8beTIIOb8 gjPsp9FHnmp8kUmajrMHtac5PpznnC4uAYHPsWK4Ygg0Ris+kRtWPJpJhbd7t5vdfORp ukXCInSZD1iSIkZTBmklSgPye0kiWdcsXCK0pYSNFs3EfcTK4xF99Sp9SqqDB9AjM4l4 q1z2JT4N9U1oVm2bPtDDUWrwC+OqYtIGM99g0v5k70Jw4PWM0atM3O5kMzQffmniC9E9 M2oe/4YDgaTmysgfLva4U2Mp89ClrOWVY2SHiVr2AkKHwcHnT9Ao+UDABe4+X7g/vm9c 0y5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=5kdNiVVY2+RldOBk6Dr0dm1AR4mbahJUY+eFrDw60tw=; b=HZbMHMn+Q0gdR98l555XMCSW/jiSPE4SlMcDLZPQnfmtXwdZNVt2OHMmOjOTz95EqZ JcHauhZ2Ahu+wPzReO4Ty3fMi97MD3AQdFJMRLQlpbYR4G5Mqdq/Hma29jRyzdLBj1yp Hcde674v9POTrstEOXMvKFXME5HJ7LgsZAq9jmrd3MJgdybSOdwOPsSeEvoBqtE1RLex bTkqfVRjnFQqJTVqZVfpu5qi0OE3VysXR51+teF/vemZ7k4ca6Zzp3p3I0m0GiiJom0g MVkrowldc5zkzwdqLShzxlfJMqWF2sTmO06EUqjrJtd6YmS5gdyBSrGrRkBTnhmVFK7m EVUQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EHRwt7aT; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p9-v6si4088404pgi.553.2018.08.23.03.34.03; Thu, 23 Aug 2018 03:34:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=EHRwt7aT; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728283AbeHWODA (ORCPT + 6 others); Thu, 23 Aug 2018 10:03:00 -0400 Received: from mail-lf1-f67.google.com ([209.85.167.67]:42952 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728205AbeHWODA (ORCPT ); Thu, 23 Aug 2018 10:03:00 -0400 Received: by mail-lf1-f67.google.com with SMTP id z11-v6so3670988lff.9 for ; Thu, 23 Aug 2018 03:33:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5kdNiVVY2+RldOBk6Dr0dm1AR4mbahJUY+eFrDw60tw=; b=EHRwt7aTwALas9xP/DorNhtrB9RNy5Lymcx+IdKpsBQMmrQMoVQS9EKyZxic+UC5kY 9rjafgZZ1tMEc+HlyjBo+lrTY7WeL4zRxN0ZhhFDfd79dJrlp6dHLqBv12DfX82VYugZ ch+Cprasm1gUI6PSA3R4ahgcYCEqBFHa79tuU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5kdNiVVY2+RldOBk6Dr0dm1AR4mbahJUY+eFrDw60tw=; b=LPmg9KP3xHGNJWZmTnm4tPq9JAgm8MzXBX/r7YX3uZc+LxnTfHI1kHsX5Ow4G+i22j wb6tiWkVQ3WIyDf02Uo/gOYWCBQ3AQBKzhKZUMqHwWqGjIRz1ZC7tHYPyqEU8WeN3H17 h1cThm3klr2nFEwUevuSqEd7BecCQ3+znWDGrgMisY1CmkSosg+cKQrvN9Atin9cwk2T 9jNcA22dUoH3x1sMJLbFw7kaLewngfTGe1eN69Z12MpFZfePW/tbHlBRvC6Es8uHO081 ATk3NMWBV18VjguZ+V8jSs5DkdZn1AqFeF/w1llFdyg/f6V/J0ni17fkcFyw42NnFx/t 8g1g== X-Gm-Message-State: AOUpUlEMhoqG/4M/Gm7nUlx3iBhAO1MxawauZglKIzRWo4j0nm8m30An /D/HDtLUt6kFEHrBy74n4U4AAw== X-Received: by 2002:a19:5353:: with SMTP id h80-v6mr23946462lfb.9.1535020435528; Thu, 23 Aug 2018 03:33:55 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id s74-v6sm556898lfg.79.2018.08.23.03.33.53 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 23 Aug 2018 03:33:54 -0700 (PDT) From: Linus Walleij To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, dev@lists.96boards.org Cc: John Stultz , Manivannan Sadhasivam , Rob Herring , Mark Rutland , Frank Rowand , Mark Brown , Michal Simek , Andy Shevchenko , Mika Westerberg , Arnd Bergmann , Linus Walleij Subject: [PATCH 3/4] bus: Add DT bindings for 96Boards low speed connector Date: Thu, 23 Aug 2018 12:33:31 +0200 Message-Id: <20180823103332.32047-4-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180823103332.32047-1-linus.walleij@linaro.org> References: <20180823103332.32047-1-linus.walleij@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org We need to be able to grab resources on a 96Boards low speed connector to populate and use a daughterboard, so define some very rudimentary properties simply passing phandles for the resources used on the low speed connector. Signed-off-by: Linus Walleij --- .../bus/96boards,low-speed-connector.txt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/devicetree/bindings/bus/96boards,low-speed-connector.txt -- 2.17.0 diff --git a/Documentation/devicetree/bindings/bus/96boards,low-speed-connector.txt b/Documentation/devicetree/bindings/bus/96boards,low-speed-connector.txt new file mode 100644 index 000000000000..6631b3edd01f --- /dev/null +++ b/Documentation/devicetree/bindings/bus/96boards,low-speed-connector.txt @@ -0,0 +1,50 @@ +96Boards Low Speed Connectors + +The 96Boards connectors represent a non-dicoverable Low Speed (LS) +and High Speed (HS) external bus on the 96Board development +boards. Each 96Board presents both of these connectors. + +The Low Speed (LS) connector is a 40 pin 2x20 female pin header: +- Power +- Two buttons: power and reset +- 2 x UART one optional with just RX/TX, one required with modem + CTS/RTS +- 2 x I2C +- 1 x SPI +- 1 x I2S (audio) +- 12 x GPIO lines named GPIO-A thru GPIO-L + +Further details on the electronics and signals are available in +"96Boards Consumer Edition, Low Cost Hardware Platform Specification" +As of writing version 1.0, January 2015. + +Required properties: + +- compatible: shall be "96boards,low-speed-connector" +- i2c0: phandle to the I2C0 bus +- i2c1: phandle to the I2C1 bus +- spi: phandle to the SPI bus +- gpios: a list of phandles to the GPIOs connected to the + connector. The handles need to be uniformly specified with the + 0 flag as the connector is not the end consumer. + +Example: + +lscon: connector { + compatible = "96boards,low-speed-connector"; + i2c0 = <&i2csw_0>; + i2c1 = <&i2csw_1>; + spi = <&spi0>; + gpios = <&gpio 36 0>, /* GPIO-A */ + <&gpio 37 0>, /* GPIO-B */ + <&gpio 39 0>, /* GPIO-C */ + <&gpio 40 0>, /* GPIO-D */ + <&gpio 44 0>, /* GPIO-E */ + <&gpio 45 0>, /* GPIO-F */ + <&gpio 78 0>, /* GPIO-G */ + <&gpio 79 0>, /* GPIO-H */ + <&gpio 80 0>, /* GPIO-I */ + <&gpio 81 0>, /* GPIO-J */ + <&gpio 82 0>, /* GPIO-K */ + <&gpio 83 0>; /* GPIO-L */ +}; From patchwork Thu Aug 23 10:33:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 144903 Delivered-To: patch@linaro.org Received: by 2002:a2e:1648:0:0:0:0:0 with SMTP id 8-v6csp24231ljw; Thu, 23 Aug 2018 03:34:03 -0700 (PDT) X-Google-Smtp-Source: AA+uWPymKDt2RcHNlMk7+jWx1nK1N3JTX/0yn22jCem1TG9vCxckQ2RABwNkciPPbwv4AzwjTkH8 X-Received: by 2002:a63:1c47:: with SMTP id c7-v6mr16847627pgm.38.1535020443025; Thu, 23 Aug 2018 03:34:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535020443; cv=none; d=google.com; s=arc-20160816; b=FuLYEUlh26NgTba6xriveNnawpQI5JpQp0A9F9PQxCkUM++H1fSr2ZnJfbxNq8/PP5 0k3hldx4CM45r5EuNvhAFS6mt7FqnzMBULByycMf0WYORLirbXeLvMCVXI3jhkNFVU6Z Jh9ks+nVwQv3LWOzGoVoJvJJqov18n5/hrah5GXBODzMRH8hdWcWbopDl5b+rUyrmL7l YYUY/Dmsjun4JDdsDi4i/VUMv77Q1uwJ538WLxz27ShW5QfnB/A1RWJ/kq68Rb2pxpTt V7GO6NP6Fa1/OM6mfY9wkA+KO1k8r/JUmhow5/Uc/Y8fquYqQFORlqabfDvNtz0e0nDx V4oA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=H5fP2+GhFBBl86apj74QkdYDj9HejIZchrRbeBP3faM=; b=qngyJ+QWOmn+pPWSwTNkcnrrPQkiW2pFrtstQesfnxv4nYnAmfdanuYeWWqrTBCu2A X1pX3I7UgqsTcCRejGi4H80B5LtYk8Ki82xJNSW2Znkznlx0AUBXxoItQ1kl8IfynKv3 xYN0F8NMpiD7YuWJRXdLkuRlay69girovGfaSB816nyI/vqBfyvM3JrNuL2a1060Uge1 TEv071jtQOqKhAWtc7cqtrqX4Yx5D83KP9FTZgpFHXKsWNsMEewzenOchwULg+vD980Y MKyIhhxTk8frhuXeuJQy3eD2jAcwW60Sc0Rp+Fpz95xxcvDD0etsQYOJqXignkp12NER lzTg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VkC6Mq92; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p9-v6si4088404pgi.553.2018.08.23.03.34.02; Thu, 23 Aug 2018 03:34:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VkC6Mq92; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727775AbeHWODF (ORCPT + 6 others); Thu, 23 Aug 2018 10:03:05 -0400 Received: from mail-lj1-f195.google.com ([209.85.208.195]:43821 "EHLO mail-lj1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728206AbeHWODE (ORCPT ); Thu, 23 Aug 2018 10:03:04 -0400 Received: by mail-lj1-f195.google.com with SMTP id m84-v6so3738816lje.10 for ; Thu, 23 Aug 2018 03:33:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=H5fP2+GhFBBl86apj74QkdYDj9HejIZchrRbeBP3faM=; b=VkC6Mq92T/A8rVeL6g11yo6O8rogCFlr3DosfAumBnitsJs5PNRz8ujJzIWzzriNrP ps+KRCfFULpOPN3CUInaNrwOIKpzIt2Dbp7PERBzKci7ooeIYk0EuX63XNkjR23L0kPY nvFn93hhr9FOUc5VG4x1CTmxK062mrlQWNUbs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=H5fP2+GhFBBl86apj74QkdYDj9HejIZchrRbeBP3faM=; b=NS1ButeYN1DazpdaZyhIz7RNucEx8XIKcz4efEgo+iytdkVPOQvH1IVPliqafBKezx mBnWFwy26mIHgv5gfHv2nehzgI84qXp8FxlhuRqYo6gHa10FOwdh/WxqJXwDuEewALBt d/u6JiMEokE1mVfZEea3LB200urg/zlu8KQexZi6Rv7YCkavFzLznukL1WBDr9D7fbYh owkRSKAGFKtSawMjsE7nEm/Ard0qwBCoEq1J8R0eNETKm7P8evPHrc1eyhPNqTp+OdVC cImysaob0/c2Vi5UsUeZK5DWyX9vEb+xajpijDcZIFNRGK8F/oJLaZxRtWxDb0rTMu9q rNuA== X-Gm-Message-State: AOUpUlEul1YjKNucTEwG8f0vyoNIniPwqnXgo/r821QmU2yGHu24APf6 T0UUdn8PQlRvbupy822wKXFWlg== X-Received: by 2002:a2e:5617:: with SMTP id k23-v6mr39013067ljb.86.1535020438209; Thu, 23 Aug 2018 03:33:58 -0700 (PDT) Received: from genomnajs.ideon.se ([85.235.10.227]) by smtp.gmail.com with ESMTPSA id s74-v6sm556898lfg.79.2018.08.23.03.33.56 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 23 Aug 2018 03:33:57 -0700 (PDT) From: Linus Walleij To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, dev@lists.96boards.org Cc: John Stultz , Manivannan Sadhasivam , Rob Herring , Mark Rutland , Frank Rowand , Mark Brown , Michal Simek , Andy Shevchenko , Mika Westerberg , Arnd Bergmann , Linus Walleij Subject: [PATCH 4/4] bus: 96boards Low-Speed Connector Date: Thu, 23 Aug 2018 12:33:32 +0200 Message-Id: <20180823103332.32047-5-linus.walleij@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180823103332.32047-1-linus.walleij@linaro.org> References: <20180823103332.32047-1-linus.walleij@linaro.org> Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This creates a bus for using a small connector driver to plug in "mezzanine boards" on the 96boards low-speed connector either by a very simple compatible string for the entire board, or by simply inserting the board device from userspace. These "mezzanine boards" are no different than "capes", "logic modules", etc. This thing, a non-discoverable connector where a user can plug in a few peripherals has been reinvented a few times. As a proof-of-concept we add the Secure96, a quite minimal mezzanine board. Users can register their boards in a simple way. Either just add their compatible-string in the device tree: board { compatible = "96boards,secure96"; }; And if they can't even change three lines in their device tree, or if they at runtime decide to plug in some board and test it, they can use sysfs, as exemplified by plugging in the secure96 security board at runtime: > cd /sys/bus/96boards-ls-connector-bus > cat supported secure96 > echo secure96 > inject [ 61.014629] lscon connector: called mezzanine_store on secure96 [ 61.020530] lscon connector: populate secure96 [ 61.027081] at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write [ 61.053569] atmel-ecc 1-0060: configuration zone is unlocked [ 61.502535] tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16) (...) The plug-in board can be removed from sysfs and added back again multiple times like this with the devices being runtime added and removed by two writes to sysfs. > echo secure96 > eject > echo secure96 > inject > echo secure96 > eject (...) Signed-off-by: Linus Walleij --- ChangeLog RFC->v1: - Create a new bus type as recommended by Arnd, fixing a bunch of scalability issues and making the whole thing look like most other kernel device driver cores. - Create LS connector devices that have .probe() and .remove() functions like any other device. - Move dynamic device creation to bus attribute files. --- drivers/bus/Kconfig | 2 + drivers/bus/Makefile | 4 +- drivers/bus/daughterboards/96boards-ls-bus.c | 39 ++ .../daughterboards/96boards-ls-connector.c | 367 ++++++++++++++++++ .../bus/daughterboards/96boards-mezzanines.h | 77 ++++ .../bus/daughterboards/96boards-secure96.c | 265 +++++++++++++ drivers/bus/daughterboards/Kconfig | 50 +++ drivers/bus/daughterboards/Makefile | 6 + 8 files changed, 809 insertions(+), 1 deletion(-) create mode 100644 drivers/bus/daughterboards/96boards-ls-bus.c create mode 100644 drivers/bus/daughterboards/96boards-ls-connector.c create mode 100644 drivers/bus/daughterboards/96boards-mezzanines.h create mode 100644 drivers/bus/daughterboards/96boards-secure96.c create mode 100644 drivers/bus/daughterboards/Kconfig create mode 100644 drivers/bus/daughterboards/Makefile -- 2.17.0 diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index d1c0b60e9326..98393c6e2190 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -173,4 +173,6 @@ config DA8XX_MSTPRI source "drivers/bus/fsl-mc/Kconfig" +source "drivers/bus/daughterboards/Kconfig" + endmenu diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index b8f036cca7ff..7a792e3e2cc2 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -29,5 +29,7 @@ obj-$(CONFIG_TI_SYSC) += ti-sysc.o obj-$(CONFIG_TS_NBUS) += ts-nbus.o obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o - obj-$(CONFIG_DA8XX_MSTPRI) += da8xx-mstpri.o + +# Non-discoverable daughterboards +obj-$(CONFIG_DAUGHTERBOARDS) += daughterboards/ diff --git a/drivers/bus/daughterboards/96boards-ls-bus.c b/drivers/bus/daughterboards/96boards-ls-bus.c new file mode 100644 index 000000000000..23de06b3fce3 --- /dev/null +++ b/drivers/bus/daughterboards/96boards-ls-bus.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * 96boards Low-speed Connector bus initialization + * (C) 2018 Linus Walleij + */ +#include +#include +#include +#include "96boards-mezzanines.h" + +static int ls_match(struct device *dev, struct device_driver *drv) +{ + /* First match on OF node */ + if (of_driver_match_device(dev, drv)) + return 1; + + /* Second match on name */ + return !strcmp(dev_name(dev), drv->name); +} + +struct bus_type ls_bus_type = { + .name = "96boards-ls-connector-bus", + .match = ls_match, +}; +EXPORT_SYMBOL_GPL(ls_bus_type); + +static int __init ls_bus_init(void) +{ + int ret; + + /* Register the LS connector bus so devices can start to probe */ + ret = bus_register(&ls_bus_type); + if (ret) { + pr_err("could not register LS connector bus\n"); + return ret; + } + return 0; +} +postcore_initcall(ls_bus_init); diff --git a/drivers/bus/daughterboards/96boards-ls-connector.c b/drivers/bus/daughterboards/96boards-ls-connector.c new file mode 100644 index 000000000000..5c958f47b23e --- /dev/null +++ b/drivers/bus/daughterboards/96boards-ls-connector.c @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * 96boards Low-speed Connector driver + * (C) 2018 Linus Walleij + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "96boards-mezzanines.h" + +static DEFINE_IDA(ls_device_ida); + +static int ls_driver_probe(struct device *dev) +{ + struct ls_device *lsdev = to_ls_device(dev); + struct ls_driver *lsdrv = to_ls_driver(dev->driver); + + if (lsdrv->probe) + return lsdrv->probe(lsdev); + return 0; +} + +static int ls_driver_remove(struct device *dev) +{ + struct ls_device *lsdev = to_ls_device(dev); + struct ls_driver *lsdrv = to_ls_driver(dev->driver); + + if (lsdrv->remove) + lsdrv->remove(lsdev); + return 0; +} + +int ls_driver_register(struct ls_driver *lsdrv) +{ + lsdrv->drv.bus = &ls_bus_type; + lsdrv->drv.probe = ls_driver_probe; + lsdrv->drv.remove = ls_driver_remove; + + return driver_register(&lsdrv->drv); +} +EXPORT_SYMBOL_GPL(ls_driver_register); + +void ls_driver_unregister(struct ls_driver *lsdrv) +{ + driver_unregister(&lsdrv->drv); +} +EXPORT_SYMBOL_GPL(ls_driver_unregister); + +struct gpio_desc *ls_get_gpiod(struct ls_device *ls, + enum ls_gpio pin, + const char *consumer_name, + enum gpiod_flags flags) +{ + struct gpio_desc *retdesc; + + /* + * TODO: get all the LS GPIOs as an array on probe() then + * the consumers can skip error handling of IS_ERR() descriptors + * and this need only set the consumer name. + */ + retdesc = devm_gpiod_get_index(ls->dev.parent, NULL, pin, flags); + if (!IS_ERR(retdesc) && consumer_name) + gpiod_set_consumer_name(retdesc, consumer_name); + + return retdesc; +} +EXPORT_SYMBOL_GPL(ls_get_gpiod); + +/* + * Mezzanine boards will call this to orderly remove their claimed + * gpio descriptors, since we acquired them all with devm_gpiod_get() + * they will eventually be released once this connector device + * disappears if the board do not release them in order. + */ +void ls_put_gpiod(struct ls_device *ls, struct gpio_desc *gpiod) +{ + devm_gpiod_put(ls->dev.parent, gpiod); +} +EXPORT_SYMBOL_GPL(ls_put_gpiod); + +static int lscon_add_device(struct ls_connector *ls, + const char *name, + struct device_node *np) +{ + struct ls_device *lsdev; + int ret; + + lsdev = kzalloc(sizeof(*lsdev), GFP_KERNEL); + if (!lsdev) + return -ENOMEM; + + lsdev->id = ida_simple_get(&ls_device_ida, 0, 0, GFP_KERNEL); + if (lsdev->id < 0) + return lsdev->id; + lsdev->dev.bus = &ls_bus_type; + lsdev->dev.of_node = np; + lsdev->dev.parent = ls->dev; + /* Propagate resources to the device */ + lsdev->i2c0 = ls->i2c0; + lsdev->i2c1 = ls->i2c1; + lsdev->spi = ls->spi; + /* + * In /sys/bus/96boards-ls-connector-bus/devices/ we find + * mezzanine0, mezzanine1 etc OR the device name if inserted + * from userspace. + */ + if (name) + dev_set_name(&lsdev->dev, "%s", name); + else + dev_set_name(&lsdev->dev, "mezzanine%d", lsdev->id); + device_initialize(&lsdev->dev); + ret = device_add(&lsdev->dev); + if (ret) { + dev_err(ls->dev, "failed to add device %s\n", + dev_name(&lsdev->dev)); + return ret; + } + + return 0; +} + +static void lscon_del_device(struct ls_device *lsdev) +{ + device_del(&lsdev->dev); + ida_simple_remove(&ls_device_ida, lsdev->id); + kfree(lsdev); +} + +struct ls_supported_buf { + char *buf; + size_t count; +}; + +static int ls_supported_print(struct device_driver *drv, void *data) +{ + struct ls_supported_buf *buf = data; + size_t count; + + count = snprintf(buf->buf + buf->count, + PAGE_SIZE, "%s\n", drv->name); + buf->count += count; + return 0; +} + +static ssize_t ls_supported_show(struct bus_type *bus, char *buf) +{ + struct ls_supported_buf sbuf; + + /* Loop over the driver list and show supported devices */ + sbuf.buf = buf; + sbuf.count = 0; + bus_for_each_drv(&ls_bus_type, NULL, &sbuf, ls_supported_print); + + return sbuf.count; +} + +static BUS_ATTR(supported, 0444, ls_supported_show, NULL); + +/* + * Match the supplied string to a driver name, if we find + * a match we return 1, saying this device is elegible for + * insertion. + */ +static int ls_inject_match(struct device_driver *drv, void *data) +{ + const char *devname = data; + + if (!strcmp(devname, drv->name)) + return 1; + return 0; +} + +static ssize_t ls_inject_store(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device *dev = ls_bus_type.dev_root; + struct ls_connector *ls = dev_get_drvdata(dev); + char *devname; + int ret; + + devname = kstrdup(buf, GFP_KERNEL); + devname = strstrip(devname); + /* Look if we have a driver for this device */ + ret = bus_for_each_drv(&ls_bus_type, NULL, devname, ls_inject_match); + if (!ret) { + kfree(devname); + return count; + } + + dev_info(ls->dev, "create %s device\n", devname); + /* + * No corresponding DT node + * + * TODO: when we have device tree overlays, this is a good + * place to start when inserting dynamic devices. + */ + lscon_add_device(ls, devname, NULL); + + kfree(devname); + return count; +} + +static BUS_ATTR(inject, 0644, NULL, ls_inject_store); + +static ssize_t ls_eject_store(struct bus_type *bus, + const char *buf, size_t count) +{ + struct device *busdev = ls_bus_type.dev_root; + struct ls_connector *ls = dev_get_drvdata(busdev); + struct ls_device *lsdev; + struct device *dev; + char *devname; + + devname = kstrdup(buf, GFP_KERNEL); + devname = strstrip(devname); + /* Look if we have this device */ + dev = bus_find_device_by_name(&ls_bus_type, NULL, devname); + if (!dev) { + kfree(devname); + return count; + } + + dev_info(ls->dev, "destroy %s device\n", devname); + + lsdev = to_ls_device(dev); + lscon_del_device(lsdev); + kfree(devname); + + return count; +} + +static BUS_ATTR(eject, 0644, NULL, ls_eject_store); + +static int lscon_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *child; + struct spi_controller *spi; + struct ls_connector *ls; + int ret; + + ls = devm_kzalloc(dev, sizeof(*ls), GFP_KERNEL); + if (!ls) + return -ENOMEM; + ls->dev = dev; + + /* Bridge I2C busses */ + child = of_parse_phandle(np, "i2c0", 0); + if (!child) { + dev_err(dev, "no i2c0 phandle\n"); + return -ENODEV; + } + ls->i2c0 = of_get_i2c_adapter_by_node(child); + if (!ls->i2c0) { + dev_err(dev, "no i2c0 adapter, deferring\n"); + return -EPROBE_DEFER; + } + + child = of_parse_phandle(np, "i2c1", 0); + if (!child) { + dev_err(dev, "no i2c1 phandle\n"); + ret = -ENODEV; + goto out_put_i2c0; + } + ls->i2c1 = of_get_i2c_adapter_by_node(child); + if (!ls->i2c1) { + dev_err(dev, "no i2c0 adapter, deferring\n"); + ret = -EPROBE_DEFER; + goto out_put_i2c0; + } + + /* Bridge SPI bus */ + child = of_parse_phandle(np, "spi", 0); + if (!child) { + dev_err(dev, "no spi phandle\n"); + ret = -ENODEV; + goto out_put_i2c1; + } + spi = of_find_spi_controller_by_node(child); + if (!spi) { + dev_err(dev, "no spi controller, deferring\n"); + ret = -EPROBE_DEFER; + goto out_put_i2c1; + } + ls->spi = spi_controller_get(spi); + if (!ls->spi) { + dev_err(dev, "no spi reference\n"); + ret = -ENODEV; + goto out_put_i2c1; + } + + platform_set_drvdata(pdev, ls); + + ls_bus_type.dev_root = dev; + ret = bus_create_file(&ls_bus_type, &bus_attr_supported); + if (ret) + goto out_put_i2c1; + ret = bus_create_file(&ls_bus_type, &bus_attr_inject); + if (ret) + goto out_put_i2c1; + ret = bus_create_file(&ls_bus_type, &bus_attr_eject); + if (ret) + goto out_put_i2c1; + + /* + * Add mezzanine boards as children, stacking possible. + * All direct children of the LS connector will be considered + * mezzanines. + */ + for_each_available_child_of_node(np, child) + lscon_add_device(ls, NULL, child); + + return 0; + +out_put_i2c1: + i2c_put_adapter(ls->i2c1); +out_put_i2c0: + i2c_put_adapter(ls->i2c0); + return ret; +} + +static int lscon_del_dev(struct device *dev, void *data) +{ + struct ls_device *lsdev = to_ls_device(dev); + + lscon_del_device(lsdev); + return 0; +} + +static int lscon_remove(struct platform_device *pdev) +{ + struct ls_connector *ls = platform_get_drvdata(pdev); + + /* Make sure we remove any registered devices */ + bus_for_each_dev(&ls_bus_type, NULL, NULL, lscon_del_dev); + + ls_bus_type.dev_root = NULL; + spi_controller_put(ls->spi); + i2c_put_adapter(ls->i2c1); + i2c_put_adapter(ls->i2c0); + + return 0; +} + +static const struct of_device_id lscon_of_match[] = { + { + .compatible = "96boards,low-speed-connector", + }, + { }, +}; + +static struct platform_driver lscon_driver = { + .driver = { + .name = "lscon", + .of_match_table = of_match_ptr(lscon_of_match), + }, + .probe = lscon_probe, + .remove = lscon_remove, +}; +builtin_platform_driver(lscon_driver); diff --git a/drivers/bus/daughterboards/96boards-mezzanines.h b/drivers/bus/daughterboards/96boards-mezzanines.h new file mode 100644 index 000000000000..93d2c6c910ed --- /dev/null +++ b/drivers/bus/daughterboards/96boards-mezzanines.h @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +/** + * enum ls_gpio - the GPIO lines on the low-speed connector + */ +enum ls_gpio { + LS_GPIO_A = 0, + LS_GPIO_B, + LS_GPIO_C, + LS_GPIO_D, + LS_GPIO_E, + LS_GPIO_F, + LS_GPIO_G, + LS_GPIO_H, + LS_GPIO_I, + LS_GPIO_J, + LS_GPIO_K, + LS_GPIO_L, +}; + +/* + * We try to use the most simplistic device model: here is the LS + * connector, it is a custom bus with its own type of devices and drivers + * on it. + */ + +extern struct bus_type ls_bus_type; + +/** + * struct ls_connector - the connector per se + * @dev: parent device (platform device in the device tree case) + * @i2c0: upward i2c0 I2C bus + * @i2c1: upward i2c1 I2C bus + * @spi: upward SPI bus + */ +struct ls_connector { + struct device *dev; + struct i2c_adapter *i2c0; + struct i2c_adapter *i2c1; + struct spi_controller *spi; +}; + +struct ls_device { + struct device dev; + const char *compatible; + int id; + struct i2c_adapter *i2c0; + struct i2c_adapter *i2c1; + struct spi_controller *spi; +}; + +struct ls_driver { + struct device_driver drv; + struct dev_ext_attribute ext_attr; + int (*probe)(struct ls_device *); + void (*remove)(struct ls_device *); +}; + +#define to_ls_device(d) \ + container_of(d, struct ls_device, dev) +#define to_ls_driver(d) \ + container_of(d, struct ls_driver, drv) + +extern int ls_driver_register(struct ls_driver *); +extern void ls_driver_unregister(struct ls_driver *); + +struct gpio_desc *ls_get_gpiod(struct ls_device *ls, + enum ls_gpio pin, + const char *consumer_name, + enum gpiod_flags flags); +void ls_put_gpiod(struct ls_device *ls, + struct gpio_desc *gpiod); diff --git a/drivers/bus/daughterboards/96boards-secure96.c b/drivers/bus/daughterboards/96boards-secure96.c new file mode 100644 index 000000000000..28053c646ba9 --- /dev/null +++ b/drivers/bus/daughterboards/96boards-secure96.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * 96boards Secure96 mezzanine board driver + * (C) 2018 Linus Walleij + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "96boards-mezzanines.h" + +struct secure96 { + struct device *dev; + struct ls_device *ls; + struct platform_device *leds_device; + struct gpio_led *secure96_leds; + struct i2c_client *eeprom; + struct i2c_client *crypto; + struct i2c_client *hash; + struct gpio_desc *tpm_reset; + struct gpio_desc *tpm_irq; + struct spi_device *tpm; +}; + +struct secure96_ledinfo { + enum ls_gpio pin; + const char *ledname; +}; + +/* + * GPIO-F, G, H and I are connected to LEDs, two red and two green + */ +static const struct secure96_ledinfo ledinfos[] = { + { + .pin = LS_GPIO_F, + .ledname = "secure96:red:0", + }, + { + .pin = LS_GPIO_G, + .ledname = "secure96:red:1", + }, + { + .pin = LS_GPIO_H, + .ledname = "secure96:green:0", + }, + { + .pin = LS_GPIO_I, + .ledname = "secure96:green:1", + }, +}; + +/* + * The On Semiconductor CAT21M01 is 131072bits i.e. 16KB. This should be + * mostly compatible to 24c128 so we register that with special pdata so + * that we can fill in the GPIO descriptor for write protect. + */ +static struct at24_platform_data secure96_eeprom_pdata = { + .byte_len = SZ_16K / 8, + .page_size = 256, + .flags = AT24_FLAG_ADDR16, +}; + +static const struct i2c_board_info secure96_eeprom = { + I2C_BOARD_INFO("24c128", 0x50), + .platform_data = &secure96_eeprom_pdata, +}; + +/* Crypto chip */ +static const struct i2c_board_info secure96_crypto = { + I2C_BOARD_INFO("atecc508a", 0x60), +}; + +/* SHA hash chip */ +static const struct i2c_board_info secure96_hash = { + I2C_BOARD_INFO("atsha204a", 0x64), +}; + +/* Infineon SLB9670 TPM 2.0 chip */ +static struct spi_board_info secure96_tpm = { + .modalias = "tpm_tis_spi", + /* The manual says 22.5MHz for 1.8V supply */ + .max_speed_hz = 22500000, + .chip_select = 0, +}; + +int secure96_probe(struct ls_device *ls) +{ + struct device *dev = &ls->dev; + struct secure96 *sec; + struct gpio_desc *gpiod; + struct gpio_led_platform_data secure96_leds_pdata; + int ret; + int i; + + sec = devm_kzalloc(dev, sizeof(*sec), GFP_KERNEL); + if (!sec) + return -ENOMEM; + sec->dev = dev; + sec->ls = ls; + + sec->secure96_leds = devm_kzalloc(dev, + ARRAY_SIZE(ledinfos) * sizeof(*sec->secure96_leds), + GFP_KERNEL); + if (!sec->secure96_leds) + return -ENOMEM; + + dev_info(dev, "populate secure96\n"); + + /* Populate the four LEDs */ + for (i = 0; i < ARRAY_SIZE(ledinfos); i++) { + const struct secure96_ledinfo *linfo; + + linfo = &ledinfos[i]; + + gpiod = ls_get_gpiod(ls, linfo->pin, linfo->ledname, + GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) { + dev_err(dev, "failed to get GPIO line %d\n", + linfo->pin); + return -ENODEV; + } + sec->secure96_leds[i].gpiod = gpiod; + sec->secure96_leds[i].name = linfo->ledname; + /* Heartbeat on first LED */ + if (i == 0) + sec->secure96_leds[i].default_trigger = "heartbeat"; + } + + secure96_leds_pdata.num_leds = ARRAY_SIZE(ledinfos); + secure96_leds_pdata.leds = sec->secure96_leds; + + sec->leds_device = platform_device_register_data(dev, + "leds-gpio", + PLATFORM_DEVID_AUTO, + &secure96_leds_pdata, + sizeof(secure96_leds_pdata)); + if (IS_ERR(sec->leds_device)) { + dev_err(dev, "failed to populate LEDs device\n"); + return -ENODEV; + } + + /* Populate the three I2C0 devices */ + gpiod = ls_get_gpiod(ls, LS_GPIO_B, "cat21m01-wp", + GPIOD_OUT_HIGH); + if (IS_ERR(gpiod)) + dev_err(dev, "no CAT21M01 write-protect GPIO\n"); + else + secure96_eeprom_pdata.wp_gpiod = gpiod; + sec->eeprom = i2c_new_device(ls->i2c0, &secure96_eeprom); + if (!sec->eeprom) { + dev_err(dev, "failed to populate EEPROM\n"); + ret = -ENODEV; + goto out_unreg_leds; + } + + sec->crypto = i2c_new_device(ls->i2c0, &secure96_crypto); + if (!sec->eeprom) { + dev_err(dev, "failed to populate crypto device\n"); + ret = -ENODEV; + goto out_remove_eeprom; + } + + sec->hash = i2c_new_device(ls->i2c0, &secure96_hash); + if (!sec->eeprom) { + dev_err(dev, "failed to populate hash device\n"); + ret = -ENODEV; + goto out_remove_crypto; + } + + /* Populate the SPI TPM device */ + gpiod = ls_get_gpiod(ls, LS_GPIO_D, + "tpm-slb9670-rst", + GPIOD_OUT_LOW); + if (IS_ERR(gpiod)) { + dev_err(dev, "failed to get TPM RESET\n"); + ret = -ENODEV; + goto out_remove_hash; + } + udelay(80); + /* Deassert RST */ + gpiod_set_value(gpiod, 1); + sec->tpm_reset = gpiod; + + gpiod = ls_get_gpiod(ls, LS_GPIO_C, + "tpm-slb9670-irq", + GPIOD_IN); + if (IS_ERR(gpiod)) { + dev_err(dev, "failed to get TPM IRQ GPIO\n"); + ret = -ENODEV; + goto out_remove_tpm_reset; + } + sec->tpm_irq = gpiod; + secure96_tpm.irq = gpiod_to_irq(gpiod); + sec->tpm = spi_new_device(ls->spi, &secure96_tpm); + if (!sec->tpm) { + dev_err(dev, "failed to populate TPM device\n"); + ret = -ENODEV; + goto out_remove_tpm_irq; + } + + dev_set_drvdata(&ls->dev, sec); + + return 0; + +out_remove_tpm_irq: + ls_put_gpiod(ls, sec->tpm_irq); +out_remove_tpm_reset: + ls_put_gpiod(ls, sec->tpm_reset); +out_remove_hash: + i2c_unregister_device(sec->hash); +out_remove_crypto: + i2c_unregister_device(sec->crypto); +out_remove_eeprom: + i2c_unregister_device(sec->eeprom); + if (secure96_eeprom_pdata.wp_gpiod) + ls_put_gpiod(ls, secure96_eeprom_pdata.wp_gpiod); +out_unreg_leds: + platform_device_unregister(sec->leds_device); + for (i = 0; i < ARRAY_SIZE(ledinfos); i++) + ls_put_gpiod(ls, sec->secure96_leds[i].gpiod); + return ret; +} + +static void secure96_remove(struct ls_device *ls) +{ + struct secure96 *sec = dev_get_drvdata(&ls->dev); + int i; + + spi_unregister_device(sec->tpm); + ls_put_gpiod(sec->ls, sec->tpm_irq); + ls_put_gpiod(sec->ls, sec->tpm_reset); + i2c_unregister_device(sec->hash); + i2c_unregister_device(sec->crypto); + i2c_unregister_device(sec->eeprom); + if (secure96_eeprom_pdata.wp_gpiod) + ls_put_gpiod(sec->ls, secure96_eeprom_pdata.wp_gpiod); + platform_device_unregister(sec->leds_device); + for (i = 0; i < ARRAY_SIZE(ledinfos); i++) + ls_put_gpiod(sec->ls, sec->secure96_leds[i].gpiod); + dev_set_drvdata(&ls->dev, NULL); +} + +static const struct of_device_id secure96_of_match[] = { + { + .compatible = "96boards,secure96", + }, + {}, +}; + +struct ls_driver secure96_driver = { + .drv = { + .owner = THIS_MODULE, + .name = "secure96", + .of_match_table = of_match_ptr(secure96_of_match), + }, + .probe = secure96_probe, + .remove = secure96_remove, +}; +module_driver(secure96_driver, ls_driver_register, ls_driver_unregister); diff --git a/drivers/bus/daughterboards/Kconfig b/drivers/bus/daughterboards/Kconfig new file mode 100644 index 000000000000..9855346c8b4d --- /dev/null +++ b/drivers/bus/daughterboards/Kconfig @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Non-discoverable daughterboards + +menuconfig DAUGHTERBOARDS + bool "Non-discoverable daughterboards" + help + These bus drivers deal with non-discoverable daughterboards, + which means daughterboards (plug-in complex logic circuit + boards) that can not reliably be discovered by software. + The physical connector is defined for the host hardware, + but we need to indicate what is on it at runtime using + sysfs. + +if DAUGHTERBOARDS + +menuconfig 96BOARDS_MEZZANINES + bool "96boards mezzanine boards" + +if 96BOARDS_MEZZANINES + +config 96BOARDS_LS_CONNECTOR + bool "96boards low speed connector driver" + depends on OF + depends on I2C + depends on SPI_MASTER + depends on GPIOLIB + help + Driver for the 96boards low speed connector + +config 96BOARDS_SECURE96 + bool "96boards Secure96 board driver" + depends on 96BOARDS_LS_CONNECTOR + select NEW_LEDS + select LEDS_CLASS + select LEDS_GPIO + select EEPROM_AT24 + select CRYPTO_HW + select CRYPTO_DEV_ATMEL_ECC + select HW_RANDOM + select TCG_TPM + select HW_RANDOM_TPM + select TCG_TIS + select TCG_TIS_SPI + help + Driver for the 96boards Secure96 mezzanine + +endif # 96BOARDS_MEZZANINES + +endif # DAUGHTERBOARDS diff --git a/drivers/bus/daughterboards/Makefile b/drivers/bus/daughterboards/Makefile new file mode 100644 index 000000000000..c9691b470fc5 --- /dev/null +++ b/drivers/bus/daughterboards/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for non-discoverable daughterboards +# +obj-$(CONFIG_96BOARDS_LS_CONNECTOR) += 96boards-ls-bus.o 96boards-ls-connector.o +obj-$(CONFIG_96BOARDS_SECURE96) += 96boards-secure96.o