From patchwork Thu May 6 16:25:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis K X-Patchwork-Id: 1475161 X-Patchwork-Delegate: koen.vandeputte@ncentric.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; helo=desiato.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=dKHSFal+; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=jJ1PMJvo; dkim-atps=neutral Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbfCR61N3z9sCD for ; Fri, 7 May 2021 02:28:35 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=E/382pOoML8tkHhbke93S8WolnXg9QR0C7V7TPTT5hE=; b=dKHSFal+RE1/rHZhdbSJQrUFM FK1R/Wdkyj9mvlZyccO+/SGQjTeBM5KhAF4BYa5VYVwwHXKq8POK8xYmfxdd6XAHbCaff1Zw9uJdx RlfIVn6uDMffzJ+SZXb280c38ucVa/BL8UTJUhAyJMsDmHLcgFhracSEwomqUyq8LyivwrzhecxB7 Bvd/VmGEuzpQGmRl9Feph6BvGUVmxLJzdNRKyIXDVlKMjd4V6ucYsQG2hOR5g2FOYLiKlHWVbESbI VD/GBSysPILoTrf43Dz6qCaEyRH6zNvxbIUH92b3tyeWDeh0Ly0XLFyA/AAxiTr9S6dXl6ZHBruw0 E83tMLSpQ==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1legq8-004nn8-6J; Thu, 06 May 2021 16:27:04 +0000 Received: from mail-lj1-x22d.google.com ([2a00:1450:4864:20::22d]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1legpu-004ngI-Pr for openwrt-devel@lists.openwrt.org; Thu, 06 May 2021 16:26:53 +0000 Received: by mail-lj1-x22d.google.com with SMTP id a36so7813214ljq.8 for ; Thu, 06 May 2021 09:26:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3OdH7FSzdyYABhZVLIpUjfe7Uj2MtsBt8LfBRi5sU+M=; b=jJ1PMJvoiKtgIW+kgS+e6WM3Rk2ipIc4+LbYH6TYiLe9ofEByCqxmH5cDqcFWftoRc JM36+eGYiy/QlIEIvSmYWd1lue/xE1XUww1FsWXV6ljQ7ezuRQsvfQloTTBMziwErafz vsErhmhCrJR0l/ftJiRLRRLQgBxw++LxS8OdhgL1PCN/Wtxjmy+xB4+i5K2Yyv0mVgjz vZsV/2hU7OTKb3LPNgSRbWWuj49nzKWdrEgnOjbOWhjHtXUfgjSyyDwaftOCefijfZWD dFDlhBCcZGDQW6QwXjYizCChMVT8qhm3pHW5hG6eBzxE3jznLR/Uj9MG+VkwbFvGKLrR GMkg== 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:mime-version:content-transfer-encoding; bh=3OdH7FSzdyYABhZVLIpUjfe7Uj2MtsBt8LfBRi5sU+M=; b=nI/p8gvbMDWPHQd3vAfQNM90v6vfRCkjhoOR9hgZiRXzXLEWt44iRl9FvpiP0y8IhG Rg9RHc3lj26JsSFjHdDWFuHaLP3j6uHX+xoHzApMGjsuCbVo7Z+nXtKiv057Kq+pzOsv L2XV+WuS9Hcks1zf2zLcZg6Hs0z7RtMg3KTRgiHQEMxrhh8AxncQreAQKNyEQpF7idLT kNKorUxhANmb3agmY8jefZuaHNG21QkFJ08AHJ42FLef4qDclYCqASdZuxX9oKmiZa2i ZnOCDGZ6nqI0BFWW6fOrIVGLT3IqzJtELrjK6pD6TRDUqhWXMjAjG6v/c4SXMagit0ai CTAA== X-Gm-Message-State: AOAM532bRu/F0xzDterJ3nubrhfP9YdT748P7eZnkZrWFtL5ZViyofe4 xNJQ/37GQWAddvMt3NcKv057UxHIyb4= X-Google-Smtp-Source: ABdhPJxhRI7w6a9EzIrnXe0K09CuM4iSPhYdg7VGTFYIavj0Y6XdxAGK/iAEgNesn2oAPT8AHE0oFw== X-Received: by 2002:a2e:934c:: with SMTP id m12mr4401697ljh.295.1620318407721; Thu, 06 May 2021 09:26:47 -0700 (PDT) Received: from kalashnikov.user.kdf.lan ([89.18.140.18]) by smtp.gmail.com with ESMTPSA id i1sm787164lfe.53.2021.05.06.09.26.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 May 2021 09:26:47 -0700 (PDT) From: Denis Kalashnikov To: openwrt-devel@lists.openwrt.org Cc: Gabor Juhos Subject: [PATCH 1/4] ath79: add MFD driver (NAND and GPIO) for Mikrotik RB91xG Date: Thu, 6 May 2021 19:25:11 +0300 Message-Id: <20210506162514.5913-2-denis281089@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210506162514.5913-1-denis281089@gmail.com> References: <20210506162514.5913-1-denis281089@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210506_172651_048678_75C6B024 X-CRM114-Status: GOOD ( 30.25 ) X-Spam-Score: 0.1 (/) X-Spam-Report: Spam detection software, running on the system "desiato.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: rb91x-ngl (nand-gpio-latch) requests and controls SoC GPIO lines that are used for NAND control and data lines multiplexed with a latch. Lines of the latch that are not used for NAND control lines, ar [...] Content analysis details: (0.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:22d listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit [denis281089[at]gmail.com] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [denis281089[at]gmail.com] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org rb91x-ngl (nand-gpio-latch) requests and controls SoC GPIO lines that are used for NAND control and data lines multiplexed with a latch. Lines of the latch that are not used for NAND control lines, are used for power LED and user LED and a Shift Register nCS. Like rb4xx-cpld driver rb91x-ngl provides API for separate NAND driver and latch-GPIO driver. This driver is used in place of the ar71xx gpio-latch driver. Signed-off-by: Denis Kalashnikov --- .../linux/ath79/files/drivers/mfd/rb91x-ngl.c | 331 ++++++++++++++++++ .../linux/ath79/files/include/mfd/rb91x-ngl.h | 59 ++++ target/linux/ath79/mikrotik/config-default | 1 + .../patches-5.4/939-mikrotik-rb91x.patch | 21 ++ 4 files changed, 412 insertions(+) create mode 100644 target/linux/ath79/files/drivers/mfd/rb91x-ngl.c create mode 100644 target/linux/ath79/files/include/mfd/rb91x-ngl.h create mode 100644 target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch diff --git a/target/linux/ath79/files/drivers/mfd/rb91x-ngl.c b/target/linux/ath79/files/drivers/mfd/rb91x-ngl.c new file mode 100644 index 0000000000..c6ab4631f5 --- /dev/null +++ b/target/linux/ath79/files/drivers/mfd/rb91x-ngl.c @@ -0,0 +1,331 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MFD driver for the MikroTik RouterBoard NAND controlled through GPIO + * multiplexed with latch. Why MFD, not pure NAND driver? Since the latch + * lines, that are not used for NAND control lines, are used for GPIO + * output function -- for leds and other. + * + * Copyright (C) 2021 Denis Kalashnikov + * + */ +#include +#include +#include +#include +#include + +#include + +#define DRIVER_NAME "rb91x-nand-gpio-latch" + +#define NAND_DATAS 8 +#define LATCH_GPIOS 3 + +static int nand_datas_count(struct rb91x_ngl *ngl) +{ + return NAND_DATAS; +} + +static int latch_gpios_count(struct rb91x_ngl *ngl) +{ + return LATCH_GPIOS; +} + +static void latch_lock(struct rb91x_ngl *ngl) +{ + mutex_lock(&ngl->mutex); + + gpio_set_value_cansleep(ngl->gpio[RB91X_NGL_NLE], 0); +} + +static void latch_unlock(struct rb91x_ngl *ngl) +{ + gpio_set_value_cansleep(ngl->gpio[RB91X_NGL_NLE], 1); + + mutex_unlock(&ngl->mutex); +} + +#define OFFSET_INVAL(offset) ((offset) < 0 || (offset) >= RB91X_NGL_GPIOS) + +static void rb91x_ngl_gpio_set_value(struct rb91x_ngl *ngl, int offset, int val) +{ + if (OFFSET_INVAL(offset)) + return; + + gpio_set_value_cansleep(ngl->gpio[offset], val); +} + +static void latch_gpio_set_value(struct rb91x_ngl *ngl, int offset, int val) +{ + if (offset >= LATCH_GPIOS) + return; + + mutex_lock(&ngl->mutex); + + gpio_set_value_cansleep(ngl->gpio[RB91X_NGL_LATCH_GPIO0 + offset], val); + + mutex_unlock(&ngl->mutex); +} + +static int rb91x_ngl_gpio_get_value(struct rb91x_ngl *ngl, int offset) +{ + if (OFFSET_INVAL(offset)) + return -EINVAL; + + return gpio_get_value(ngl->gpio[offset]); +} + +static void rb91x_ngl_gpio_direction_output(struct rb91x_ngl *ngl, int offset, + int val) +{ + if (OFFSET_INVAL(offset)) + return; + + gpio_direction_output(ngl->gpio[offset], val); +} + +static void rb91x_ngl_gpio_direction_input(struct rb91x_ngl *ngl, int offset) +{ + if (OFFSET_INVAL(offset)) + return; + + gpio_direction_input(ngl->gpio[offset]); +} + +static const struct mfd_cell mfd_cells[] = { + { + .name = "mikrotik,rb91x-nand", + .of_compatible = "mikrotik,rb91x-nand", + }, { + .name = "mikrotik,rb91x-gpio-latch", + .of_compatible = "mikrotik,rb91x-gpio-latch", + }, +}; + +static int get_gpios(struct device *dev, const char *prop_name) +{ + int n; + + n = of_get_named_gpio(dev->of_node, prop_name, 0); + if (n < 0) + dev_err(dev, "Could not read required '%s' property: %d\n", prop_name, n); + //pr_info(DRIVER_NAME ": %s = %d\n", prop_name, n); + + return n; +} + +/* + * NOTE: all gpios are labeled with driver name, not with @name. + * @name is used only in error message. Since we failed to choose + * a good names for multiplexed gpios. + */ +static int req_gpio(struct device *dev, int gpio, const char *name) +{ + int ret; + + ret = devm_gpio_request(dev, gpio, DRIVER_NAME); + if (ret) { + pr_err(DRIVER_NAME ": failed to request gpio %d ('%s'): %d\n", + gpio, name, ret); + return ret; + } + + //pr_info(DRIVER_NAME ": request gpio %d ('%s')\n", gpio, name); + + return ret; +} + +static int probe(struct platform_device *pdev) +{ + struct device_node *of_node = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct rb91x_ngl *ngl; + int i, n, ret; + + pr_info("rb91x-nand-gpio-latch driver probe\n"); + + ngl = devm_kzalloc(dev, sizeof(*ngl), GFP_KERNEL); + if (!ngl) + return -ENOMEM; + + /* TODO: read gpios flags (active high/low) */ + + for (i = 0; i < RB91X_NGL_GPIOS; i++) { + ngl->gpio[i] = -ENOENT; + } + + /* Read NAND control gpios */ + ngl->gpio[RB91X_NGL_NAND_NCE] = get_gpios(dev, "nand-nce-gpios"); + ngl->gpio[RB91X_NGL_NAND_CLE] = get_gpios(dev, "nand-cle-gpios"); + ngl->gpio[RB91X_NGL_NAND_ALE] = get_gpios(dev, "nand-ale-gpios"); + ngl->gpio[RB91X_NGL_NAND_NRW] = get_gpios(dev, "nand-nrw-gpios"); + ngl->gpio[RB91X_NGL_NAND_RDY] = get_gpios(dev, "nand-rdy-gpios"); + ngl->gpio[RB91X_NGL_NAND_READ] = get_gpios(dev, "nand-read-gpios"); + + ngl->gpio[RB91X_NGL_NLE] = get_gpios(dev, "nle-gpios"); + + /* Read NAND data gpios */ + + n = of_gpio_named_count(of_node, "nand-data-gpios"); + if (n != NAND_DATAS) { + dev_err(dev, DRIVER_NAME + ": required 'nand-data-gpios' property must have %d gpios\n", + NAND_DATAS); + return -EINVAL; + } + + //dev_info(dev, DRIVER_NAME ": nand-data-gpios count = %d\n", n); + + for (i = 0; i < n; i++) { + ret = of_get_named_gpio(of_node, "nand-data-gpios", i); + if (ret < 0) { + dev_err(dev, DRIVER_NAME + ": Couldn't read required 'nand-data-gpios': %d\n", + ret); + return -EINVAL; + } + + //dev_info(dev, DRIVER_NAME ": nand-data-gpios = %d\n", ret); + + ngl->gpio[RB91X_NGL_NAND_DATA0 + i] = ret; + } + + /* Read latch gpios */ + + n = of_gpio_named_count(of_node, "latch-gpios"); + if (n != LATCH_GPIOS) { + dev_err(dev, DRIVER_NAME + ": required 'latch-gpios' property must have %d gpios\n", + LATCH_GPIOS); + return -EINVAL; + } + + //dev_info(dev, DRIVER_NAME ": latch-gpios count = %d\n", n); + + for (i = 0; i < n; i++) { + ret = of_get_named_gpio(of_node, "latch-gpios", i); + if (ret < 0) { + dev_err(dev, DRIVER_NAME + ": Couldn't read required 'latch-gpios': %d\n", + ret); + return -EINVAL; + } + + //dev_info(dev, DRIVER_NAME ": latch-gpios = %d\n", ret); + + ngl->gpio[RB91X_NGL_LATCH_GPIO0 + i] = ret; + } + + if (ngl->gpio[RB91X_NGL_NAND_NCE] < 0 + || ngl->gpio[RB91X_NGL_NAND_CLE] < 0 + || ngl->gpio[RB91X_NGL_NAND_ALE] < 0 + || ngl->gpio[RB91X_NGL_NAND_NRW] < 0 + || ngl->gpio[RB91X_NGL_NAND_RDY] < 0 + || ngl->gpio[RB91X_NGL_NAND_READ] < 0 + || ngl->gpio[RB91X_NGL_NLE] < 0) + return -EINVAL; + + /* Request gpios */ + + if (req_gpio(dev, ngl->gpio[RB91X_NGL_NLE], "nLE")) + return -EINVAL; + + if (req_gpio(dev, ngl->gpio[RB91X_NGL_NAND_NCE], "NAND-nCE")) + return -EINVAL; + + if (req_gpio(dev, ngl->gpio[RB91X_NGL_NAND_CLE], "NAND-CLE")) + return -EINVAL; + + if (req_gpio(dev, ngl->gpio[RB91X_NGL_NAND_ALE], "NAND-ALE")) + return -EINVAL; + + if (req_gpio(dev, ngl->gpio[RB91X_NGL_NAND_NRW], "NAND-nRW")) + return -EINVAL; + + if (req_gpio(dev, ngl->gpio[RB91X_NGL_NAND_RDY], "NAND-RDY")) + return -EINVAL; + + if (req_gpio(dev, ngl->gpio[RB91X_NGL_NAND_READ], "NAND-READ")) + return -EINVAL; + + for (i = 0; i < NAND_DATAS; i++) { + /* + * Some data gpios are equal to control gpios. + * Check this. + */ + n = ngl->gpio[RB91X_NGL_NAND_DATA0 + i]; + if (n == ngl->gpio[RB91X_NGL_NAND_NCE] + || n == ngl->gpio[RB91X_NGL_NAND_CLE] + || n == ngl->gpio[RB91X_NGL_NAND_ALE] + || n == ngl->gpio[RB91X_NGL_NAND_NRW] + || n == ngl->gpio[RB91X_NGL_NAND_RDY] + || n == ngl->gpio[RB91X_NGL_NAND_READ]) + continue; + if (req_gpio(dev, n, "NAND-DATAx")) + return -EINVAL; + } + + /* + * NOTE: We suppose that latch gpios are equal to some + * control gpios, so they have been already requested. + */ + + ngl->nand_datas_count = nand_datas_count; + ngl->latch_lock = latch_lock; + ngl->latch_unlock = latch_unlock; + ngl->gpio_set_value = rb91x_ngl_gpio_set_value; + ngl->gpio_get_value = rb91x_ngl_gpio_get_value; + ngl->gpio_direction_input = rb91x_ngl_gpio_direction_input; + ngl->gpio_direction_output = rb91x_ngl_gpio_direction_output; + ngl->latch_gpio_set_value = latch_gpio_set_value; + ngl->latch_gpios_count = latch_gpios_count; + + mutex_init(&ngl->mutex); + + dev_set_drvdata(dev, ngl); + + /* + * All gpios and the latch are controlled by NAND driver, + * but we need to init gpio lines for the latch gpio in case + * of NAND driver is missing. + */ + + /* Unlock the latch */ + gpio_direction_output(ngl->gpio[RB91X_NGL_NLE], 1); + + /* TODO: are latch gpio lines active high or low? */ + for (i = 0; i < LATCH_GPIOS; i++) { + gpio_direction_output(ngl->gpio[RB91X_NGL_LATCH_GPIO0 + i], 0); + } + + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, + mfd_cells, ARRAY_SIZE(mfd_cells), + NULL, 0, NULL); +} + +static int remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id match[] = { + { .compatible = "mikrotik,nand-gpio-latch", }, + { }, +}; +MODULE_DEVICE_TABLE(of, match); + +static struct platform_driver rb91x_ngl_driver = { + .probe = probe, + .remove = remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(match), + }, +}; + +module_platform_driver(rb91x_ngl_driver); + +MODULE_DESCRIPTION("Driver for Mikrotik RouterBoard 91x NAND controlled through GPIOs multiplexed with latch"); +MODULE_AUTHOR("Denis Kalashnikov "); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ath79/files/include/mfd/rb91x-ngl.h b/target/linux/ath79/files/include/mfd/rb91x-ngl.h new file mode 100644 index 0000000000..5360aa7548 --- /dev/null +++ b/target/linux/ath79/files/include/mfd/rb91x-ngl.h @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * MFD driver for the MikroTik RouterBoard 91xG NAND controlled + * through GPIOs multiplexed with latch (rb91x-nand-gpio-latch). + * + * Copyright (C) 2021 Denis Kalashnikov + */ + +#include + +enum rb91x_ngl_gpios { + /* NAND control gpios */ + RB91X_NGL_NAND_NCE, /* nCE -- Chip Enable, Active Low */ + RB91X_NGL_NAND_CLE, /* CLE -- Command Latch Enable */ + RB91X_NGL_NAND_ALE, /* ALE -- Address Latch Enable */ + RB91X_NGL_NAND_NRW, /* nRW -- Read/Write Enable, Active Low */ + RB91X_NGL_NAND_RDY, /* RDY -- NAND Ready */ + RB91X_NGL_NAND_READ, /* READ */ + + RB91X_NGL_NLE, /* nLE -- Latch Enable, Active Low */ + + /* NAND data gpios */ + RB91X_NGL_NAND_DATA0, + + /* Latch gpios */ + RB91X_NGL_LATCH_GPIO0 = RB91X_NGL_NAND_DATA0 + 32, + + RB91X_NGL_GPIOS = RB91X_NGL_LATCH_GPIO0 + 32, /* Total number of gpios */ +}; + +struct rb91x_ngl { + /* Public */ + + /* API for RB91x NAND controller driver */ + void (*gpio_set_value)(struct rb91x_ngl *ngl, int offset, int val); + void (*gpio_direction_input)(struct rb91x_ngl *ngl, int offset); + void (*gpio_direction_output)(struct rb91x_ngl *ngl, int offset, + int val); + int (*gpio_get_value)(struct rb91x_ngl *ngl, int offset); + void (*latch_lock)(struct rb91x_ngl *ngl); + void (*latch_unlock)(struct rb91x_ngl *ngl); + int (*nand_datas_count)(struct rb91x_ngl *ngl); + + /* API for RB91x gpio latch controller driver */ + void (*latch_gpio_set_value)(struct rb91x_ngl *ngl, int offset, + int val); + int (*latch_gpios_count)(struct rb91x_ngl *ngl); + + + /* Private */ + + /* + * To synchronize access of NAND driver and GPIO driver + * to shared gpio lines. + */ + struct mutex mutex; + + int gpio[RB91X_NGL_GPIOS]; +}; diff --git a/target/linux/ath79/mikrotik/config-default b/target/linux/ath79/mikrotik/config-default index 1e637bdfd3..67c980a491 100644 --- a/target/linux/ath79/mikrotik/config-default +++ b/target/linux/ath79/mikrotik/config-default @@ -8,6 +8,7 @@ CONFIG_LEDS_RESET=y CONFIG_LZO_DECOMPRESS=y CONFIG_MDIO_GPIO=y CONFIG_MFD_RB4XX_CPLD=y +CONFIG_MFD_RB91X_NGL=y CONFIG_MIKROTIK=y CONFIG_MIKROTIK_RB_SYSFS=y CONFIG_MTD_NAND=y diff --git a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch new file mode 100644 index 0000000000..a85db0892c --- /dev/null +++ b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch @@ -0,0 +1,21 @@ +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -2020,5 +2020,10 @@ config MFD_RB4XX_CPLD + Enables support for the CPLD chip (NAND & GPIO) on Mikrotik + Routerboard RB4xx series. + ++config MFD_RB91X_NGL ++ tristate "Mikrotik RB91x NAND and GPIO driver ++ select MFD_CORE ++ depends on ATH79 || COMPILE_TEST ++ + endmenu + endif +--- a/drivers/mfd/Makefile ++++ b/drivers/mfd/Makefile +@@ -257,3 +257,5 @@ obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-b + obj-$(CONFIG_MFD_STMFX) += stmfx.o + + obj-$(CONFIG_MFD_RB4XX_CPLD) += rb4xx-cpld.o ++ ++obj-$(CONFIG_MFD_RB91X_NGL) += rb91x-ngl.o From patchwork Thu May 6 16:25:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis K X-Patchwork-Id: 1475162 X-Patchwork-Delegate: koen.vandeputte@ncentric.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; helo=desiato.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=XddP6ZOF; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=Z1sOlZNh; dkim-atps=neutral Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbfCZ6dGKz9sCD for ; Fri, 7 May 2021 02:28:42 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=8x3TqS36aKbdhvZt9y6+1ilC+OnbTmnnNU9ufqRQBqY=; b=XddP6ZOFpkSE7YAeql4e6cFj2 HCYhbiLvvDg1Td2s70bH6VOzuPTKvu2sxdIn5kG9P+1SN36+cBMekrwN39kCTlDAr2LDZq7lByljS u9AKK/8+3Wh9tg0unerQDNmZP+ZGC+7qz6nEMPxDDrnnyfa5Exa6P7ifqk+QqcJuBXlWVJtkizhoj MBc+T4tjmaCzIaafX4liGHtU6pRF/dg25vH99kEY0sEkXURLufoQ5R97JxAB4xT8bxtEXfguFnZpL W2xb+eQn+J3M4a8SuFG9vt4GocLm94yp/Fx26m1aJOXjcF52BrhXyeUMp6wGZhxsnGRBOCbUbPhwt 1BAdR4MEg==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1legqG-004np8-0B; Thu, 06 May 2021 16:27:12 +0000 Received: from mail-lf1-x12b.google.com ([2a00:1450:4864:20::12b]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1legpv-004ngj-MI for openwrt-devel@lists.openwrt.org; Thu, 06 May 2021 16:26:53 +0000 Received: by mail-lf1-x12b.google.com with SMTP id c3so8630100lfs.7 for ; Thu, 06 May 2021 09:26:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=L+ji14hhYmE0QlbKae1im69KswjiKvkDdq5uQJnGnfM=; b=Z1sOlZNhqNYEqdDQvIpa6vo7MeWqGOmIMb2HUqW6ugMjjCY3vjv3Gog/YadmzDRIWw v/9Ss1wI9KALkGTgNu13RNkjjkbhqOZqbAhvDNNpej3AsswxM1rvbUGZaR/jLCPbrVVq fSPHge5D+M6v6FnK3SHV8vp4N5Hivi5UZHt1Ll3q7opjiZr3zr5bq7N6h6tB9OtT4fOD wivwOwlIp1i1UyjIb3mhiOOMbUxWFYY/0Ti0BJBAKD9P97DwhF+UPXSeoOGOO7aZQ2dZ AgPsSb8MHXisc9fvxOVio4YfBWxwX3uf8CDjm8+0vP/UTVeclPre+d5QyExnFeKvGG46 JOFg== 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:mime-version:content-transfer-encoding; bh=L+ji14hhYmE0QlbKae1im69KswjiKvkDdq5uQJnGnfM=; b=o7est4JCEsE1DhLXVjQFFW1D2dhOMKfal5KKoNr5CixQyXvnO71VQiFGkhH20fTOcc BLsg2BdFJY5wGss4xKVApUtfKfgte1efJBRkhTrAxUvysf2jQvzjK+wpRElU8O4Oi+JV 6p8ER7ITbXfY61n4y6XmHf3K1/gHEbp72uaNjP90b069U/C6cY6XT9Pf6C2powVXXAS1 RXM0pAZLZy+ZutMfA6CsYHDeyxkgdpJlJHKuIcTXMEw3EYry48/6pX+/gDntzf0+RrmT WKpbCXTrsRCnx6OwWrd5JsMSFKdtmBEd7dcLLf9H5n4szCUiUe6bvEuI8aYCV/XkYP72 KSmw== X-Gm-Message-State: AOAM531fey1Xm+WSLYEHMJiqEsX/Q802F22F1n8TV6aAUw6tFFXD1fji 5E0AtxmpOqEcXYITr2ppEfT29y76Cy4= X-Google-Smtp-Source: ABdhPJw2HQ7EEX3JdcLP0Q6fFYtij0IvJoAxEt0xo/BcwjHV/Y1sqobu1DL4rEyOQgv5zJ2xWHxJRw== X-Received: by 2002:a05:6512:3619:: with SMTP id f25mr1582877lfs.399.1620318409030; Thu, 06 May 2021 09:26:49 -0700 (PDT) Received: from kalashnikov.user.kdf.lan ([89.18.140.18]) by smtp.gmail.com with ESMTPSA id i1sm787164lfe.53.2021.05.06.09.26.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 May 2021 09:26:48 -0700 (PDT) From: Denis Kalashnikov To: openwrt-devel@lists.openwrt.org Cc: Gabor Juhos Subject: [PATCH 2/4] ath79: add GPIO-latch driver for Mikrotik RB91xG Date: Thu, 6 May 2021 19:25:12 +0300 Message-Id: <20210506162514.5913-3-denis281089@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210506162514.5913-1-denis281089@gmail.com> References: <20210506162514.5913-1-denis281089@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210506_172652_017377_577B8636 X-CRM114-Status: GOOD ( 21.12 ) X-Spam-Score: 0.1 (/) X-Spam-Report: Spam detection software, running on the system "desiato.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: This driver exports GPIO lines on the latch that are not used for NAND control lines (but used for data lines). It doesn't request byself SoC gpio lines and set them through API provided by rb91x-ngl. [...] Content analysis details: (0.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:12b listed in] [list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit [denis281089[at]gmail.com] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [denis281089[at]gmail.com] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org This driver exports GPIO lines on the latch that are not used for NAND control lines (but used for data lines). It doesn't request byself SoC gpio lines and set them through API provided by rb91x-ngl. Exported lines are used for power LED, user LED and nCS of the Shift Register. Signed-off-by: Denis Kalashnikov --- .../files/drivers/gpio/gpio-latch-rb91x.c | 127 ++++++++++++++++++ target/linux/ath79/mikrotik/config-default | 1 + .../patches-5.4/939-mikrotik-rb91x.patch | 23 ++++ 3 files changed, 151 insertions(+) create mode 100644 target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c diff --git a/target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c b/target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c new file mode 100644 index 0000000000..f1ed8ebc96 --- /dev/null +++ b/target/linux/ath79/files/drivers/gpio/gpio-latch-rb91x.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver of GPIO controller on a 8-bit NAND latch (LVC573) on MikroTik RB91x. + * + * Copyright (C) 2021 Denis Kalashnikov + */ + +#include +#include +#include +#include +#include + +#include + +#define DRIVER_NAME "rb91x-gpio-latch" + +static int get(struct gpio_chip *gc, unsigned offset) +{ + return -ENOSYS; +} + +static void set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct rb91x_ngl *ngl = gpiochip_get_data(gc); + + ngl->latch_gpio_set_value(ngl, offset, value); +} + +static int direction_input(struct gpio_chip *gc, unsigned offset) +{ + return -ENOSYS; +} + +static int direction_output(struct gpio_chip *gc, unsigned offset, int value) +{ + struct rb91x_ngl *ngl = gpiochip_get_data(gc); + + ngl->latch_gpio_set_value(ngl, offset, value); + + return 0; +} + +static int probe(struct platform_device *pdev) +{ + struct gpio_chip *gc; + struct device_node *of_node = pdev->dev.of_node; + struct device *dev = &pdev->dev, *parent = pdev->dev.parent; + struct rb91x_ngl *ngl; + int ret; + u32 val; + + pr_info(DRIVER_NAME " driver probe\n"); + + if (!parent) + return -ENODEV; + + gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + /* + ret = of_property_read_u32(of_node, "base", &val); + if (ret < 0) { + dev_err(dev, "Could not read required 'base' property\n"); + return -EINVAL; + } + pr_info(DRIVER_NAME ": base = %d\n", val); + gc->base = val; + */ + gc->base = -1; /* Request dynamic allocation */ + + ngl = dev_get_drvdata(parent); + if (!ngl) { + pr_err(DRIVER_NAME " ngl is null\n"); + return -EINVAL; + } + + gc->label = DRIVER_NAME; + gc->parent = dev; + gc->can_sleep = true; + gc->ngpio = ngl->latch_gpios_count(ngl); + gc->get = get; + gc->set = set; + gc->direction_input = direction_input, + gc->direction_output = direction_output; + gc->of_node = of_node; + + platform_set_drvdata(pdev, gc); + + ret = gpiochip_add_data(gc, ngl); + if (ret) { + pr_err(DRIVER_NAME ": failed to add gpio chip: %d\n", ret); + return ret; + } + + return 0; +} + +static int remove(struct platform_device *pdev) +{ + gpiochip_remove(platform_get_drvdata(pdev)); + return 0; +} + +static const struct of_device_id match[] = { + { .compatible = "mikrotik," DRIVER_NAME }, + {}, +}; + +MODULE_DEVICE_TABLE(of, match); + +static struct platform_driver rb91x_gpio_latch_driver = { + .probe = probe, + .remove = remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = match, + }, +}; + +module_platform_driver(rb91x_gpio_latch_driver); + +MODULE_DESCRIPTION("Driver for GPIO on MikroTik RB91x NAND latch"); +MODULE_AUTHOR("Denis Kalashnikov "); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ath79/mikrotik/config-default b/target/linux/ath79/mikrotik/config-default index 67c980a491..92b7824eba 100644 --- a/target/linux/ath79/mikrotik/config-default +++ b/target/linux/ath79/mikrotik/config-default @@ -1,6 +1,7 @@ CONFIG_CRC16=y CONFIG_CRYPTO_DEFLATE=y CONFIG_GPIO_LATCH=y +CONFIG_GPIO_LATCH_RB91X=y CONFIG_GPIO_RB4XX=y CONFIG_GPIO_WATCHDOG=y CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y diff --git a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch index a85db0892c..f2135d486b 100644 --- a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch +++ b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch @@ -19,3 +19,26 @@ obj-$(CONFIG_MFD_RB4XX_CPLD) += rb4xx-cpld.o + +obj-$(CONFIG_MFD_RB91X_NGL) += rb91x-ngl.o +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -130,6 +130,10 @@ config GPIO_ATH79 + Select this option to enable GPIO driver for + Atheros AR71XX/AR724X/AR913X SoC devices. + ++config GPIO_LATCH_RB91X ++ tristate "Mikrotik RB91X GPIO latch driver" ++ depends on MFD_RB91X_NGL ++ + config GPIO_RASPBERRYPI_EXP + tristate "Raspberry Pi 3 GPIO Expander" + default RASPBERRYPI_FIRMWARE +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -67,6 +67,7 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o + obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o + obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o + obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o ++obj-$(CONFIG_GPIO_LATCH_RB91X) += gpio-latch-rb91x.o + obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o + obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o + obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o From patchwork Thu May 6 16:25:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis K X-Patchwork-Id: 1475163 X-Patchwork-Delegate: koen.vandeputte@ncentric.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; helo=desiato.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=MzHpxDA+; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=IEfxhR83; dkim-atps=neutral Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbfCf6Kqhz9sWk for ; Fri, 7 May 2021 02:28:46 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=Wa01fOZ/zbUAYRbJ2gKiC9zErXHKkFd7j4FouLQ977Q=; b=MzHpxDA+9meAucd9Epeo76H/c YPM4ZheYkhMD5n0fD9xCZZ/JwM9UFBZE15QIOk0y7R1vPZAj8N4KF09trpQThCb4HxvY+37uLHxfG SjgxSJSjlQEcXdqwwGzymy4tfjDkWKOMc2BpOUYGhtdq5dT3UwXjc2YFypt46PydYoF3XWSj1FuAY +F1L51dN4yBl4VF4SWAAm/T+xxLUvrVlOzHIupsMZ3mumdMyLf5pcUkFf9jALXP45R1RWLWx2evpS rL4ZTdccEU0pvUTH1CW9R8ml1U/aB5KfYnIMR0ZT3R6m/3O47Hi01mV1oe+l8oVp0Ki3YomDWCF7n BzRK35qeg==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1legqQ-004nsL-B2; Thu, 06 May 2021 16:27:22 +0000 Received: from mail-lf1-x136.google.com ([2a00:1450:4864:20::136]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1legpw-004ngo-2J for openwrt-devel@lists.openwrt.org; Thu, 06 May 2021 16:26:55 +0000 Received: by mail-lf1-x136.google.com with SMTP id x19so8662708lfa.2 for ; Thu, 06 May 2021 09:26:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=CbeVNuYlWEZFZ4ncx0FKGVgSfmasn7+dHUMJom8xrN8=; b=IEfxhR83/Z6mKi9h3bjTjqHCzgLfCXpEKrlf947nacNFSXrgPM7TMqBGAa2xzc7PmG gwYZ6zzLeGCah5ZNKmXdu/cGWfRF/sx7rvFOcDuL2wO9i69Ep2B7SYOcphVzJ9FJFx0x m44Ufwk/4L6GMhLSa0YnVveevnCpkpyavO/QO9dLjfXj0t0Ivr1rI8NRqSTWEPIo42nO S57WVFMHiF9s12YFgU7pecD9GNhhTYc2+4XwbFeKmiO6/hcOKf0446Y8iynhd963l+I6 fk56gXXkWzJXY6rDnbh6ZijSTtVD8MY3KJCeJPeCYtROueQS2ZaJgT2ZM2xCsiOaJrQ+ NeQw== 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:mime-version:content-transfer-encoding; bh=CbeVNuYlWEZFZ4ncx0FKGVgSfmasn7+dHUMJom8xrN8=; b=Lq1unIzjJX18HzxTixQitqGSgCsIagYLnw0hzsHFZHH+2eIRcfqiLxsC1KnMIP9+oA un7tBCra9SUphUbLrOo7SYKkYmdE9n2C7bFS2UE2xI8eEjSNM78idYWMrrAe7Z0IiuEz QpGHQsfdTVW+2RB7iWX60RtM2THVdTLQXF2rxVYRQ7/sbllh1G6gel8gMEGX697C57pG ETuDf0TgHxKmmsjD4KP6td2XlIK4qNmDnWhU0pUIBL4m3YM9vnFYNMb2i4UNPaFKijwT CbXPOiRzxgA9FPdkxegZJfCrUVsBxzA9Uh50GcRdCTcGZ1PbYG5mlhpZcTjEJRcZe+tk V0pQ== X-Gm-Message-State: AOAM531AYAzmUiMagYxdIFGtDJRXgbd8TPP1x/5p8J7Qzwt1t7JiBACX dvLg+YtBsz92KJV6i8T9eBGXzC9tvLk= X-Google-Smtp-Source: ABdhPJxmFwoC6Q8tIXAZC/xCBjTYGF1E5Yp9wpTwY5T1t+PlnsaM/6PgR9fq5d3QVVGzR1ZMJeyeNw== X-Received: by 2002:a19:f112:: with SMTP id p18mr3702372lfh.441.1620318410537; Thu, 06 May 2021 09:26:50 -0700 (PDT) Received: from kalashnikov.user.kdf.lan ([89.18.140.18]) by smtp.gmail.com with ESMTPSA id i1sm787164lfe.53.2021.05.06.09.26.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 May 2021 09:26:50 -0700 (PDT) From: Denis Kalashnikov To: openwrt-devel@lists.openwrt.org Cc: Gabor Juhos Subject: [PATCH 3/4] ath79: add NAND driver for Mikrotik RB91xG Date: Thu, 6 May 2021 19:25:13 +0300 Message-Id: <20210506162514.5913-4-denis281089@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210506162514.5913-1-denis281089@gmail.com> References: <20210506162514.5913-1-denis281089@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210506_172652_857532_AEA9560D X-CRM114-Status: GOOD ( 30.88 ) X-Spam-Score: 0.1 (/) X-Spam-Report: Spam detection software, running on the system "desiato.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Mikrotik guys doesn't use a NAND controller embedded in SoC on this board. Instead they control NAND through SoC gpio lines. Also NAND data and control lines are multiplexed by a latch. More painful i [...] Content analysis details: (0.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:136 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit [denis281089[at]gmail.com] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [denis281089[at]gmail.com] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Mikrotik guys doesn't use a NAND controller embedded in SoC on this board. Instead they control NAND through SoC gpio lines. Also NAND data and control lines are multiplexed by a latch. More painful is that the latch lines that are not used for NAND control lines, are used for two LEDs and a serial register nCS. So, we need a MFD driver that control access to these shared lines. Signed-off-by: Denis Kalashnikov --- .../files/drivers/mtd/nand/raw/nand_rb91x.c | 432 ++++++++++++++++++ target/linux/ath79/mikrotik/config-default | 1 + .../patches-5.4/939-mikrotik-rb91x.patch | 21 + 3 files changed, 454 insertions(+) create mode 100644 target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb91x.c diff --git a/target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb91x.c b/target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb91x.c new file mode 100644 index 0000000000..c9d5072547 --- /dev/null +++ b/target/linux/ath79/files/drivers/mtd/nand/raw/nand_rb91x.c @@ -0,0 +1,432 @@ +/* + * NAND flash driver for the MikroTik RouterBOARD 91x series + * + * Main part is copied from original driver written by Gabor Juhos. + * + * Copyright (C) 2013-2014 Gabor Juhos + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +/* + * WARNING: to speed up NAND reading/writing we are working with SoC GPIO + * controller registers directly -- not through standard GPIO API. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* TODO: ar71xx regs (SoC GPIO controller ones) should be get from DTS? */ +#include +//#include + +#include + +#define DRIVER_NAME "rb91x-nand" + +static void __iomem *ath79_gpio_base; + +#define DRV_DESC "MikrotTik RB91x NAND flash driver" + +#define NAND_LOW_DATA_MASK 0x1f +#define NAND_HIGH_DATA_MASK 0xe0 +#define NAND_HIGH_DATA_SHIFT 8 + +struct drvdata { + struct nand_chip chip; + struct device *dev; + struct rb91x_ngl *ngl; + + /* Bit masks */ + u32 nand_rdy_bit; + u32 nand_nrw_bit; + u32 nand_data_bits; + u32 nand_input_bits; + u32 nand_output_bits; +}; + +static inline struct drvdata *mtd_to_drvdata(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + + return container_of(chip, struct drvdata, chip); +} + +static struct mtd_info *drvdata_to_mtd(struct drvdata *p) +{ + return nand_to_mtd(&p->chip); +} + +static int ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + switch (section) { + case 0: + oobregion->offset = 8; + oobregion->length = 3; + return 0; + case 1: + oobregion->offset = 13; + oobregion->length = 3; + return 0; + default: + return -ERANGE; + } +} + +static int ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *oobregion) +{ + switch (section) { + case 0: + oobregion->offset = 0; + oobregion->length = 4; + return 0; + case 1: + oobregion->offset = 4; + oobregion->length = 1; + return 0; + case 2: + oobregion->offset = 6; + oobregion->length = 2; + return 0; + case 3: + oobregion->offset = 11; + oobregion->length = 2; + return 0; + default: + return -ERANGE; + } +} + +static const struct mtd_ooblayout_ops nand_ecclayout_ops = { + .ecc = ooblayout_ecc, + .free = ooblayout_free, +}; + +/* TODO: Should be in DTS */ +static struct mtd_partition nand_partitions[] = { + { + .name = "booter", + .offset = 0, + .size = (256 * 1024), + .mask_flags = MTD_WRITEABLE, + }, { + .name = "kernel", + .offset = (256 * 1024), + .size = (4 * 1024 * 1024) - (256 * 1024), + }, { + .name = "ubi", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL, + }, +}; + +static void nand_write(struct drvdata *drvdata, + const u8 *buf, + unsigned len) +{ + void __iomem *base = ath79_gpio_base; + u32 oe_reg; + u32 out_reg; + u32 out; + unsigned i; + struct rb91x_ngl *ngl = drvdata->ngl; + + ngl->latch_lock(ngl); + + oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); + out_reg = __raw_readl(base + AR71XX_GPIO_REG_OUT); + + /* set data lines to output mode */ + __raw_writel(oe_reg & ~(drvdata->nand_data_bits | drvdata->nand_nrw_bit), + base + AR71XX_GPIO_REG_OE); + + out = out_reg & ~(drvdata->nand_data_bits | drvdata->nand_nrw_bit); + for (i = 0; i != len; i++) { + u32 data; + + data = (buf[i] & NAND_HIGH_DATA_MASK) << + NAND_HIGH_DATA_SHIFT; + data |= buf[i] & NAND_LOW_DATA_MASK; + data |= out; + __raw_writel(data, base + AR71XX_GPIO_REG_OUT); + + /* deactivate WE line */ + data |= drvdata->nand_nrw_bit; + __raw_writel(data, base + AR71XX_GPIO_REG_OUT); + /* flush write */ + __raw_readl(base + AR71XX_GPIO_REG_OUT); + } + + /* restore registers */ + __raw_writel(out_reg, base + AR71XX_GPIO_REG_OUT); + __raw_writel(oe_reg, base + AR71XX_GPIO_REG_OE); + /* flush write */ + __raw_readl(base + AR71XX_GPIO_REG_OUT); + + ngl->latch_unlock(ngl); +} + +static void nand_read(struct drvdata *drvdata, + u8 *read_buf, + unsigned len) +{ + void __iomem *base = ath79_gpio_base; + u32 oe_reg; + u32 out_reg; + unsigned i; + struct rb91x_ngl *ngl = drvdata->ngl; + + /* enable read mode */ + ngl->gpio_set_value(ngl, RB91X_NGL_NAND_READ, 1); + + ngl->latch_lock(ngl); + + /* save registers */ + oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); + out_reg = __raw_readl(base + AR71XX_GPIO_REG_OUT); + + /* set data lines to input mode */ + __raw_writel(oe_reg | drvdata->nand_data_bits, + base + AR71XX_GPIO_REG_OE); + + for (i = 0; i < len; i++) { + u32 in; + u8 data; + + /* activate RE line */ + __raw_writel(drvdata->nand_nrw_bit, base + AR71XX_GPIO_REG_CLEAR); + /* flush write */ + __raw_readl(base + AR71XX_GPIO_REG_CLEAR); + + /* read input lines */ + in = __raw_readl(base + AR71XX_GPIO_REG_IN); + + /* deactivate RE line */ + __raw_writel(drvdata->nand_nrw_bit, base + AR71XX_GPIO_REG_SET); + + data = (in & NAND_LOW_DATA_MASK); + data |= (in >> NAND_HIGH_DATA_SHIFT) & + NAND_HIGH_DATA_MASK; + + read_buf[i] = data; + } + + /* restore registers */ + __raw_writel(out_reg, base + AR71XX_GPIO_REG_OUT); + __raw_writel(oe_reg, base + AR71XX_GPIO_REG_OE); + /* flush write */ + __raw_readl(base + AR71XX_GPIO_REG_OUT); + + + ngl->latch_unlock(ngl); + + /* disable read mode */ + ngl->gpio_set_value(ngl, RB91X_NGL_NAND_READ, 0); + +} + +static int dev_ready(struct nand_chip *chip) +{ + struct rb91x_ngl *ngl = ((struct drvdata *)chip->priv)->ngl; + + return ngl->gpio_get_value(ngl, RB91X_NGL_NAND_RDY); +} + +static void cmd_ctrl(struct nand_chip *chip, int cmd, + unsigned int ctrl) +{ + struct drvdata *drvdata = chip->priv; + struct rb91x_ngl *ngl = drvdata->ngl; + + if (ctrl & NAND_CTRL_CHANGE) { + ngl->gpio_set_value(ngl, RB91X_NGL_NAND_CLE, + (ctrl & NAND_CLE) ? 1 : 0); + ngl->gpio_set_value(ngl, RB91X_NGL_NAND_ALE, + (ctrl & NAND_ALE) ? 1 : 0); + ngl->gpio_set_value(ngl, RB91X_NGL_NAND_NCE, + (ctrl & NAND_NCE) ? 0 : 1); + } + + if (cmd != NAND_CMD_NONE) { + u8 t = cmd; + + nand_write(drvdata, &t, 1); + } +} + +static u8 read_byte(struct nand_chip *chip) +{ + u8 data = 0xff; + + nand_read(chip->priv, &data, 1); + + return data; +} + +static void read_buf(struct nand_chip *chip, u8 *buf, int len) +{ + nand_read(chip->priv, buf, len); +} + +static void write_buf(struct nand_chip *chip, const u8 *buf, int len) +{ + nand_write(chip->priv, buf, len); +} + +static int probe(struct platform_device *pdev) +{ + struct drvdata *drvdata; + struct mtd_info *mtd; + int ret, i; + struct device *dev = &pdev->dev, *parent = dev->parent; + struct rb91x_ngl *ngl; + + if (!parent) + return -ENODEV; + + pr_info(DRV_DESC "\n"); + + /* TODO: Should be get from DTS */ + ath79_gpio_base = ioremap(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); + + drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + platform_set_drvdata(pdev, drvdata); + + ngl = dev_get_drvdata(parent); + drvdata->ngl = ngl; + + drvdata->dev = &pdev->dev; + + drvdata->chip.priv = drvdata; + + drvdata->chip.legacy.cmd_ctrl = cmd_ctrl; + drvdata->chip.legacy.dev_ready = dev_ready; + drvdata->chip.legacy.read_byte = read_byte; + drvdata->chip.legacy.write_buf = write_buf; + drvdata->chip.legacy.read_buf = read_buf; + + drvdata->chip.legacy.chip_delay = 25; + drvdata->chip.ecc.mode = NAND_ECC_SOFT; + drvdata->chip.ecc.algo = NAND_ECC_HAMMING; + drvdata->chip.options = NAND_NO_SUBPAGE_WRITE; + + /* + * WARNING: To speed up NAND reading/writing, we work with + * SoC GPIO controller registers directly -- not through gpio API. + * So, we suppose that data gpios and nRW and RDY gpios are + * SoC gpios and its base is 0, another words: they are equal + * to bits in the SoC GPIO controller registers. + */ + + if (ngl->gpio[RB91X_NGL_NAND_RDY] >= 32) { + dev_err(dev, "NAND RDY GPIO must be < 32\n"); + return -EINVAL; + } + drvdata->nand_rdy_bit = BIT(ngl->gpio[RB91X_NGL_NAND_RDY]); + + if (ngl->gpio[RB91X_NGL_NAND_NRW] >= 32) { + dev_err(dev, "NAND NRW GPIO must be < 32\n"); + return -EINVAL; + } + drvdata->nand_nrw_bit = BIT(ngl->gpio[RB91X_NGL_NAND_NRW]); + + drvdata->nand_data_bits = 0; + for (i = 0; i < ngl->nand_datas_count(ngl); i++) { + if (ngl->gpio[RB91X_NGL_NAND_DATA0 + i] >= 32) { + dev_err(dev, "NAND Data GPIO must be < 32\n"); + return -EINVAL; + } + drvdata->nand_data_bits |= + BIT(ngl->gpio[RB91X_NGL_NAND_DATA0 + i]); + } + + drvdata->nand_input_bits = drvdata->nand_data_bits | + drvdata->nand_rdy_bit; + drvdata->nand_output_bits = drvdata->nand_data_bits | + drvdata->nand_nrw_bit; + + /* Unlock latch */ + ngl->gpio_direction_output(ngl, RB91X_NGL_NLE, 1); + + ngl->gpio_direction_output(ngl, RB91X_NGL_NAND_NCE, 1); + ngl->gpio_direction_output(ngl, RB91X_NGL_NAND_NRW, 1); + ngl->gpio_direction_output(ngl, RB91X_NGL_NAND_CLE, 0); + ngl->gpio_direction_output(ngl, RB91X_NGL_NAND_ALE, 0); + ngl->gpio_direction_output(ngl, RB91X_NGL_NAND_READ, 0); + ngl->gpio_direction_input(ngl, RB91X_NGL_NAND_RDY); + + mtd = drvdata_to_mtd(drvdata); + mtd->owner = THIS_MODULE; + ret = nand_scan(&drvdata->chip, 1); + if (ret) { + dev_err(drvdata->dev, "nand_scan() failed: %d\n", ret); + return ret; + } + + if (mtd->writesize == 512) + mtd_set_ooblayout(mtd, &nand_ecclayout_ops); + + ret = mtd_device_register(mtd, nand_partitions, + ARRAY_SIZE(nand_partitions)); + if (ret) { + dev_err(drvdata->dev, "mtd_device_register() failed: %d\n", + ret); + goto err_release_nand; + } + + return 0; + +err_release_nand: + nand_release(&drvdata->chip); + return ret; +} + +static int remove(struct platform_device *pdev) +{ + struct drvdata *drvdata = platform_get_drvdata(pdev); + + nand_release(&drvdata->chip); + + return 0; +} + +static const struct of_device_id match[] = { + { .compatible = "mikrotik,rb91x-nand" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, match); + +static struct platform_driver rb91x_nand_driver = { + .probe = probe, + .remove = remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = match, + }, +}; + +module_platform_driver(rb91x_nand_driver); + +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_AUTHOR("Denis Kalashnikov "); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ath79/mikrotik/config-default b/target/linux/ath79/mikrotik/config-default index 92b7824eba..df5442d6b3 100644 --- a/target/linux/ath79/mikrotik/config-default +++ b/target/linux/ath79/mikrotik/config-default @@ -17,6 +17,7 @@ CONFIG_MTD_NAND_AR934X=y CONFIG_MTD_NAND_CORE=y CONFIG_MTD_NAND_ECC=y CONFIG_MTD_NAND_RB4XX=y +CONFIG_MTD_NAND_RB91X=y CONFIG_MTD_RAW_NAND=y CONFIG_MTD_ROUTERBOOT_PARTS=y CONFIG_MTD_SPI_NAND=y diff --git a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch index f2135d486b..726dcdf973 100644 --- a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch +++ b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch @@ -19,6 +19,27 @@ obj-$(CONFIG_MFD_RB4XX_CPLD) += rb4xx-cpld.o + +obj-$(CONFIG_MFD_RB91X_NGL) += rb91x-ngl.o +--- a/drivers/mtd/nand/raw/Kconfig ++++ b/drivers/mtd/nand/raw/Kconfig +@@ -559,4 +559,8 @@ config MTD_NAND_RB4XX + Enables support for the NAND flash chip on Mikrotik Routerboard + RB4xx series. + ++config MTD_NAND_RB91X ++ tristate "Mikrotik RB91x NAND driver" ++ depends on MFD_RB91X_NGL ++ + endif # MTD_RAW_NAND +--- a/drivers/mtd/nand/raw/Makefile ++++ b/drivers/mtd/nand/raw/Makefile +@@ -59,6 +59,7 @@ obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm + obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o + obj-$(CONFIG_MTD_NAND_AR934X) += ar934x_nand.o + obj-$(CONFIG_MTD_NAND_RB4XX) += nand_rb4xx.o ++obj-$(CONFIG_MTD_NAND_RB91X) += nand_rb91x.o + + nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o + nand-objs += nand_onfi.o --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -130,6 +130,10 @@ config GPIO_ATH79 From patchwork Thu May 6 16:25:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis K X-Patchwork-Id: 1475165 X-Patchwork-Delegate: koen.vandeputte@ncentric.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; helo=desiato.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=ottWnHPP; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=XCCxD19m; dkim-atps=neutral Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbfD432XSz9sCD for ; Fri, 7 May 2021 02:29:08 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=hyWJ0di8tB8PskDak4ktmWkVTPDlLOuldDNxe6QqqA0=; b=ottWnHPPJORNWaDCqPZoGc5yi K6hRt3JBnuYvkUu6RzIotvPsHnw4mNaWot1lUeQi1fClA8e/90dgaJObNR0YuMta/G88MS72w6L5N vrj3a9L5t+FWjORF8ux11KRZ44HYk/xoh5yD/PbCPGuEREK/15k8rm/lfc6/MKbjJQyN7NL/Ncqc6 YXjNMbov0m3agowyvcoErCXLNFR+RZ8p0Or+eQ4EXTjOSzlxZ+tM62AtQrUM29okB6Hzb+r+dYC0r HzP3cWQIUgW7z6CIgOqpudx4ZARDBCWF0SI256zXyQ+rirCAY8kMUurxtsXcOeR4js5KyPe9jZ4VY sVyToiPvg==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1legqi-004nxg-3k; Thu, 06 May 2021 16:27:40 +0000 Received: from mail-lj1-x231.google.com ([2a00:1450:4864:20::231]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1legpz-004ni3-Bu for openwrt-devel@lists.openwrt.org; Thu, 06 May 2021 16:26:58 +0000 Received: by mail-lj1-x231.google.com with SMTP id u25so7824464ljg.7 for ; Thu, 06 May 2021 09:26:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5J55sREZQBQY4AGutq7T8phQ/rS/WVhJCBw3FBMVrQQ=; b=XCCxD19mqqGhicE0VJlXl0jdC60lzsHQunzMiXayj0S15j5DRJ89kcZ88CSEB8Cil9 xTkiWCS8YR9t/dWiSzYjo5A1pw0EBgkFI2uGufuuXATaoIsfBRpX6HGm+iCvt/KEuiOa tLz4a8DOwMwgc0oeXfeJVocBAAD1owdDK3O+dMYbukz6MPnrYoEKpVoR8b89QIjQdhRh AWgTkfZrQoaeuj4wAhaDU08sJ1Rp7uiW4PShQqufRN9uKgCuPC4Mq9+angXUkkJu9LLe iRKvE5GA/804Zu6h7T+/ZKLdqQPK6LcqiCY0m2qqP5a8i9sDWdj+C1J0GJmTcIOeK/0M A5sA== 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:mime-version:content-transfer-encoding; bh=5J55sREZQBQY4AGutq7T8phQ/rS/WVhJCBw3FBMVrQQ=; b=iVG0+cugO58tFYWMZrN4zqbDLfFX3Dv+DwWGg0tG3q/OFgTyPXlNgzapERFaNKchr6 9iTeksioZEkpGx1ca1/bWRM5RLkJPZaz6qH/ZJ8hY/PsQ1G8PyiDlPlulhtQLTfTtEIV ww/G0+3b+Hzg1qmZz7SZIdv+nCAtPJmFncGnOXadlUAhx2KLGyh4a/HHa9PqMkH7Liw+ PGdBw21/vDJGcjo4gS6qUDe4GQQOGXYrRl5Y7t3cewGrf3Q7p2AfH0y+fRl/b0/uc32E 7uVcFFP2nhqNQV/hQiPrFE6vjp3682pN0qpiOSWCeod1VHBVT1fsotLd1M66zkrW3rRr 9j0w== X-Gm-Message-State: AOAM530lGzVHdFcpNyGRv+9UkvizLcmZY5erjYTuROYmBHogCOyt5idm SyOGzLsEq0QUHeQ4Ax4soz2Yhz5s2pk= X-Google-Smtp-Source: ABdhPJwAS4IRh0UkPLHCvoALtI1N+a2VkHOExulL7ZNwGugMfrJCHvPrkRUXLpQOnfA3TXlmckE0jQ== X-Received: by 2002:a2e:9d85:: with SMTP id c5mr4120995ljj.95.1620318412102; Thu, 06 May 2021 09:26:52 -0700 (PDT) Received: from kalashnikov.user.kdf.lan ([89.18.140.18]) by smtp.gmail.com with ESMTPSA id i1sm787164lfe.53.2021.05.06.09.26.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 May 2021 09:26:51 -0700 (PDT) From: Denis Kalashnikov To: openwrt-devel@lists.openwrt.org Cc: Gabor Juhos Subject: [PATCH 4/4] ath79: add support of Mikrotik RouterBoard 91xG series Date: Thu, 6 May 2021 19:25:14 +0300 Message-Id: <20210506162514.5913-5-denis281089@gmail.com> X-Mailer: git-send-email 2.26.3 In-Reply-To: <20210506162514.5913-1-denis281089@gmail.com> References: <20210506162514.5913-1-denis281089@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210506_172655_682846_51EC88BC X-CRM114-Status: GOOD ( 24.93 ) X-Spam-Score: 0.1 (/) X-Spam-Report: Spam detection software, running on the system "desiato.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: This board has been supported in the ar71xx. Links: * https://mikrotik.com/product/RB912UAG-2HPnD * https://openwrt.org/toh/hwdata/mikrotik/mikrotik_rb912uag-2hpnd Hardware: * SoC: Atheros AR9342, 1 core, 600MHz, MIPS, code name "Wasp" (like AR9341, AR9344, AR9350), Content analysis details: (0.1 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2a00:1450:4864:20:0:0:0:231 listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit [denis281089[at]gmail.com] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [denis281089[at]gmail.com] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org This board has been supported in the ar71xx. Links: * https://mikrotik.com/product/RB912UAG-2HPnD * https://openwrt.org/toh/hwdata/mikrotik/mikrotik_rb912uag-2hpnd Hardware: * SoC: Atheros AR9342, 1 core, 600MHz, MIPS, code name "Wasp" (like AR9341, AR9344, AR9350), * RAM: DDR 64MB, * Storage: * 64KB SPI NOR: chip Winbond 25X05. With Mikrotik first-stage Bootloader and hardware config (Ethernet MAC addr, wireless calibration data, etc). Driver: upstream m25p80/spi-nor. * 128MB NAND: chip Winbond W29N01GV. With Mikrotik second-stage Bootloader, kernel, initramfs, rootfs and user data. Driver: ad-hoc rb91x-nand, since Mikrotik guys doesn't use a SoC NAND controller on this board and controls NAND chip through gpio lines multiplexed with data lines by a latch, * Ethernet: x1 10/10/1000 port with POE, MAC is embedded in SoC and is managed by upstream ag71xx driver. PHY is on the separate chip AR8033, connected through RGMII and MDIO and controlled by upstream at803x driver, * Wi-Fi: 802.11bgn, MAC in SoC, driver: ath9k, wireless calibration data is in SPI NOR flash in hard_config partition (offset 0x1000), * PCIe: host controller embedded in SoC. Driver: ar724x. On PCIe there is only USB 2.0 ECHI host controller, connected to USB port and mPCIe slot, that can be used for LTE cell modem. Only one can be powerd at the same time. * SoC GPIO: 23 lines, driver: ath79-gpio, * SPI bus: SPI controller is embedded in SoC. 3 nCS lines. Devices: SPI NOR flash (nCS 0) and a Shift Register (see below, uses gpio line as nCS). Driver: ath79-spi. * Shift register: 8-bit, on SPI bus, chip 74HC595, driver: 74x164, nCS is on gpio line, * Latch: 8-bit latch, chip NXP LVC573A. Used for multiplaction of NAND control and data lines (NAND connected to SoC GPIO lines). Several lines of the latch, that is not used for NAND control lines, are used for power LED and user LED and nCS of a shift register, * Button: controlled by ??? * Beeper/buzzer: controller by SoC gpio line ??? * LEDs: 5 general purpose LEDs connected to the shift register, power LED and user LED, connected to the latch. All them can be controlled by software. Ethernet phy LED, What is working: * Gigabit Ethernet (should be tested more under load), * SPI NOR and NAND flash (sysupgrade can be used), * 2.4 GHz Wi-Fi ('iw dev wlan0 scan' is working), * LEDs, What is not working: * USB port and mPCIe slot, * Beeper, * Button, You can flash image by sysupgrade utility or load it by net (by DHCP/TFTP, hold the button while booting). Signed-off-by: Denis Kalashnikov --- .../dts/ar9342_mikrotik_routerboard-912g.dts | 314 ++++++++++++++++++ target/linux/ath79/image/mikrotik.mk | 9 + .../base-files/etc/board.d/02_network | 2 + .../etc/hotplug.d/firmware/10-ath9k-eeprom | 1 + .../base-files/lib/upgrade/platform.sh | 1 + 5 files changed, 327 insertions(+) create mode 100644 target/linux/ath79/dts/ar9342_mikrotik_routerboard-912g.dts diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912g.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912g.dts new file mode 100644 index 0000000000..bc4aeeb6d0 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912g.dts @@ -0,0 +1,314 @@ +#include "ar9344.dtsi" + +#include +#include + +/* + * TODO list: + * - Enable beeper/buzzer, + * - Enable button/key, + * - Enable usb EHCI and export GPIOs for + * turning on/off power for USB port and mPCIe slot, + * - Test Wi-Fi working, + * - Test Gigabit Ethernet working (see pll settings), + */ + +/ { + compatible = "mikrotik,routerboard-912g"; + model = "Mikrotik RB912G"; +}; + +&ahb { + /* + * MFD: NAND plus GPIO-controller. They use/share SoC GPIO lines. Some of the + * GPIO lines are multiplexed by a 8-bit latch (LVC573). + * NAND is controlled by GPIO lines (bitbang), also some NAND control lines + * (nCE, ALE, CLE, READ) and data lines are multiplexed by a latch. So driver + * set control lines, enable latch ("latched them") and then transfer data. + * Several lines of the latch (not used for NAND control lines) are used + * as general-purpose GPIO. NAND ECC format is Mikrotik specific. + */ + /* + +-----------+ + | | ++-----------------+ | | +| | | | +| | | | +| | | | 3-4 lines +| | | +-------- +| G | 8 lines | 8-bit | GPIO +| P +-------+-------------------------------------------------+ | (leds, SSR nCS) +| I | | | Latch | +| O | | | | +| s | | | LVC573 | 4 lines +| | | | +-------+ +| | | | | | +| | | | | | +| | | | | | +| | | | | | +| | | | | | +| | | 8 +-----------+ | +| | | | +| | | l | +| | | i | +| SoC | | n | +| | | e | +| | | s +----------------------------------+ | +| | | | | | +| | | | C | | +| | | | | nCE, CLE, ALE, | +| | | | O +----------------+ +| | | | D | READ +| | | | N | +| | | | A | +| | | | N A N D T | +| | +-----------------+ T | +| | | R | nRW, RDY +| | | A +----------+ +| | | O | | +| | | | | +| | | L | | +| | | | | +| G | | | | +| P | +----------------------------------+ | +| I | 2 lines | +| O +-----------------------------------------------------------------------+ +| s | +| | ++-----------------+ + Drawn on https://asciiflow.com + */ + nand_gpio { + compatible = "mikrotik,nand-gpio-latch"; + + /* NAND control gpios */ + nand-read-gpios = <&gpio 3 0>; /* Read */ + nand-rdy-gpios = <&gpio 4 0>; /* Ready */ + nand-nrw-gpios = <&gpio 12 GPIO_ACTIVE_LOW>; /* Read/Write Strobe */ + nand-nce-gpios = <&gpio 13 GPIO_ACTIVE_LOW>; /* Chip Enable */ + nand-cle-gpios = <&gpio 14 0>; /* Command Latch */ + nand-ale-gpios = <&gpio 15 0>; /* Address Latch */ + + /* Latch Enable */ + nle-gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + + nand-data-gpios = <&gpio 0 0>, + <&gpio 1 0>, + <&gpio 2 0>, + <&gpio 3 0>, + <&gpio 4 0>, + <&gpio 13 0>, + <&gpio 14 0>, + <&gpio 15 0>; + + latch-gpios = <&gpio 0 GPIO_ACTIVE_LOW>, + <&gpio 1 GPIO_ACTIVE_LOW>, + <&gpio 2 GPIO_ACTIVE_LOW>; + + nand { + compatible = "mikrotik,rb91x-nand"; + + partitions { + compatible = "fixed-partitions"; + #size-cells = <1>; + + /* Mikrotik second-stage bootloader */ + partition@0 { + label = "booter"; + reg = <0x0000000 0x0040000>; + read-only; + }; + + /* Kernel and initramfs */ + partition@40000 { + label = "kernel"; + reg = <0x0040000 0x03c0000>; + }; + + /* Read-only rootfs and user data (overlayfs) */ + partition@400000 { + label = "ubi"; + reg = <0x0400000 0x7c00000>; + }; + }; + }; + + /* + * GPIO lines of the latch, that are not used for the NAND + * control lines. Used for Serial Shift register nCS and + * controling two LEDs: power adn user. + */ + gpio_latch: gpio { + compatible = "mikrotik,rb91x-gpio-latch"; + gpio-controller; + #gpio-cells = <2>; + }; + }; +}; + +/* We just copy-past this */ +&mdio0 { + status = "okay"; + + phy-mask = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; + +/* We just copy-paste this */ +ð0 { + status = "okay"; + + /* pll-data = <0x02000000 0x00000101 0x00001313>; */ + + /* mtd-mac-address = <&hard_config 0x10>; */ + + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + + gmac-config { + device = <&gmac>; + rxd-delay = <3>; + rxdv-delay = <3>; + }; +}; + +&spi { + status = "okay"; + + /* + * New spi-ar934x driver (that superseeds spi-ath79 and support + * new shift-register mode) seems doesn't support gpio line nCS + * (cs-gpios) (do it?). + */ + compatible = "qca,ar7100-spi"; + + /* Gpio nCS line for the shift register */ + cs-gpios = <0>, <&gpio_latch 0 GPIO_ACTIVE_LOW>; + + /* 64KB NOR SPI flash with routerboot and board config data */ + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <25000000>; + + partitions { + compatible = "mikrotik,routerboot-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Mikrotik first-stage Bootloader */ + partition@0 { + label = "routerboot"; + reg = <0x0 0x0>; + read-only; + }; + + /* + * Ethernet MAC address, wireless calibration data, + * etc. You can read them from + * /sys/firmware/mikrotik/hard_config. + * You don't need to use rbcfg util anymore. + */ + hard_config: hard_config { + read-only; + }; + + bios { + size = <0x1000>; + read-only; + }; + + /* Mikrotik Bootloader's Config */ + soft_config { + }; + }; + }; + + /* + * 8-bit Shift register 74HC595 used as output GPIO chip (5 LEDs and + * 2 lines for turning on/off power for USB port and mPCIe slot). + * nCS is connected to gpio line (not to the internal SPI controller + * line), this line goes from the SoC through the latch. + */ + ssr: ssr@1 { + compatible = "fairchild,74hc595"; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + /* SPI params */ + reg = <1>; + spi-max-frequency = <10000000>; + }; +}; + +/ { + leds { + compatible = "gpio-leds"; + + led_power { + label = "green:power"; + gpios = <&gpio_latch 1 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + led_user { + label = "green:user"; + gpios = <&gpio_latch 2 GPIO_ACTIVE_HIGH>; + }; + + led1 { + label = "green:led1"; + gpios = <&ssr 0 GPIO_ACTIVE_HIGH>; + }; + + led2 { + label = "green:led2"; + gpios = <&ssr 1 GPIO_ACTIVE_HIGH>; + }; + + led3 { + label = "green:led3"; + gpios = <&ssr 2 GPIO_ACTIVE_HIGH>; + }; + + led4 { + label = "green:led4"; + gpios = <&ssr 3 GPIO_ACTIVE_HIGH>; + }; + + led5 { + label = "green:led5"; + gpios = <&ssr 4 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + + /* Is not working now -- we don't know why */ + beeper { + compatible = "gpio-beeper"; + gpios = <&gpio 17 GPIO_ACTIVE_HIGH>; + }; +}; + +/* It is needed for USB port and mPCIe slot */ +&pcie { + status = "okay"; +}; + +/* SoC Wi-Fi MAC managed by ath9k driver (RB912UAG-2HPnD) */ +&wmac { + status = "okay"; + /* + * Wireless calibration data is in SPI NOR flash + * hard_config partition. In OpenWrt you can also + * read it from sysfs file + * /sys/firmware/mikrotik/hard_config/wlan_data + * from offset 0x1000 + * (/etc/hotplug.d/firmware/10-ath9k-eeprom script + * does this). + */ + qca,no-eeprom; +}; diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index 74f8603b5a..b9c21dab7d 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -1,5 +1,14 @@ include ./common-mikrotik.mk +define Device/mikrotik_routerboard-912g + $(Device/mikrotik_nand) + SOC := ar9342 + DEVICE_MODEL := RouterBOARD 912G + DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 + SUPPORTED_DEVICES += rb-912g +endef +TARGET_DEVICES += mikrotik_routerboard-912g + define Device/mikrotik_routerboard-493g $(Device/mikrotik_nand) SOC := ar7161 diff --git a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network index 4ffe82588c..07bb22c088 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network @@ -14,6 +14,7 @@ ath79_setup_interfaces() ucidef_add_switch "switch1" \ "0@eth1" "1:lan:4" "2:lan:1" "3:lan:2" "4:lan:3" ;; + mikrotik,routerboard-912g|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-sxt-5nd-r2|\ @@ -36,6 +37,7 @@ ath79_setup_macs() local mac_base="$(cat /sys/firmware/mikrotik/hard_config/mac_base)" case "$board" in + mikrotik,routerboard-912g|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-sxt-5nd-r2|\ diff --git a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom index 7ef6fdbe0f..7868ceaac9 100644 --- a/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +++ b/target/linux/ath79/mikrotik/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom @@ -23,6 +23,7 @@ board=$(board_name) case "$FIRMWARE" in "ath9k-eeprom-ahb-18100000.wmac.bin") case $board in + mikrotik,routerboard-912g|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-sxt-5nd-r2|\ mikrotik,routerboard-wapr-2nd) diff --git a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh index 97d388168f..736a0932f7 100644 --- a/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh +++ b/target/linux/ath79/mikrotik/base-files/lib/upgrade/platform.sh @@ -32,6 +32,7 @@ platform_do_upgrade() { case "$board" in mikrotik,routerboard-493g|\ + mikrotik,routerboard-912g|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-922uags-5hpacd|\ mikrotik,routerboard-sxt-5nd-r2)