From patchwork Wed Aug 8 15:27:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Marek_Beh=C3=BAn?= X-Patchwork-Id: 10560189 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BA37E157B for ; Wed, 8 Aug 2018 15:28:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A7C622B0D7 for ; Wed, 8 Aug 2018 15:28:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9B6A72B0E1; Wed, 8 Aug 2018 15:28:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3EDCB2B0D7 for ; Wed, 8 Aug 2018 15:28:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=/dSqpg5NVA07GL49ZDWxPQiskNZLScSn8QY3Bz8/x+I=; b=Aghrz1p3ucRSBakf9f7c9rasiy G9Jsa9GvMNiE3wXJQ1EIcFgjh1cjxNEsq/2YuDdOgRUlKyRK26A4SU197dqB9n1e+NOrMl1Sm55Pz EyNLeSKh1wzH+ay+P8bVU/kXnXG/XUBSiQAT9qAD1oBBRc/kDdYURWpb2qkLQ5OzZjZk68nB2gvpo xRZaUa0Ag2jREZdRM1GBLUOT+tk9fhw4YoA2AXSekKRFGg0u2gOA57u/yAwDACGNS3ZvlKKI+VMFF u+Qri7cP0GwAQvR5p/VSCJqJkuK3afMGjWUl9p6oooMiBlDNiijeLol3dXmipMF1mKd+zUsBDzyxP eSQftlHw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fnQO2-0001Ei-6K; Wed, 08 Aug 2018 15:28:34 +0000 Received: from mail.nic.cz ([2001:1488:800:400::400]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fnQNR-0000T6-GW for linux-arm-kernel@lists.infradead.org; Wed, 08 Aug 2018 15:28:01 +0000 Received: from dellmb.labs.office.nic.cz (unknown [IPv6:2001:1488:fffe:6:cac7:3539:7f1f:463]) by mail.nic.cz (Postfix) with ESMTP id 92BCD605EC; Wed, 8 Aug 2018 17:27:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=nic.cz; s=default; t=1533742062; bh=PfqxOe/B5lx1k45PiZUlxEjdwy9tdas3sqKytwamp7Q=; h=From:To:Date; b=Ayf6z1s9UDjqg4Yz6UiCfrcS7dzyjaSpY15UuPucs0zR/pjp3cFS0etsQOZX8QW+5 2j4K3kUMMIwJn3qOu5mWXmU42VyiEdpidwMuV+AD6q1dw6XmTorcLgU/PkR6dZk7fd 9Q8hYEGncohRGGW5zXrOlD3/2pQsCJ39nWfqmeBE= From: =?utf-8?q?Marek_Beh=C3=BAn?= To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v1 3/7] drivers: gpio: Add support for Turris Mox SFP GPIOs Date: Wed, 8 Aug 2018 17:27:02 +0200 Message-Id: <20180808152706.21727-4-marek.behun@nic.cz> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20180808152706.21727-1-marek.behun@nic.cz> References: <20180808152706.21727-1-marek.behun@nic.cz> X-Virus-Scanned: clamav-milter 0.99.2 at mail X-Virus-Status: Clean X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180808_082757_886607_901BB7A0 X-CRM114-Status: GOOD ( 15.03 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Gregory CLEMENT , Tomas Hlavacek , =?utf-8?q?Marek_Beh=C3=BAn?= MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The SFP cage GPIOs on the SFP cage module of Turris Mox can be configured via the moxtet bus. This driver supports those GPIOs so that they can be used by phylink. Signed-off-by: Marek Behun create mode 100644 Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt create mode 100644 drivers/gpio/gpio-moxtet-sfp.c diff --git a/Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt b/Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt new file mode 100644 index 000000000000..a8267aef7d2c --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-moxtet-sfp.txt @@ -0,0 +1,16 @@ +GPIO configuration of the SFP cage found on Turris Mox (over Moxtet bus) + +Required properties: + - compatible : Should be "cznic,moxtet-sfp". + - gpio-controller : Marks the device node as a GPIO controller. + - #gpio-cells : Should be two. For consumer use see gpio.txt. + +Example: + + moxtet_sfp: moxtet-sfp@0 { + compatible = "cznic,moxtet-sfp"; + gpio-controller; + #gpio-cells; + reg = <0>; + moxtet,id = <1>; + } diff --git a/MAINTAINERS b/MAINTAINERS index 27ca12e8309a..cfac1b21596c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1383,6 +1383,7 @@ M: Marek Behun W: http://mox.turris.cz S: Maintained F: include/mfd/moxtet.h +F: drivers/gpio/gpio-moxtet-sfp.c F: drivers/mfd/moxtet.c ARM/EBSA110 MACHINE SUPPORT diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 71c0ab46f216..bd6e52de99c5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1048,6 +1048,15 @@ config GPIO_MAX77620 driver also provides interrupt support for each of the gpios. Say yes here to enable the max77620 to be used as gpio controller. +config GPIO_MOXTET_SFP + tristate "Turris Mox SFP GPIO expander" + depends on MFD_MOXTET + help + Say yes here if you are building for the Turris Mox router. + This is the driver needed for configuring the GPIOs found on the + module with SFP cage of the Turris Mox router. + This driver uses the Moxtet bus. + config GPIO_MSIC bool "Intel MSIC mixed signal gpio support" depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 1324c8f966a7..ba464186c468 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -84,7 +84,8 @@ obj-$(CONFIG_GPIO_MC33880) += gpio-mc33880.o obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o obj-$(CONFIG_GPIO_ML_IOH) += gpio-ml-ioh.o obj-$(CONFIG_GPIO_MM_LANTIQ) += gpio-mm-lantiq.o -obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o +obj-$(CONFIG_GPIO_MOCKUP) += gpio-mockup.o +obj-$(CONFIG_GPIO_MOXTET_SFP) += gpio-moxtet-sfp.o obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o @@ -100,7 +101,7 @@ obj-$(CONFIG_GPIO_PCI_IDIO_16) += gpio-pci-idio-16.o obj-$(CONFIG_GPIO_PCIE_IDIO_24) += gpio-pcie-idio-24.o obj-$(CONFIG_GPIO_PISOSR) += gpio-pisosr.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o -obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio-pmic-eic-sprd.o +obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)+= gpio-pmic-eic-sprd.o obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o diff --git a/drivers/gpio/gpio-moxtet-sfp.c b/drivers/gpio/gpio-moxtet-sfp.c new file mode 100644 index 000000000000..87ba73bf55c5 --- /dev/null +++ b/drivers/gpio/gpio-moxtet-sfp.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Turris Mox SFP - GPIOs on the SFP cage found on Turris Mox SFP module + * + * Copyright (C) 2018 Marek Behun + */ + +#include +#include +#include +#include +#include + +#define MOXTET_SFP_IN_GPIOS 3 + +struct moxtet_sfp_chip { + struct device *dev; + struct gpio_chip gpio_chip; + struct gpio_desc *gpiod_oe; + u8 state; +}; + +static int moxtet_sfp_get_value(struct gpio_chip *gc, unsigned int offset) +{ + struct moxtet_sfp_chip *chip = gpiochip_get_data(gc); + int ret; + + if (offset < MOXTET_SFP_IN_GPIOS) { + ret = moxtet_device_read(chip->dev); + } else { + offset -= MOXTET_SFP_IN_GPIOS; + ret = moxtet_device_written(chip->dev); + } + + if (ret < 0) + return ret; + + return (ret >> offset) & 1; +} + +static void moxtet_sfp_set_value(struct gpio_chip *gc, unsigned int offset, + int val) +{ + struct moxtet_sfp_chip *chip = gpiochip_get_data(gc); + int ret; + + if (offset < MOXTET_SFP_IN_GPIOS) + return; + + offset -= MOXTET_SFP_IN_GPIOS; + + ret = moxtet_device_written(chip->dev); + if (ret < 0) + return; + + if (val) + ret |= (1 << offset); + else + ret &= ~(1 << offset); + + moxtet_device_write(chip->dev, ret); +} + +static int moxtet_sfp_get_direction(struct gpio_chip *gc, unsigned int offset) +{ + return offset < MOXTET_SFP_IN_GPIOS; +} + +static int moxtet_sfp_direction_input(struct gpio_chip *gc, unsigned int offset) +{ + if (offset >= MOXTET_SFP_IN_GPIOS) + return -EINVAL; + return 0; +} + +static int moxtet_sfp_direction_output(struct gpio_chip *gc, + unsigned int offset, int val) +{ + if (offset < MOXTET_SFP_IN_GPIOS) + return -EINVAL; + + moxtet_sfp_set_value(gc, offset, val); + return 0; +} + +static int moxtet_sfp_probe(struct device *dev) +{ + struct moxtet_sfp_chip *chip; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = dev; + chip->gpio_chip.parent = dev; + + dev_set_drvdata(dev, chip); + + chip->gpiod_oe = devm_gpiod_get_optional(dev, "enable", + GPIOD_OUT_LOW); + if (IS_ERR(chip->gpiod_oe)) + return PTR_ERR(chip->gpiod_oe); + + gpiod_set_value_cansleep(chip->gpiod_oe, 1); + + chip->gpio_chip.label = dev_name(dev); + chip->gpio_chip.get_direction = moxtet_sfp_get_direction; + chip->gpio_chip.direction_input = moxtet_sfp_direction_input; + chip->gpio_chip.direction_output = moxtet_sfp_direction_output; + chip->gpio_chip.get = moxtet_sfp_get_value; + chip->gpio_chip.set = moxtet_sfp_set_value; + chip->gpio_chip.base = -1; + + chip->gpio_chip.ngpio = 5; + + chip->gpio_chip.can_sleep = true; + chip->gpio_chip.owner = THIS_MODULE; + + return gpiochip_add_data(&chip->gpio_chip, chip); +} + +static int moxtet_sfp_remove(struct device *dev) +{ + struct moxtet_sfp_chip *chip = dev_get_drvdata(dev); + + gpiod_set_value_cansleep(chip->gpiod_oe, 0); + gpiochip_remove(&chip->gpio_chip); + + return 0; +} + +static const struct of_device_id moxtet_sfp_dt_ids[] = { + { .compatible = "cznic,moxtet-sfp" }, + {}, +}; +MODULE_DEVICE_TABLE(of, moxtet_sfp_dt_ids); + +static const enum turris_mox_module_id moxtet_sfp_id_table[] = { + TURRIS_MOX_MODULE_SFP, + 0 +}; + +static struct moxtet_driver moxtet_sfp_driver = { + .driver = { + .name = "moxtet-sfp", + .of_match_table = moxtet_sfp_dt_ids, + .probe = moxtet_sfp_probe, + .remove = moxtet_sfp_remove, + }, + .id_table = moxtet_sfp_id_table, +}; +module_moxtet_driver(moxtet_sfp_driver); + +MODULE_AUTHOR("Marek Behun "); +MODULE_DESCRIPTION("GPIO configuration of the SFP cage found on Turris Mox"); +MODULE_LICENSE("GPL v2");