From patchwork Tue Nov 16 16:06:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis K X-Patchwork-Id: 1555924 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: bilbo.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=PV1BT24O; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=nKJXrIZX; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4Htrg24q2Pz9s5P for ; Wed, 17 Nov 2021 03:12:14 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=0j6V316Yw/0AItXDkDYRQ5GDLQELkvQLQG/MrzpCs+Y=; b=PV1BT24OGIfnwN TRkfU4GHn9b9xPFUhuuD5dkd+22F6dkLgPmp+xDnaiDZsP1Jf229bGw2gyuwKp4p+A0Jqr2ZT1hO5 UOuabqLCYmdJGrpCja3g5bs/P+8swG25cKkrkyp/lHkwFlTiKLFeKNj8fwwjtPtXfQx+tLLe3MkVh 1tVy92oHfVLf5i8aAKqJgTN4mAbY3Q78d1kiR0QZqKcuoqf4hwE0dhNoFgMJFHuWDjPO7hEti1yjV jxi6I23mfjMnfKBN4zcCn/4u0uvOAUsr7iOAeFSG1V6ST51YRjpsaicD5CuDc51j9NosZEgCk8IJf Ssv+DPdygBxoBmVqnB1A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mn102-002HJb-VG; Tue, 16 Nov 2021 16:07:59 +0000 Received: from mail-lj1-x22c.google.com ([2a00:1450:4864:20::22c]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mn0zc-002HEl-4T for openwrt-devel@lists.openwrt.org; Tue, 16 Nov 2021 16:07:34 +0000 Received: by mail-lj1-x22c.google.com with SMTP id 207so44351937ljf.10 for ; Tue, 16 Nov 2021 08:07:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9E9zv2t/jDNwRjMhCC0cZTfzjJNcOKq6wRSb2/f5N1I=; b=nKJXrIZXfIlke0uA+c3Zov0MTlgpyjEsxWF2Z3Hl9Z/H+TiKgQq7pqpDG9TE2SZYaM J9nZFpIn/4YlVd1sTtAPyOnpJjvojr4QF+SjwXkRMBCsriIerXP/SCRTo0a1YXkeXO44 SnIpe5fbF4uHeZ/b5GMW2dQsgYILhptJQ784XQoBwZfOFN5mOmvUWvkSKc8c6eia/k20 7DwcfTxppmxfC7v4bP382ha9jOJ4mimCTBnLFNle1oyVvrTBxqzLYsqvYTkuWIcF/Lzc X7XK5r1opIDShVzwhIzkIwl2VovGhzrTXBn71W1kvvu4NHf/QwHq6PZcnPVnTcIW8HB4 l0EQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9E9zv2t/jDNwRjMhCC0cZTfzjJNcOKq6wRSb2/f5N1I=; b=nlATo40QcTSNWMEQAYLH2K01QbUfIGmTMDEkhCTtFRqf7HeBMIKg1MPXj5MsEXRLSZ Dkr7az6GI9mi3bl65/WFGpGmjpaohOgGuQ4kMDc7q5JU2m0Dq5DjiUYkFnYHzKVkNz4t et3jgvICrakbiEygtkGkD2RpLUwvmzKeiHzt7YZma8uOCI/tUrpURqvOQus4dMEQT5I8 Y6zWzfRrkur5UNrMaBx8zets6HYKgrMj8mtxiogyzupf5Kxjn1tb2ve85D06ZSJwaMTm V3B4Xja4YboLkJ5MAFuLsgQfphbHt9dTu60ZR9c9GLJVBeAV3sdmg0vnAIsRwR9EQvAI JSig== X-Gm-Message-State: AOAM530cY4dCv8aRHmtTPxzVE4zz+6oko5n7WTTXqimd7T0Zuxs4QrXw rKwxJxxvlOsEmog+iLfShE22TusgQlr6Cg== X-Google-Smtp-Source: ABdhPJyohlbiDGPwEVzYq1qyy241eIxAf8zCqVjaSZSTmqDbGEQZkeolZ7t6baGt9a/HbZAmAv2Bfg== X-Received: by 2002:a05:651c:2dd:: with SMTP id f29mr273703ljo.464.1637078848243; Tue, 16 Nov 2021 08:07:28 -0800 (PST) Received: from kalashnikov.user.kdf.lan ([89.18.140.18]) by smtp.gmail.com with ESMTPSA id b22sm2002202lfv.20.2021.11.16.08.07.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Nov 2021 08:07:26 -0800 (PST) From: Denis Kalashnikov To: openwrt-devel@lists.openwrt.org Cc: Koen Vandeputte , Sergey Ryazanov Subject: [PATCH v2 1/2] ath79: add support for reset key on MikroTik RB912UAG-2HPnD Date: Tue, 16 Nov 2021 19:06:43 +0300 Message-Id: <20211116160644.2047-2-denis281089@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211116160644.2047-1-denis281089@gmail.com> References: <20211116160644.2047-1-denis281089@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_080732_231312_AE6B4153 X-CRM114-Status: GOOD ( 30.99 ) X-Spam-Score: 0.1 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.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: On MikroTik RB91x board series a reset key shares SoC gpio line #15 with NAND ALE and NAND IO7. So we need a custom gpio driver to manage this non-trivial connection schema. Also rb91x-nand needs to h [...] 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:22c 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.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [denis281089[at]gmail.com] 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit [denis281089[at]gmail.com] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 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 On MikroTik RB91x board series a reset key shares SoC gpio line #15 with NAND ALE and NAND IO7. So we need a custom gpio driver to manage this non-trivial connection schema. Also rb91x-nand needs to have ability to disable a polling of the key while it works with NAND, and we need to add "cansleep" suffix to several gpiolib calls in gpio-latch. Signed-off-by: Denis Kalashnikov Reviewed-by: Sergey Ryazanov --- Changes in v2: * Fix identations of switch statements. target/linux/ath79/config-5.10 | 1 + target/linux/ath79/config-5.4 | 1 + ...9342_mikrotik_routerboard-912uag-2hpnd.dts | 23 +- .../ath79/files/drivers/gpio/gpio-latch.c | 4 +- .../ath79/files/drivers/gpio/gpio-rb91x-key.c | 216 ++++++++++++++++++ .../files/drivers/mtd/nand/raw/rb91x_nand.c | 15 +- target/linux/ath79/mikrotik/config-default | 1 + .../patches-5.10/939-mikrotik-rb91x.patch | 19 ++ .../patches-5.4/939-mikrotik-rb91x.patch | 19 ++ 9 files changed, 293 insertions(+), 6 deletions(-) create mode 100644 target/linux/ath79/files/drivers/gpio/gpio-rb91x-key.c diff --git a/target/linux/ath79/config-5.10 b/target/linux/ath79/config-5.10 index 786d70decf..cbd883c4d3 100644 --- a/target/linux/ath79/config-5.10 +++ b/target/linux/ath79/config-5.10 @@ -74,6 +74,7 @@ CONFIG_GPIO_74X164=y CONFIG_GPIO_ATH79=y CONFIG_GPIO_GENERIC=y # CONFIG_GPIO_LATCH is not set +# CONFIG_GPIO_RB91X_KEY is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y diff --git a/target/linux/ath79/config-5.4 b/target/linux/ath79/config-5.4 index e37b728554..6ae5559730 100644 --- a/target/linux/ath79/config-5.4 +++ b/target/linux/ath79/config-5.4 @@ -91,6 +91,7 @@ CONFIG_GPIO_74X164=y CONFIG_GPIO_ATH79=y CONFIG_GPIO_GENERIC=y # CONFIG_GPIO_LATCH is not set +# CONFIG_GPIO_RB91X_KEY is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y diff --git a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts index ee2c12b4e0..34140a3f63 100644 --- a/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts @@ -16,6 +16,13 @@ led-upgrade = &led_power; }; + gpio_key: gpio_key { + compatible = "mikrotik,gpio-rb91x-key"; + gpio-controller; + #gpio-cells = <2>; + gpio = <&gpio 15 GPIO_ACTIVE_HIGH>; + }; + gpio_latch: gpio_latch { compatible = "gpio-latch"; gpio-controller; @@ -27,7 +34,7 @@ <0>, /* Not connected */ <&gpio 13 GPIO_ACTIVE_HIGH>, <&gpio 14 GPIO_ACTIVE_HIGH>, - <&gpio 15 GPIO_ACTIVE_HIGH>, + <&gpio_key 0 GPIO_ACTIVE_HIGH>, <&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ }; @@ -40,7 +47,8 @@ <&gpio_latch 6 GPIO_ACTIVE_HIGH>, /* Command Latch Enable (CLE) */ <&gpio_latch 7 GPIO_ACTIVE_HIGH>, /* Address Latch Enable (ALE) */ <&gpio 12 GPIO_ACTIVE_LOW>, /* Read/Write Enable (nRW) */ - <&gpio_latch 8 GPIO_ACTIVE_LOW>; /* Latch Enable (nLE) */ + <&gpio_latch 8 GPIO_ACTIVE_LOW>, /* Latch Enable (nLE) */ + <&gpio_key 2 GPIO_ACTIVE_HIGH>; /* Key poll disable */ partitions { compatible = "fixed-partitions"; @@ -64,6 +72,17 @@ }; }; + keys { + compatible = "gpio-keys-polled"; + poll-interval = <20>; + + button@0 { + label = "reset"; + linux,code = ; + gpios = <&gpio_key 1 GPIO_ACTIVE_LOW>; + }; + }; + leds { compatible = "gpio-leds"; diff --git a/target/linux/ath79/files/drivers/gpio/gpio-latch.c b/target/linux/ath79/files/drivers/gpio/gpio-latch.c index f3545a663e..44d6e3173c 100644 --- a/target/linux/ath79/files/drivers/gpio/gpio-latch.c +++ b/target/linux/ath79/files/drivers/gpio/gpio-latch.c @@ -62,7 +62,7 @@ gpio_latch_get(struct gpio_chip *gc, unsigned offset) int ret; gpio_latch_lock(glc, false); - ret = gpiod_get_value(glc->gpios[offset]); + ret = gpiod_get_raw_value_cansleep(glc->gpios[offset]); gpio_latch_unlock(glc, false); return ret; @@ -81,7 +81,7 @@ gpio_latch_set(struct gpio_chip *gc, unsigned offset, int value) } gpio_latch_lock(glc, enable_latch); - gpiod_set_raw_value(glc->gpios[offset], value); + gpiod_set_raw_value_cansleep(glc->gpios[offset], value); gpio_latch_unlock(glc, disable_latch); } diff --git a/target/linux/ath79/files/drivers/gpio/gpio-rb91x-key.c b/target/linux/ath79/files/drivers/gpio/gpio-rb91x-key.c new file mode 100644 index 0000000000..ec7b68dd4f --- /dev/null +++ b/target/linux/ath79/files/drivers/gpio/gpio-rb91x-key.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for reset key gpio line on MikroTik RB91x board series. + * This line is shared between NAND ALE (goes through a latch), + * NAND IO7 and reset key. We make 3 virtual gpio lines from the + * single physical one: + * 1) Capable output one for NAND, + * 2) Capable input one for reset key, + * 3) And capable output one, aka "key-poll-disable", + * for NAND -- to syncronise NAND operation and key polling. + * + * Copyright (C) 2021 Denis Kalashnikov + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_RB91X_KEY_DRIVER_NAME "gpio-rb91x-key" + +enum gpio_rb91x_key_gpios { + GPIO_RB91X_KEY_NAND, + GPIO_RB91X_KEY_POLL, + GPIO_RB91X_KEY_PDIS, + + GPIO_RB91X_KEY_NGPIOS, +}; + +struct gpio_rb91x_key { + struct gpio_chip gc; + struct mutex mutex; + struct mutex poll_mutex; + int polling_disabled; + struct gpio_desc *gpio; +}; + +static inline struct gpio_rb91x_key *to_gpio_rb91x_key(struct gpio_chip *gc) +{ + return container_of(gc, struct gpio_rb91x_key, gc); +} + +static int gpio_rb91x_key_get(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_rb91x_key *drvdata = to_gpio_rb91x_key(gc); + struct gpio_desc *gpio = drvdata->gpio; + int val, bak_val; + + switch (offset) { + case GPIO_RB91X_KEY_NAND: + mutex_lock(&drvdata->mutex); + val = gpiod_get_value_cansleep(gpio); + mutex_unlock(&drvdata->mutex); + break; + case GPIO_RB91X_KEY_PDIS: + mutex_lock(&drvdata->mutex); + val = drvdata->polling_disabled; + mutex_unlock(&drvdata->mutex); + break; + case GPIO_RB91X_KEY_POLL: + mutex_lock(&drvdata->poll_mutex); + mutex_lock(&drvdata->mutex); + bak_val = gpiod_get_raw_value_cansleep(gpio); + gpiod_direction_input(gpio); + /* + * Without this delay nothing works. Get it + * from mikrotik RouterOS linux kernel patches. + */ + udelay(200); + val = gpiod_get_raw_value_cansleep(gpio); + gpiod_direction_output_raw(gpio, bak_val); + mutex_unlock(&drvdata->mutex); + mutex_unlock(&drvdata->poll_mutex); + break; + default: + return -EINVAL; + } + + return val; +} + +static int gpio_rb91x_key_direction_input(struct gpio_chip *gc, unsigned offset) +{ + switch (offset) { + case GPIO_RB91X_KEY_POLL: + return 0; + default: + return -EINVAL; + } +} + +static void gpio_rb91x_key_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct gpio_rb91x_key *drvdata = to_gpio_rb91x_key(gc); + struct gpio_desc *gpio = drvdata->gpio; + + mutex_lock(&drvdata->mutex); + + switch (offset) { + case GPIO_RB91X_KEY_NAND: + gpiod_set_raw_value_cansleep(gpio, value); + break; + case GPIO_RB91X_KEY_PDIS: + if (value) { + if (!drvdata->polling_disabled) { + mutex_lock(&drvdata->poll_mutex); + drvdata->polling_disabled = 1; + } + } else { + if (drvdata->polling_disabled) { + mutex_unlock(&drvdata->poll_mutex); + drvdata->polling_disabled = 0; + } + } + break; + default: + break; + } + + mutex_unlock(&drvdata->mutex); +} + +static int gpio_rb91x_key_direction_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + switch (offset) { + case GPIO_RB91X_KEY_NAND: + case GPIO_RB91X_KEY_PDIS: + gpio_rb91x_key_set(gc, offset, value); + return 0; + default: + return -EINVAL; + } +} + +static int gpio_rb91x_key_probe(struct platform_device *pdev) +{ + struct gpio_rb91x_key *drvdata; + struct gpio_chip *gc; + struct device *dev = &pdev->dev; + struct device_node *of_node = dev->of_node; + int r; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + mutex_init(&drvdata->mutex); + mutex_init(&drvdata->poll_mutex); + + drvdata->gpio = devm_gpiod_get(dev, NULL, GPIOD_OUT_LOW); + if (IS_ERR(drvdata->gpio)) { + dev_err(dev, "failed to get gpio: %ld\n", + PTR_ERR(drvdata->gpio)); + return PTR_ERR(drvdata->gpio); + } + + gc = &drvdata->gc; + gc->label = GPIO_RB91X_KEY_DRIVER_NAME; + gc->can_sleep = 1; + gc->base = -1; + gc->ngpio = GPIO_RB91X_KEY_NGPIOS; + gc->get = gpio_rb91x_key_get; + gc->set = gpio_rb91x_key_set; + gc->direction_output = gpio_rb91x_key_direction_output; + gc->direction_input = gpio_rb91x_key_direction_input; + gc->of_node = of_node; + + platform_set_drvdata(pdev, drvdata); + + r = gpiochip_add(&drvdata->gc); + if (r) { + dev_err(dev, "gpiochip_add() failed: %d\n", r); + return r; + } + + return 0; +} + +static int gpio_rb91x_key_remove(struct platform_device *pdev) +{ + struct gpio_rb91x_key *drvdata = platform_get_drvdata(pdev); + + gpiochip_remove(&drvdata->gc); + return 0; +} + +static const struct of_device_id gpio_rb91x_key_match[] = { + { .compatible = "mikrotik,"GPIO_RB91X_KEY_DRIVER_NAME }, + {}, +}; + +MODULE_DEVICE_TABLE(of, gpio_rb91x_key_match); + +static struct platform_driver gpio_rb91x_key_driver = { + .probe = gpio_rb91x_key_probe, + .remove = gpio_rb91x_key_remove, + .driver = { + .name = GPIO_RB91X_KEY_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = gpio_rb91x_key_match, + }, +}; + +module_platform_driver(gpio_rb91x_key_driver); + +MODULE_DESCRIPTION("Driver for reset key gpio line shared with NAND for MikroTik RB91x board series."); +MODULE_AUTHOR("Denis Kalashnikov "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" GPIO_RB91X_KEY_DRIVER_NAME); diff --git a/target/linux/ath79/files/drivers/mtd/nand/raw/rb91x_nand.c b/target/linux/ath79/files/drivers/mtd/nand/raw/rb91x_nand.c index e231944519..3ed17e45be 100644 --- a/target/linux/ath79/files/drivers/mtd/nand/raw/rb91x_nand.c +++ b/target/linux/ath79/files/drivers/mtd/nand/raw/rb91x_nand.c @@ -40,6 +40,7 @@ enum rb91x_nand_gpios { RB91X_NAND_ALE, /* Address Latch Enable */ RB91X_NAND_NRW, /* Read/Write. Active low */ RB91X_NAND_NLE, /* Latch Enable. Active low */ + RB91X_NAND_PDIS, /* Reset Key Poll Disable. Active high */ RB91X_NAND_GPIOS, }; @@ -57,6 +58,12 @@ static inline void rb91x_nand_latch_lock(struct rb91x_nand_drvdata *drvdata, gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_NLE], lock); } +static inline void rb91x_nand_rst_key_poll_disable(struct rb91x_nand_drvdata *drvdata, + int disable) +{ + gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_PDIS], disable); +} + static int rb91x_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion) { @@ -115,6 +122,7 @@ static void rb91x_nand_write(struct rb91x_nand_drvdata *drvdata, unsigned i; rb91x_nand_latch_lock(drvdata, 1); + rb91x_nand_rst_key_poll_disable(drvdata, 1); oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); out_reg = __raw_readl(base + AR71XX_GPIO_REG_OUT); @@ -146,6 +154,7 @@ static void rb91x_nand_write(struct rb91x_nand_drvdata *drvdata, /* Flush write */ __raw_readl(base + AR71XX_GPIO_REG_OUT); + rb91x_nand_rst_key_poll_disable(drvdata, 0); rb91x_nand_latch_lock(drvdata, 0); } @@ -162,6 +171,7 @@ static void rb91x_nand_read(struct rb91x_nand_drvdata *drvdata, gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_READ], 1); rb91x_nand_latch_lock(drvdata, 1); + rb91x_nand_rst_key_poll_disable(drvdata, 1); /* Save registers */ oe_reg = __raw_readl(base + AR71XX_GPIO_REG_OE); @@ -199,6 +209,7 @@ static void rb91x_nand_read(struct rb91x_nand_drvdata *drvdata, /* Flush write */ __raw_readl(base + AR71XX_GPIO_REG_OUT); + rb91x_nand_rst_key_poll_disable(drvdata, 0); rb91x_nand_latch_lock(drvdata, 0); /* Disable read mode */ @@ -278,8 +289,8 @@ static int rb91x_nand_probe(struct platform_device *pdev) gpios = gpiod_get_array(dev, NULL, GPIOD_OUT_LOW); if (IS_ERR(gpios)) { - dev_err(dev, "failed to get gpios: %d\n", (int)gpios); - return -EINVAL; + dev_err(dev, "failed to get gpios: %d\n", PTR_ERR(gpios)); + return PTR_ERR(gpios); } if (gpios->ndescs != RB91X_NAND_GPIOS) { diff --git a/target/linux/ath79/mikrotik/config-default b/target/linux/ath79/mikrotik/config-default index 74cfdf0423..f09f5c86bb 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_RB91X_KEY=y CONFIG_GPIO_RB4XX=y CONFIG_GPIO_WATCHDOG=y CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y diff --git a/target/linux/ath79/patches-5.10/939-mikrotik-rb91x.patch b/target/linux/ath79/patches-5.10/939-mikrotik-rb91x.patch index 5bbab93c51..4f4344b40f 100644 --- a/target/linux/ath79/patches-5.10/939-mikrotik-rb91x.patch +++ b/target/linux/ath79/patches-5.10/939-mikrotik-rb91x.patch @@ -14,6 +14,17 @@ config GPIO_LOGICVC tristate "Xylon LogiCVC GPIO support" depends on MFD_SYSCON && OF +@@ -495,6 +502,10 @@ config GPIO_REG + A 32-bit single register GPIO fixed in/out implementation. This + can be used to represent any register as a set of GPIO signals. + ++config GPIO_RB91X_KEY ++ tristate "MikroTik RB91x board series reset key support" ++ depends on ATH79 ++ + config GPIO_SAMA5D2_PIOBU + tristate "SAMA5D2 PIOBU GPIO support" + depends on MFD_SYSCON --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -72,6 +72,7 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o @@ -24,6 +35,14 @@ obj-$(CONFIG_GPIO_LOGICVC) += gpio-logicvc.o obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o +@@ -121,6 +122,7 @@ obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o + obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o + obj-$(CONFIG_GPIO_RB4XX) += gpio-rb4xx.o ++obj-$(CONFIG_GPIO_RB91X_KEY) += gpio-rb91x-key.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o + obj-$(CONFIG_GPIO_RDA) += gpio-rda.o --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -571,4 +571,10 @@ config MTD_NAND_RB4XX 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 6d84443945..680269507e 100644 --- a/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch +++ b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch @@ -32,6 +32,17 @@ config GPIO_RASPBERRYPI_EXP tristate "Raspberry Pi 3 GPIO Expander" default RASPBERRYPI_FIRMWARE +@@ -441,6 +445,10 @@ config GPIO_REG + A 32-bit single register GPIO fixed in/out implementation. This + can be used to represent any register as a set of GPIO signals. + ++config GPIO_RB91X_KEY ++ tristate "MikroTik RB91x board series reset key support" ++ depends on ATH79 ++ + config GPIO_SAMA5D2_PIOBU + tristate "SAMA5D2 PIOBU GPIO support" + depends on MFD_SYSCON --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_GPIO_IT87) += gpio-it87.o @@ -42,3 +53,11 @@ obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o +@@ -114,6 +115,7 @@ obj-$(CONFIG_GPIO_PMIC_EIC_SPRD) += gpio + obj-$(CONFIG_GPIO_PXA) += gpio-pxa.o + obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o + obj-$(CONFIG_GPIO_RB4XX) += gpio-rb4xx.o ++obj-$(CONFIG_GPIO_RB91X_KEY) += gpio-rb91x-key.o + obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t583.o + obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o + obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o From patchwork Tue Nov 16 16:06:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Denis K X-Patchwork-Id: 1555926 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: bilbo.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=mAkU/mai; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20210112 header.b=Se+dut7o; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4Htrg42gc1z9s5P for ; Wed, 17 Nov 2021 03:12:16 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=5TPxBBDFAjWJSh0+23l3Y055SG1ahOLhiJgWuoR0xxo=; b=mAkU/mai2b31MS Q7+HefSNaBg+NpOjUyn58+vfyACUHiNkqMRD4KPzNWZXl0ywWWVT56VtQCqqZOKURZajZA5qMeAqp jTm+3nUco0yLBWQn5t59JpNPiIJ05i2h/mDo/6pUHTsf9BMTgHKndPhrAyJsThx8jwPuhwPk50/vB yd3flZMXddvEg47znOK+SOkZh0c73K5TzVmhRz1CANQiuZ01WZkRMcUGjlAEdBAO/BsGiAoTVP81E JRD0QbuTJgUk8WbOUPrggm71XAQv49oxEiANRNoTcHb5Ji78Eze2NKyGBVhAOZvvQx8y+4YNlz6C+ VEZunG9EyaQe7/LfrAPw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mn0zp-002HGu-6U; Tue, 16 Nov 2021 16:07:45 +0000 Received: from mail-lf1-x136.google.com ([2a00:1450:4864:20::136]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mn0zb-002HEd-JV for openwrt-devel@lists.openwrt.org; Tue, 16 Nov 2021 16:07:33 +0000 Received: by mail-lf1-x136.google.com with SMTP id f18so54630150lfv.6 for ; Tue, 16 Nov 2021 08:07:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GFZwGxar8bCzq8/+U3/zJyQrGIPYhxm8GACjzl/NRwc=; b=Se+dut7oNtU96NKNPgmwyhckvYs8WBnXbqvKrNAVXUqk6pnktS6g2p8XHDUB4h51IJ 2MU6KDLd5V38vJpqMY1pGvdNCBVWI9jwDYgKQwi2jD8jATWJkkkk9KB8lMf99ymQbf4g Zsiu9GoI/6kE7CEQpGGs6H3SCGrVqP83+tcaaEzIEh7NqR5fsgZ88SPUIApL6eLE1+kh Koffw8ADr+RyPFB0POeR06KOQ9U4MDcmj3MtYePGfBZdvQqU8ZmdHhPgw78VA5zXVyYj CMhWUB0OLUT7QlaU/FhCdpiYmQkVd17sFpsUAi7/hIiozlHYxSLhmE/umd4amerM5GXA vYEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GFZwGxar8bCzq8/+U3/zJyQrGIPYhxm8GACjzl/NRwc=; b=iGy9B1SCviOx+8xZ97nw1Euxhoa+H47HDYfCH/cdCreYx8Dg4UERTnZuAzeEpVVLWI 6flzcd8NI31t+92qJ/0kh9fBuhI+o+hhKWDeRcv0KrU1nkNDAdaphdZGLnIzFVB6mAet C0D5am3SbG2I/q2lROww1hyXHkLLjSgamRKQxM1z01VV0RjUNg5aOACstO04lXDOUjj4 kJQPRBzhdWuDJmTh29lqAEXhS5KccDQ67+yVirynVKQatpJQmJt1VI3mht4cb4BTS9Ix h3HafVp6fOVsBXzI1Zsyl0hQ2YZ3RwTyhhpSCgM7NvlVpZ7M8zg2L46r9juLICcCJhmI k7Aw== X-Gm-Message-State: AOAM533lvF1GNQQUxYao6+buJYgKsVmITIAJmQpdlmz62vZSINHQnSWZ gfO+TLIdnI/60dE9rN5VLO8WMz6zhZZIPQ== X-Google-Smtp-Source: ABdhPJxXvmfjDa7NGZEUUUqT8n13Fj9KCaGDjtoo2I7kQVAY+AFD8qqnFd03ZN+77VnxMorSG9HmYw== X-Received: by 2002:a05:6512:5c2:: with SMTP id o2mr7624243lfo.8.1637078848979; Tue, 16 Nov 2021 08:07:28 -0800 (PST) Received: from kalashnikov.user.kdf.lan ([89.18.140.18]) by smtp.gmail.com with ESMTPSA id b22sm2002202lfv.20.2021.11.16.08.07.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Nov 2021 08:07:28 -0800 (PST) From: Denis Kalashnikov To: openwrt-devel@lists.openwrt.org Cc: Koen Vandeputte , Sergey Ryazanov , Thibaut Subject: [PATCH v2 2/2] generic: platform/mikrotik: use MTD notifier Date: Tue, 16 Nov 2021 19:06:44 +0300 Message-Id: <20211116160644.2047-3-denis281089@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211116160644.2047-1-denis281089@gmail.com> References: <20211116160644.2047-1-denis281089@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211116_080731_674286_BDB9C678 X-CRM114-Status: GOOD ( 18.62 ) X-Spam-Score: 0.1 (/) X-Spam-Report: Spam detection software, running on the system "bombadil.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: If the SPI probe is sufficiently delayed, the routerboot driver may fail to init as the routerboot partitions are not yet available. Register an MTD user notifier instead of doing straight init so that the init subroutines are only executed when the target MTD partitions are present. 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.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [denis281089[at]gmail.com] 0.2 FREEMAIL_ENVFROM_END_DIGIT Envelope-from freemail username ends in digit [denis281089[at]gmail.com] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 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 If the SPI probe is sufficiently delayed, the routerboot driver may fail to init as the routerboot partitions are not yet available. Register an MTD user notifier instead of doing straight init so that the init subroutines are only executed when the target MTD partitions are present. Because the init/exit routines can now be called outside of the kernel normal init/exit calls, they cannot be jettisoned and must always be available: the __init and __exit qualifiers are thus removed. Reported-by: Denis Kalashnikov Signed-off-by: Denis Kalashnikov Signed-off-by: Thibaut VARĂˆNE Reviewed-by: Sergey Ryazanov --- v2: * Use MTD notifier (hopefully a robust and right way of doing this thing) instead of late_initcall workaround. v1: * Replace module_init() with late_intcall() in routerboot module. .../drivers/platform/mikrotik/rb_hardconfig.c | 16 +++---- .../drivers/platform/mikrotik/rb_softconfig.c | 16 +++---- .../drivers/platform/mikrotik/routerboot.c | 45 ++++++++++++++++--- .../drivers/platform/mikrotik/routerboot.h | 8 ++-- 4 files changed, 59 insertions(+), 26 deletions(-) diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c index e6a6928896..5ba8b376f2 100644 --- a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c +++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c @@ -676,10 +676,9 @@ static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj, return count; } -int __init rb_hardconfig_init(struct kobject *rb_kobj) +int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) { struct kobject *hc_wlan_kobj; - struct mtd_info *mtd; size_t bytes_read, buflen, outlen; const u8 *buf; void *outbuf; @@ -690,20 +689,19 @@ int __init rb_hardconfig_init(struct kobject *rb_kobj) hc_kobj = NULL; hc_wlan_kobj = NULL; - // TODO allow override - mtd = get_mtd_device_nm(RB_MTD_HARD_CONFIG); - if (IS_ERR(mtd)) + ret = __get_mtd_device(mtd); + if (ret) return -ENODEV; hc_buflen = mtd->size; hc_buf = kmalloc(hc_buflen, GFP_KERNEL); if (!hc_buf) { - put_mtd_device(mtd); + __put_mtd_device(mtd); return -ENOMEM; } ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf); - put_mtd_device(mtd); + __put_mtd_device(mtd); if (ret) goto fail; @@ -818,8 +816,10 @@ fail: return ret; } -void __exit rb_hardconfig_exit(void) +void rb_hardconfig_exit(void) { kobject_put(hc_kobj); + hc_kobj = NULL; kfree(hc_buf); + hc_buf = NULL; } diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c index 070bd32d5a..5273b8d7ed 100644 --- a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c +++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c @@ -705,9 +705,8 @@ mtdfail: static struct kobj_attribute sc_kattrcommit = __ATTR(commit, RB_SC_RMODE|RB_SC_WMODE, sc_commit_show, sc_commit_store); -int __init rb_softconfig_init(struct kobject *rb_kobj) +int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd) { - struct mtd_info *mtd; size_t bytes_read, buflen; const u8 *buf; int i, ret; @@ -716,20 +715,19 @@ int __init rb_softconfig_init(struct kobject *rb_kobj) sc_buf = NULL; sc_kobj = NULL; - // TODO allow override - mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG); - if (IS_ERR(mtd)) + ret = __get_mtd_device(mtd); + if (ret) return -ENODEV; sc_buflen = mtd->size; sc_buf = kmalloc(sc_buflen, GFP_KERNEL); if (!sc_buf) { - put_mtd_device(mtd); + __put_mtd_device(mtd); return -ENOMEM; } ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf); - put_mtd_device(mtd); + __put_mtd_device(mtd); if (ret) goto fail; @@ -799,8 +797,10 @@ fail: return ret; } -void __exit rb_softconfig_exit(void) +void rb_softconfig_exit(void) { kobject_put(sc_kobj); + sc_kobj = NULL; kfree(sc_buf); + sc_buf = NULL; } diff --git a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c index 4c8c0bfac5..96f2460916 100644 --- a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c +++ b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "routerboot.h" @@ -160,25 +161,57 @@ fail: return ret; } -static int __init routerboot_init(void) +static void routerboot_mtd_notifier_add(struct mtd_info *mtd) { - rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj); - if (!rb_kobj) - return -ENOMEM; + /* Currently routerboot is only known to live on NOR flash */ + if (mtd->type != MTD_NORFLASH) + return; /* * We ignore the following return values and always register. * These init() routines are designed so that their failed state is * always manageable by the corresponding exit() calls. + * Notifier is called with MTD mutex held: use __get/__put variants. + * TODO: allow partition names override */ - rb_hardconfig_init(rb_kobj); - rb_softconfig_init(rb_kobj); + if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) + rb_hardconfig_init(rb_kobj, mtd); + else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) + rb_softconfig_init(rb_kobj, mtd); +} + +static void routerboot_mtd_notifier_remove(struct mtd_info *mtd) +{ + if (mtd->type != MTD_NORFLASH) + return; + + if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) + rb_hardconfig_exit(); + else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) + rb_softconfig_exit(); +} + +/* Note: using a notifier prevents qualifying init()/exit() functions with __init/__exit */ +static struct mtd_notifier routerboot_mtd_notifier = { + .add = routerboot_mtd_notifier_add, + .remove = routerboot_mtd_notifier_remove, +}; + +static int __init routerboot_init(void) +{ + rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj); + if (!rb_kobj) + return -ENOMEM; + + register_mtd_user(&routerboot_mtd_notifier); return 0; } static void __exit routerboot_exit(void) { + unregister_mtd_user(&routerboot_mtd_notifier); + /* Exit routines are idempotent */ rb_softconfig_exit(); rb_hardconfig_exit(); kobject_put(rb_kobj); // recursive afaict diff --git a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h index 67d89808d5..e858a524af 100644 --- a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h +++ b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h @@ -25,11 +25,11 @@ int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id, u16 *pld_ofs, u16 *pld_len); int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen); -int __init rb_hardconfig_init(struct kobject *rb_kobj); -void __exit rb_hardconfig_exit(void); +int rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); +void rb_hardconfig_exit(void); -int __init rb_softconfig_init(struct kobject *rb_kobj); -void __exit rb_softconfig_exit(void); +int rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd); +void rb_softconfig_exit(void); ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf); ssize_t routerboot_tag_show_u32s(const u8 *pld, u16 pld_len, char *buf);