diff --git a/include/feeds.mk b/include/feeds.mk index 98e315bceb..632fecb4a3 100644 --- a/include/feeds.mk +++ b/include/feeds.mk @@ -43,5 +43,11 @@ endef # 1: package name define GetABISuffix -$(if $(filter-out kmod-%,$(1)),$(if $(ABIV_$(1)),$(ABIV_$(1)),$(foreach v,$(wildcard $(STAGING_DIR)/pkginfo/$(1).version),$(shell cat $(v))))) +$(if $(ABIV_$(1)),$(ABIV_$(1)),$(call FormatABISuffix,$(1),$(foreach v,$(wildcard $(STAGING_DIR)/pkginfo/$(1).version),$(shell cat $(v))))) +endef + +# 1: package name +# 2: abi version +define FormatABISuffix +$(if $(filter-out kmod-%,$(1)),$(if $(2),$(if $(filter %0 %1 %2 %3 %4 %5 %6 %7 %8 %9,$(1)),-)$(2))) endef diff --git a/include/package-ipkg.mk b/include/package-ipkg.mk index c2017cd220..e972b7de0b 100644 --- a/include/package-ipkg.mk +++ b/include/package-ipkg.mk @@ -99,7 +99,7 @@ _endef=endef ifeq ($(DUMP),) define BuildTarget/ipkg - ABIV_$(1):=$(if $(filter-out kmod-%,$(1)),$(ABI_VERSION)) + ABIV_$(1):=$(call FormatABISuffix,$(1),$(ABI_VERSION)) PDIR_$(1):=$(call FeedPackageDir,$(1)) IPKG_$(1):=$$(PDIR_$(1))/$(1)$$(ABIV_$(1))_$(VERSION)_$(PKGARCH).ipk IDIR_$(1):=$(PKG_BUILD_DIR)/ipkg-$(PKGARCH)/$(1) diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile index 2f6b779e6d..94e0d9b57f 100644 --- a/package/network/config/netifd/Makefile +++ b/package/network/config/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2021-05-26 -PKG_SOURCE_VERSION:=899c2a4520526d43113f73cf673f20e2486a40fb -PKG_MIRROR_HASH:=354905192b30af88ea953241ed332555e67cdb7e3b54dd139250bf1e6ad3a709 +PKG_SOURCE_DATE:=2021-07-13 +PKG_SOURCE_VERSION:=1f283c654aeb1f8983e0a81b7a81cc4784fffe3f +PKG_MIRROR_HASH:=a65bb00f376eec5006c6efa1bc3298687054c3936de9c61997496969c93f9ccc PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 diff --git a/package/network/utils/iwinfo/Makefile b/package/network/utils/iwinfo/Makefile index b3ef261369..815c477988 100644 --- a/package/network/utils/iwinfo/Makefile +++ b/package/network/utils/iwinfo/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libiwinfo -PKG_RELEASE:=2 +PKG_RELEASE:=2.1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/iwinfo.git @@ -26,7 +26,7 @@ define Package/libiwinfo SECTION:=libs CATEGORY:=Libraries TITLE:=Generalized Wireless Information Library (iwinfo) - DEPENDS:=+libnl-tiny +libuci +libubus + DEPENDS:=+libnl-tiny +libuci +libubus +libiwinfo-data ABI_VERSION:=$(IWINFO_ABI_VERSION) endef @@ -50,6 +50,12 @@ define Package/libiwinfo-lua/description endef +define Package/libiwinfo-data + TITLE:=libiwinfo Lua binding + HIDDEN:=1 +endef + + define Package/iwinfo SECTION:=utils CATEGORY:=Utilities @@ -90,8 +96,6 @@ endef define Package/libiwinfo/install $(INSTALL_DIR) $(1)/usr/lib $(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so.$(IWINFO_ABI_VERSION) $(1)/usr/lib/libiwinfo.so.$(IWINFO_ABI_VERSION) - $(INSTALL_DIR) $(1)/usr/share/libiwinfo - $(INSTALL_DATA) $(PKG_BUILD_DIR)/hardware.txt $(1)/usr/share/libiwinfo/hardware.txt endef define Package/libiwinfo-lua/install @@ -99,6 +103,11 @@ define Package/libiwinfo-lua/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so endef +define Package/libiwinfo-data/install + $(INSTALL_DIR) $(1)/usr/share/libiwinfo + $(INSTALL_DATA) $(PKG_BUILD_DIR)/hardware.txt $(1)/usr/share/libiwinfo/devices.txt +endef + define Package/iwinfo/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/bin/iwinfo @@ -106,4 +115,5 @@ endef $(eval $(call BuildPackage,libiwinfo)) $(eval $(call BuildPackage,libiwinfo-lua)) +$(eval $(call BuildPackage,libiwinfo-data)) $(eval $(call BuildPackage,iwinfo)) diff --git a/package/network/utils/iwinfo/patches/0001-iwinfo-rename-hardware.txt-to-devices.txt.patch b/package/network/utils/iwinfo/patches/0001-iwinfo-rename-hardware.txt-to-devices.txt.patch new file mode 100644 index 0000000000..f0cfaf372d --- /dev/null +++ b/package/network/utils/iwinfo/patches/0001-iwinfo-rename-hardware.txt-to-devices.txt.patch @@ -0,0 +1,26 @@ +From a0a0e02dd91d14a50155390d5fd3b95d6ec87bf4 Mon Sep 17 00:00:00 2001 +From: Jo-Philipp Wich +Date: Sun, 11 Jul 2021 15:56:35 +0200 +Subject: [PATCH] iwinfo: rename hardware.txt to devices.txt + +Signed-off-by: Jo-Philipp Wich +--- + include/iwinfo.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/iwinfo.h b/include/iwinfo.h +index f7097cc..8469ee7 100644 +--- a/include/iwinfo.h ++++ b/include/iwinfo.h +@@ -255,7 +255,7 @@ struct iwinfo_hardware_entry { + + extern const struct iwinfo_iso3166_label IWINFO_ISO3166_NAMES[]; + +-#define IWINFO_HARDWARE_FILE "/usr/share/libiwinfo/hardware.txt" ++#define IWINFO_HARDWARE_FILE "/usr/share/libiwinfo/devices.txt" + + + struct iwinfo_ops { +-- +2.30.2 + diff --git a/target/linux/ath79/config-5.4 b/target/linux/ath79/config-5.4 index 25c3a08e69..60f57692e2 100644 --- a/target/linux/ath79/config-5.4 +++ b/target/linux/ath79/config-5.4 @@ -90,6 +90,7 @@ CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_74X164=y CONFIG_GPIO_ATH79=y CONFIG_GPIO_GENERIC=y +# CONFIG_GPIO_LATCH is not set CONFIG_HANDLE_DOMAIN_IRQ=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y @@ -172,6 +173,7 @@ CONFIG_MTD_CFI_GEOMETRY=y CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_MAP_BANK_WIDTH_1 is not set # CONFIG_MTD_MAP_BANK_WIDTH_4 is not set +# CONFIG_MTD_NAND_RB91X is not set CONFIG_MTD_PARSER_CYBERTAN=y CONFIG_MTD_PHYSMAP=y CONFIG_MTD_SPI_NOR=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 new file mode 100644 index 0000000000..ee2c12b4e0 --- /dev/null +++ b/target/linux/ath79/dts/ar9342_mikrotik_routerboard-912uag-2hpnd.dts @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "ar9344.dtsi" + +#include +#include + +/ { + compatible = "mikrotik,routerboard-912uag-2hpnd", "qca,ar9342"; + model = "MikroTik RouterBOARD 912UAG-2HPnD"; + + aliases { + led-boot = &led_power; + led-failsafe = &led_power; + led-running = &led_power; + led-upgrade = &led_power; + }; + + gpio_latch: gpio_latch { + compatible = "gpio-latch"; + gpio-controller; + #gpio-cells = <2>; + gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, + <&gpio 1 GPIO_ACTIVE_HIGH>, + <&gpio 2 GPIO_ACTIVE_HIGH>, + <&gpio 3 GPIO_ACTIVE_HIGH>, + <0>, /* Not connected */ + <&gpio 13 GPIO_ACTIVE_HIGH>, + <&gpio 14 GPIO_ACTIVE_HIGH>, + <&gpio 15 GPIO_ACTIVE_HIGH>, + <&gpio 11 GPIO_ACTIVE_LOW>; /* Latch Enable */ + }; + + nand_gpio { + compatible = "mikrotik,rb91x-nand"; + + gpios = <&gpio_latch 3 GPIO_ACTIVE_HIGH>, /* Read */ + <&gpio 4 GPIO_ACTIVE_HIGH>, /* Ready (RDY) */ + <&gpio_latch 5 GPIO_ACTIVE_LOW>, /* Chip Enable (nCE) */ + <&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) */ + + partitions { + compatible = "fixed-partitions"; + #size-cells = <1>; + + partition@0 { + label = "booter"; + reg = <0x0 0x0040000>; + read-only; + }; + + partition@40000 { + label = "kernel"; + reg = <0x0040000 0x03c0000>; + }; + + partition@400000 { + label = "ubi"; + reg = <0x0400000 0x7c00000>; + }; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_power: power { + label = "green:power"; + gpios = <&gpio_latch 1 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + 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>; + }; + }; + + gpio-export { + compatible = "gpio-export"; + + beeper { + gpio-export,name = "beeper"; + gpio-export,output = <1>; /* Must be 1 to avoid EMI induced clicking noise */ + gpios = <&ssr 5 GPIO_ACTIVE_HIGH>; + }; + + usb_power { + gpio-export,name = "power-usb"; + gpio-export,output = <1>; + gpios = <&ssr 6 GPIO_ACTIVE_HIGH>; + }; + + pcie_power { + gpio-export,name = "power-pcie"; + gpio-export,output = <0>; + gpios = <&ssr 7 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&spi { + status = "okay"; + + compatible = "qca,ar7100-spi"; + + cs-gpios = <0>, <&gpio_latch 0 GPIO_ACTIVE_LOW>; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + + partitions { + compatible = "mikrotik,routerboot-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "routerboot"; + reg = <0x0 0x0>; + read-only; + }; + + hard_config: hard_config { + read-only; + }; + + bios { + size = <0x1000>; + read-only; + }; + + soft_config { + }; + }; + }; + + ssr: ssr@1 { + compatible = "fairchild,74hc595"; + gpio-controller; + #gpio-cells = <2>; + registers-number = <1>; + reg = <1>; + spi-max-frequency = <50000000>; + }; +}; + +&mdio0 { + status = "okay"; + + phy-mask = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; + +ð0 { + status = "okay"; + + phy-mode = "rgmii-id"; + phy-handle = <&phy0>; + pll-data = <0x02000000 0x00000101 0x00001313>; + + gmac-config { + device = <&gmac>; + rgmii-gmac0 = <1>; + rgmii-enabled = <1>; + rxd-delay = <1>; + txd-delay = <1>; + }; +}; + +&wmac { + status = "okay"; + qca,no-eeprom; +}; + +&pcie { + status = "okay"; +}; + +&usb { + status = "okay"; +}; + +&usb_phy { + status = "okay"; +}; diff --git a/target/linux/ath79/files/drivers/gpio/gpio-latch.c b/target/linux/ath79/files/drivers/gpio/gpio-latch.c new file mode 100644 index 0000000000..f3545a663e --- /dev/null +++ b/target/linux/ath79/files/drivers/gpio/gpio-latch.c @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GPIO latch driver + * + * Copyright (C) 2014 Gabor Juhos + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GPIO_LATCH_DRIVER_NAME "gpio-latch" +#define GPIO_LATCH_LINES 9 + +struct gpio_latch_chip { + struct gpio_chip gc; + struct mutex mutex; + struct mutex latch_mutex; + bool latch_enabled; + int le_gpio; + bool le_active_low; + struct gpio_desc *gpios[GPIO_LATCH_LINES]; +}; + +static inline struct gpio_latch_chip *to_gpio_latch_chip(struct gpio_chip *gc) +{ + return container_of(gc, struct gpio_latch_chip, gc); +} + +static void gpio_latch_lock(struct gpio_latch_chip *glc, bool enable) +{ + mutex_lock(&glc->mutex); + + if (enable) + glc->latch_enabled = true; + + if (glc->latch_enabled) + mutex_lock(&glc->latch_mutex); +} + +static void gpio_latch_unlock(struct gpio_latch_chip *glc, bool disable) +{ + if (glc->latch_enabled) + mutex_unlock(&glc->latch_mutex); + + if (disable) + glc->latch_enabled = true; + + mutex_unlock(&glc->mutex); +} + +static int +gpio_latch_get(struct gpio_chip *gc, unsigned offset) +{ + struct gpio_latch_chip *glc = to_gpio_latch_chip(gc); + int ret; + + gpio_latch_lock(glc, false); + ret = gpiod_get_value(glc->gpios[offset]); + gpio_latch_unlock(glc, false); + + return ret; +} + +static void +gpio_latch_set(struct gpio_chip *gc, unsigned offset, int value) +{ + struct gpio_latch_chip *glc = to_gpio_latch_chip(gc); + bool enable_latch = false; + bool disable_latch = false; + + if (offset == glc->le_gpio) { + enable_latch = value ^ glc->le_active_low; + disable_latch = !enable_latch; + } + + gpio_latch_lock(glc, enable_latch); + gpiod_set_raw_value(glc->gpios[offset], value); + gpio_latch_unlock(glc, disable_latch); +} + +static int +gpio_latch_direction_output(struct gpio_chip *gc, unsigned offset, int value) +{ + struct gpio_latch_chip *glc = to_gpio_latch_chip(gc); + bool enable_latch = false; + bool disable_latch = false; + int ret; + + if (offset == glc->le_gpio) { + enable_latch = value ^ glc->le_active_low; + disable_latch = !enable_latch; + } + + gpio_latch_lock(glc, enable_latch); + ret = gpiod_direction_output_raw(glc->gpios[offset], value); + gpio_latch_unlock(glc, disable_latch); + + return ret; +} + +static int gpio_latch_probe(struct platform_device *pdev) +{ + struct gpio_latch_chip *glc; + struct gpio_chip *gc; + struct device *dev = &pdev->dev; + struct device_node *of_node = dev->of_node; + int i, n; + + glc = devm_kzalloc(dev, sizeof(*glc), GFP_KERNEL); + if (!glc) + return -ENOMEM; + + mutex_init(&glc->mutex); + mutex_init(&glc->latch_mutex); + + n = gpiod_count(dev, NULL); + if (n <= 0) { + dev_err(dev, "failed to get gpios: %d\n", n); + return n; + } else if (n != GPIO_LATCH_LINES) { + dev_err(dev, "expected %d gpios\n", GPIO_LATCH_LINES); + return -EINVAL; + } + + for (i = 0; i < n; i++) { + glc->gpios[i] = devm_gpiod_get_index_optional(dev, NULL, i, + GPIOD_OUT_LOW); + if (IS_ERR(glc->gpios[i])) { + dev_err(dev, "failed to get gpio %d: %d\n", i, + PTR_ERR(glc->gpios[i])); + return PTR_ERR(glc->gpios[i]); + } + } + + glc->le_gpio = 8; + glc->le_active_low = gpiod_is_active_low(glc->gpios[glc->le_gpio]); + + if (!glc->gpios[glc->le_gpio]) { + dev_err(dev, "missing required latch-enable gpio %d\n", + glc->le_gpio); + return -EINVAL; + } + + gc = &glc->gc; + gc->label = GPIO_LATCH_DRIVER_NAME; + gc->can_sleep = true; + gc->base = -1; + gc->ngpio = GPIO_LATCH_LINES; + gc->get = gpio_latch_get; + gc->set = gpio_latch_set; + gc->direction_output = gpio_latch_direction_output; + gc->of_node = of_node; + + platform_set_drvdata(pdev, glc); + + i = gpiochip_add(&glc->gc); + if (i) { + dev_err(dev, "gpiochip_add() failed: %d\n", i); + return i; + } + + return 0; +} + +static int gpio_latch_remove(struct platform_device *pdev) +{ + struct gpio_latch_chip *glc = platform_get_drvdata(pdev); + + gpiochip_remove(&glc->gc); + return 0; +} + +static const struct of_device_id gpio_latch_match[] = { + { .compatible = GPIO_LATCH_DRIVER_NAME }, + {}, +}; + +MODULE_DEVICE_TABLE(of, gpio_latch_match); + +static struct platform_driver gpio_latch_driver = { + .probe = gpio_latch_probe, + .remove = gpio_latch_remove, + .driver = { + .name = GPIO_LATCH_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = gpio_latch_match, + }, +}; + +module_platform_driver(gpio_latch_driver); + +MODULE_DESCRIPTION("GPIO latch driver"); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_AUTHOR("Denis Kalashnikov "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" GPIO_LATCH_DRIVER_NAME); diff --git a/target/linux/ath79/files/drivers/mtd/nand/raw/ar934x_nand.c b/target/linux/ath79/files/drivers/mtd/nand/raw/ar934x_nand.c index 5f0026b475..7ba7b68d57 100644 --- a/target/linux/ath79/files/drivers/mtd/nand/raw/ar934x_nand.c +++ b/target/linux/ath79/files/drivers/mtd/nand/raw/ar934x_nand.c @@ -1266,7 +1266,6 @@ static int ar934x_nfc_setup_hwecc(struct ar934x_nfc *nfc) * Writing a subpage separately is not supported, because * the controller only does ECC on full-page accesses. */ - nand->options = NAND_NO_SUBPAGE_WRITE; nand->ecc.size = 512; nand->ecc.bytes = 7; @@ -1325,6 +1324,9 @@ static int ar934x_nfc_attach_chip(struct nand_chip *nand) if (ret) return ret; + if (mtd->writesize == 2048) + nand->options |= NAND_NO_SUBPAGE_WRITE; + if (nand->ecc.mode == NAND_ECC_HW) { ret = ar934x_nfc_setup_hwecc(nfc); if (ret) 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 new file mode 100644 index 0000000000..e231944519 --- /dev/null +++ b/target/linux/ath79/files/drivers/mtd/nand/raw/rb91x_nand.c @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * MikroTik RB91x NAND flash driver + * + * Main part is copied from original driver written by Gabor Juhos. + * + * Copyright (C) 2013-2014 Gabor Juhos + */ + +/* + * 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 + +/* Bit masks for NAND data lines in ath79 gpio 32-bit register */ +#define RB91X_NAND_NRW_BIT BIT(12) +#define RB91X_NAND_DATA_BITS (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) \ + | BIT(13) | BIT(14) | BIT(15)) +#define RB91X_NAND_LOW_DATA_MASK 0x1f +#define RB91X_NAND_HIGH_DATA_MASK 0xe0 +#define RB91X_NAND_HIGH_DATA_SHIFT 8 + +enum rb91x_nand_gpios { + RB91X_NAND_READ,/* Read */ + RB91X_NAND_RDY, /* NAND Ready */ + RB91X_NAND_NCE, /* Chip Enable. Active low */ + RB91X_NAND_CLE, /* Command Latch Enable */ + RB91X_NAND_ALE, /* Address Latch Enable */ + RB91X_NAND_NRW, /* Read/Write. Active low */ + RB91X_NAND_NLE, /* Latch Enable. Active low */ + + RB91X_NAND_GPIOS, +}; + +struct rb91x_nand_drvdata { + struct nand_chip chip; + struct device *dev; + struct gpio_desc **gpio; + void __iomem *ath79_gpio_base; +}; + +static inline void rb91x_nand_latch_lock(struct rb91x_nand_drvdata *drvdata, + int lock) +{ + gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_NLE], lock); +} + +static int rb91x_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 rb91x_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 rb91x_nand_ecclayout_ops = { + .ecc = rb91x_ooblayout_ecc, + .free = rb91x_ooblayout_free, +}; + +static void rb91x_nand_write(struct rb91x_nand_drvdata *drvdata, + const u8 *buf, + unsigned len) +{ + void __iomem *base = drvdata->ath79_gpio_base; + u32 oe_reg; + u32 out_reg; + u32 out; + unsigned i; + + rb91x_nand_latch_lock(drvdata, 1); + + 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 & ~(RB91X_NAND_DATA_BITS | RB91X_NAND_NRW_BIT), + base + AR71XX_GPIO_REG_OE); + + out = out_reg & ~(RB91X_NAND_DATA_BITS | RB91X_NAND_NRW_BIT); + for (i = 0; i != len; i++) { + u32 data; + + data = (buf[i] & RB91X_NAND_HIGH_DATA_MASK) << + RB91X_NAND_HIGH_DATA_SHIFT; + data |= buf[i] & RB91X_NAND_LOW_DATA_MASK; + data |= out; + __raw_writel(data, base + AR71XX_GPIO_REG_OUT); + + /* Deactivate WE line */ + data |= RB91X_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); + + rb91x_nand_latch_lock(drvdata, 0); +} + +static void rb91x_nand_read(struct rb91x_nand_drvdata *drvdata, + u8 *read_buf, + unsigned len) +{ + void __iomem *base = drvdata->ath79_gpio_base; + u32 oe_reg; + u32 out_reg; + unsigned i; + + /* Enable read mode */ + gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_READ], 1); + + rb91x_nand_latch_lock(drvdata, 1); + + /* 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 | RB91X_NAND_DATA_BITS, + base + AR71XX_GPIO_REG_OE); + + for (i = 0; i < len; i++) { + u32 in; + u8 data; + + /* Activate RE line */ + __raw_writel(RB91X_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(RB91X_NAND_NRW_BIT, base + AR71XX_GPIO_REG_SET); + + data = (in & RB91X_NAND_LOW_DATA_MASK); + data |= (in >> RB91X_NAND_HIGH_DATA_SHIFT) & + RB91X_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); + + rb91x_nand_latch_lock(drvdata, 0); + + /* Disable read mode */ + gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_READ], 0); +} + +static int rb91x_nand_dev_ready(struct nand_chip *chip) +{ + struct rb91x_nand_drvdata *drvdata = (struct rb91x_nand_drvdata *)(chip->priv); + + return gpiod_get_value_cansleep(drvdata->gpio[RB91X_NAND_RDY]); +} + +static void rb91x_nand_cmd_ctrl(struct nand_chip *chip, int cmd, + unsigned int ctrl) +{ + struct rb91x_nand_drvdata *drvdata = chip->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_CLE], + (ctrl & NAND_CLE) ? 1 : 0); + gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_ALE], + (ctrl & NAND_ALE) ? 1 : 0); + gpiod_set_value_cansleep(drvdata->gpio[RB91X_NAND_NCE], + (ctrl & NAND_NCE) ? 1 : 0); + } + + if (cmd != NAND_CMD_NONE) { + u8 t = cmd; + + rb91x_nand_write(drvdata, &t, 1); + } +} + +static u8 rb91x_nand_read_byte(struct nand_chip *chip) +{ + u8 data = 0xff; + + rb91x_nand_read(chip->priv, &data, 1); + + return data; +} + +static void rb91x_nand_read_buf(struct nand_chip *chip, u8 *buf, int len) +{ + rb91x_nand_read(chip->priv, buf, len); +} + +static void rb91x_nand_write_buf(struct nand_chip *chip, const u8 *buf, int len) +{ + rb91x_nand_write(chip->priv, buf, len); +} + +static void rb91x_nand_release(struct rb91x_nand_drvdata *drvdata) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,8,0) + mtd_device_unregister(nand_to_mtd(&drvdata->chip)); + nand_cleanup(&drvdata->chip); +#else + nand_release(&drvdata->chip); +#endif +} + +static int rb91x_nand_probe(struct platform_device *pdev) +{ + struct rb91x_nand_drvdata *drvdata; + struct mtd_info *mtd; + int r; + struct device *dev = &pdev->dev; + struct gpio_descs *gpios; + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + platform_set_drvdata(pdev, drvdata); + + 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; + } + + if (gpios->ndescs != RB91X_NAND_GPIOS) { + dev_err(dev, "expected %d gpios\n", RB91X_NAND_GPIOS); + return -EINVAL; + } + + drvdata->gpio = gpios->desc; + + gpiod_direction_input(drvdata->gpio[RB91X_NAND_RDY]); + + drvdata->ath79_gpio_base = ioremap(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); + + drvdata->dev = dev; + + drvdata->chip.priv = drvdata; + + drvdata->chip.legacy.cmd_ctrl = rb91x_nand_cmd_ctrl; + drvdata->chip.legacy.dev_ready = rb91x_nand_dev_ready; + drvdata->chip.legacy.read_byte = rb91x_nand_read_byte; + drvdata->chip.legacy.write_buf = rb91x_nand_write_buf; + drvdata->chip.legacy.read_buf = rb91x_nand_read_buf; + + drvdata->chip.legacy.chip_delay = 25; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,9,0) + drvdata->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; + drvdata->chip.ecc.algo = NAND_ECC_ALGO_HAMMING; +#else + drvdata->chip.ecc.mode = NAND_ECC_SOFT; + drvdata->chip.ecc.algo = NAND_ECC_HAMMING; +#endif + drvdata->chip.options = NAND_NO_SUBPAGE_WRITE; + + r = nand_scan(&drvdata->chip, 1); + if (r) { + dev_err(dev, "nand_scan() failed: %d\n", r); + return r; + } + + mtd = nand_to_mtd(&drvdata->chip); + mtd->dev.parent = dev; + mtd_set_of_node(mtd, dev->of_node); + mtd->owner = THIS_MODULE; + if (mtd->writesize == 512) + mtd_set_ooblayout(mtd, &rb91x_nand_ecclayout_ops); + + r = mtd_device_register(mtd, NULL, 0); + if (r) { + dev_err(dev, "mtd_device_register() failed: %d\n", + r); + goto err_release_nand; + } + + return 0; + +err_release_nand: + rb91x_nand_release(drvdata); + return r; +} + +static int rb91x_nand_remove(struct platform_device *pdev) +{ + struct rb91x_nand_drvdata *drvdata = platform_get_drvdata(pdev); + + rb91x_nand_release(drvdata); + + return 0; +} + +static const struct of_device_id rb91x_nand_match[] = { + { .compatible = "mikrotik,rb91x-nand" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, rb91x_nand_match); + +static struct platform_driver rb91x_nand_driver = { + .probe = rb91x_nand_probe, + .remove = rb91x_nand_remove, + .driver = { + .name = "rb91x-nand", + .owner = THIS_MODULE, + .of_match_table = rb91x_nand_match, + }, +}; + +module_platform_driver(rb91x_nand_driver); + +MODULE_DESCRIPTION("MikrotTik RB91x NAND flash driver"); +MODULE_VERSION(DRV_VERSION); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_AUTHOR("Denis Kalashnikov "); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/ath79/image/mikrotik.mk b/target/linux/ath79/image/mikrotik.mk index 74f8603b5a..4256f77379 100644 --- a/target/linux/ath79/image/mikrotik.mk +++ b/target/linux/ath79/image/mikrotik.mk @@ -9,6 +9,15 @@ define Device/mikrotik_routerboard-493g endef TARGET_DEVICES += mikrotik_routerboard-493g +define Device/mikrotik_routerboard-912uag-2hpnd + $(Device/mikrotik_nand) + SOC := ar9342 + DEVICE_MODEL := RouterBOARD 912UAG-2HPnD + DEVICE_PACKAGES += kmod-usb-ehci kmod-usb2 + SUPPORTED_DEVICES += rb-912uag-2hpnd +endef +TARGET_DEVICES += mikrotik_routerboard-912uag-2hpnd + define Device/mikrotik_routerboard-921gs-5hpacd-15s $(Device/mikrotik_nand) SOC := qca9558 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 54e7bb20cf..bd249e0b86 100755 --- a/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network +++ b/target/linux/ath79/mikrotik/base-files/etc/board.d/02_network @@ -15,6 +15,7 @@ ath79_setup_interfaces() ucidef_add_switch "switch1" \ "0@eth1" "1:lan:4" "2:lan:1" "3:lan:2" "4:lan:3" ;; + mikrotik,routerboard-912uag-2hpnd|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-lhg-2nd|\ mikrotik,routerboard-sxt-5nd-r2|\ @@ -37,6 +38,7 @@ ath79_setup_macs() local mac_base="$(cat /sys/firmware/mikrotik/hard_config/mac_base)" case "$board" in + mikrotik,routerboard-912uag-2hpnd|\ 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..ae0c94d8ec 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-912uag-2hpnd|\ 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..6962c6fdcc 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-912uag-2hpnd|\ mikrotik,routerboard-921gs-5hpacd-15s|\ mikrotik,routerboard-922uags-5hpacd|\ mikrotik,routerboard-sxt-5nd-r2) diff --git a/target/linux/ath79/mikrotik/config-default b/target/linux/ath79/mikrotik/config-default index 8609893f6e..97dddfb197 100644 --- a/target/linux/ath79/mikrotik/config-default +++ b/target/linux/ath79/mikrotik/config-default @@ -15,6 +15,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 new file mode 100644 index 0000000000..6d84443945 --- /dev/null +++ b/target/linux/ath79/patches-5.4/939-mikrotik-rb91x.patch @@ -0,0 +1,44 @@ +--- 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 support" ++ depends on ATH79 && MTD_RAW_NAND ++ + 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) += rb91x_nand.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 + Select this option to enable GPIO driver for + Atheros AR71XX/AR724X/AR913X SoC devices. + ++config GPIO_LATCH ++ tristate "MikroTik RouterBOARD GPIO latch support" ++ depends on ATH79 ++ + 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) += gpio-latch.o + obj-$(CONFIG_GPIO_LOONGSON1) += gpio-loongson1.o + obj-$(CONFIG_GPIO_LOONGSON) += gpio-loongson.o + obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o diff --git a/target/linux/generic/config-5.4 b/target/linux/generic/config-5.4 index bc361bf659..cc68c35b04 100644 --- a/target/linux/generic/config-5.4 +++ b/target/linux/generic/config-5.4 @@ -961,6 +961,12 @@ CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_AES_ARM is not set # CONFIG_CRYPTO_AES_ARM_BS is not set # CONFIG_CRYPTO_AES_ARM_CE is not set +# CONFIG_CRYPTO_AES_ARM64 is not set +# CONFIG_CRYPTO_AES_ARM64_BS is not set +# CONFIG_CRYPTO_AES_ARM64_CE is not set +# CONFIG_CRYPTO_AES_ARM64_CE_BLK is not set +# CONFIG_CRYPTO_AES_ARM64_CE_CCM is not set +# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set # CONFIG_CRYPTO_AES_NI_INTEL is not set # CONFIG_CRYPTO_AES_TI is not set CONFIG_CRYPTO_ALGAPI=y @@ -1047,6 +1053,7 @@ CONFIG_CRYPTO_BLKCIPHER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_GHASH_ARM_CE is not set +# CONFIG_CRYPTO_GHASH_ARM64_CE is not set # CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set # CONFIG_CRYPTO_HASH is not set # CONFIG_CRYPTO_HMAC is not set @@ -1104,13 +1111,17 @@ CONFIG_CRYPTO_PCRYPT=y # CONFIG_CRYPTO_SHA1_ARM is not set # CONFIG_CRYPTO_SHA1_ARM_CE is not set # CONFIG_CRYPTO_SHA1_ARM_NEON is not set +# CONFIG_CRYPTO_SHA1_ARM64_CE is not set # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA256_ARM is not set +# CONFIG_CRYPTO_SHA256_ARM64 is not set # CONFIG_CRYPTO_SHA2_ARM_CE is not set +# CONFIG_CRYPTO_SHA2_ARM64_CE is not set # CONFIG_CRYPTO_SHA3 is not set # CONFIG_CRYPTO_SHA3_ARM64 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_SHA512_ARM is not set +# CONFIG_CRYPTO_SHA512_ARM64 is not set # CONFIG_CRYPTO_SHA512_ARM64_CE is not set # CONFIG_CRYPTO_SIMD is not set # CONFIG_CRYPTO_SM3 is not set diff --git a/target/linux/mediatek/mt7622/config-5.4 b/target/linux/mediatek/mt7622/config-5.4 index b873bdc40c..282cd0bab5 100644 --- a/target/linux/mediatek/mt7622/config-5.4 +++ b/target/linux/mediatek/mt7622/config-5.4 @@ -331,6 +331,7 @@ CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HAVE_UID16=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HOLES_IN_ZONE=y +# CONFIG_HW_RANDOM_MTK is not set CONFIG_HZ=250 CONFIG_HZ_250=y CONFIG_I2C=y @@ -527,6 +528,8 @@ CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SGL_ALLOC=y CONFIG_SG_POOL=y CONFIG_SMP=y +# CONFIG_SND_SOC_MT6797 is not set +# CONFIG_SND_SOC_MT8183 is not set CONFIG_SPARSEMEM=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_MANUAL=y