diff --git a/target/linux/airoha/dts/an7581-xg-140g-y003.dts b/target/linux/airoha/dts/an7581-xg-140g-y003.dts new file mode 100644 index 0000000000..6a5609eed3 --- /dev/null +++ b/target/linux/airoha/dts/an7581-xg-140g-y003.dts @@ -0,0 +1,344 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/dts-v1/; + +#include +#include +#include +#include "an7581.dtsi" + +/ { + model = "Bell XG-140G-Y003"; + compatible = "bell,xg-140g-y003", "airoha,an7581", "airoha,en7581"; + + aliases { + serial0 = &uart1; + }; + + chosen { + bootargs-append = " root=/dev/ubiblock0_0 rootfstype=squashfs ro console=ttyS0,115200 earlycon"; + stdout-path = "serial0:115200n8"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; + + leds { + compatible = "gpio-leds"; + + pwr_led: led-0 { + // label = "blue:power"; + color = ; + function = LED_FUNCTION_POWER; + gpios = <&en7581_pinctrl 17 GPIO_ACTIVE_LOW>; + }; + + led-1 { + label = "blue:pon"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&en7581_pinctrl 18 GPIO_ACTIVE_LOW>; + }; + + los_led: led-2 { + label = "blue:los"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&en7581_pinctrl 19 GPIO_ACTIVE_LOW>; + }; + + internet_led: led-3 { + label = "blue:internet"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&en7581_pinctrl 20 GPIO_ACTIVE_LOW>; + }; + + led-4 { + label = "blue:fxs"; + color = ; + function = LED_FUNCTION_STATUS; + gpios = <&en7581_pinctrl 33 GPIO_ACTIVE_LOW>; + }; + }; + + buttons { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&en7581_pinctrl 0 GPIO_ACTIVE_LOW>; + linux,input-type = ; + linux,code = ; + debounce-interval = <60>; + }; + }; +}; + +&en7581_pinctrl { + gpio-ranges = <&en7581_pinctrl 0 13 47>; + + mdio_pins: mdio-pins { + mux { + function = "mdio"; + groups = "mdio"; + }; + + conf { + pins = "gpio2"; + output-high; + }; + }; + + gswp2_led0_pins: gswp2-led0-pins { + mux { + pins = "gpio34"; + function = "phy2_led0"; + }; + }; + + gswp3_led0_pins: gswp3-led0-pins { + mux { + pins = "gpio35"; + function = "phy3_led0"; + }; + }; + + gswp4_led0_pins: gswp4-led0-pins { + mux { + pins = "gpio42"; + function = "phy4_led0"; + }; + }; +}; + +&snfi { + status = "okay"; +}; + +&spi_nand { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bootloader"; + reg = <0x00000000 0x00080000>; + read-only; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x7c000>; + }; + + partition@7c000 { + label = "u-boot-env"; + reg = <0x7c000 0x2000>; + + // nvmem-layout { + // compatible = "u-boot,env"; + // }; + }; + }; + + partition@80000 { + label = "romfile"; + reg = <0x00080000 0x00040000>; + }; + + partition@c0000 { + label = "nsb_master"; + reg = <0x000c0000 0x02880000>; + + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "kernel"; + reg = <0x0 0x880000>; + }; + + partition@880000 { + compatible = "linux,ubi"; + label = "ubi"; + reg = <0x880000 0x2000000>; + }; + }; + + partition@2940000 { + label = "nsb_slave"; + reg = <0x02940000 0x02880000>; + }; + + partition@51c0000 { + label = "bosa"; + reg = <0x051c0000 0x00040000>; + }; + + partition@5200000 { + label = "ri"; + reg = <0x05200000 0x00040000>; + }; + + partition@5240000 { + label = "flag"; + reg = <0x05240000 0x00040000>; + }; + + partition@5280000 { + label = "flagback"; + reg = <0x05280000 0x00040000>; + }; + + partition@52c0000 { + label = "config"; + reg = <0x052c0000 0x00a00000>; + }; + + partition@5cc0000 { + label = "framwork1"; + reg = <0x05cc0000 0x01000000>; + }; + + partition@6cc0000 { + label = "framwork2"; + reg = <0x06cc0000 0x01000000>; + }; + + partition@7cc0000 { + label = "apps"; + reg = <0x07cc0000 0x060e0000>; + }; + + partition@dda0000 { + label = "oopsfs"; + reg = <0x0dda0000 0x00400000>; + }; + + partition@e1a0000 { + label = "log"; + reg = <0x0e1a0000 0x00a00000>; + }; + }; +}; + +&i2c0 { + status = "okay"; +}; + +&npu { + status = "okay"; +}; + +ð { + status = "okay"; +}; + +&gdm1 { + status = "okay"; +}; + +&gdm4 { + status = "okay"; + phy-handle = <&phy15>; + phy-mode = "2500base-x"; + label = "lan1"; +}; + +&switch { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins>; + + ports { + port@2 { + status = "okay"; + label = "lan2"; + }; + + port@3 { + status = "okay"; + label = "lan3"; + }; + + port@4 { + status = "okay"; + label = "lan4"; + }; + }; + + mdio { + ethernet-phy@a { + status = "okay"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp2_led0_pins>; + + leds { + led@0 { + status = "okay"; + active-low; + function = LED_FUNCTION_LAN; + color = ; + }; + }; + }; + + ethernet-phy@b { + status = "okay"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp3_led0_pins>; + + leds { + led@0 { + status = "okay"; + active-low; + function = LED_FUNCTION_LAN; + color = ; + }; + }; + }; + + ethernet-phy@c { + status = "okay"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gswp4_led0_pins>; + + leds { + led@0 { + status = "okay"; + active-low; + function = LED_FUNCTION_LAN; + color = ; + }; + }; + }; + + phy15: ethernet-phy@f { + /* Airoha EN8811H */ + compatible = "ethernet-phy-id03a2.a411", "ethernet-phy-ieee802.3-c22"; + reg = <15>; + + reset-gpios = <&en7581_pinctrl 31 GPIO_ACTIVE_LOW>; + reset-assert-us = <10000>; + reset-deassert-us = <2000000>; + + leds { + #address-cells = <1>; + #size-cells = <0>; + + led@0 { + reg = <0>; + function = LED_FUNCTION_LAN; + color = ; + }; + }; + }; + }; +}; diff --git a/target/linux/airoha/image/an7581.mk b/target/linux/airoha/image/an7581.mk index 497c7acacf..9bee05adbb 100644 --- a/target/linux/airoha/image/an7581.mk +++ b/target/linux/airoha/image/an7581.mk @@ -42,3 +42,22 @@ define Device/airoha_an7581-evb-emmc ARTIFACTS := preloader.bin bl31-uboot.fip endef TARGET_DEVICES += airoha_an7581-evb-emmc + +define Device/bell_xg-140g-y003 + $(call Device/FitImageLzma) + DEVICE_VENDOR := Bell + DEVICE_MODEL := Bell XG-140G-Y003 + DEVICE_DTS := an7581-xg-140g-y003 + KERNEL_SIZE := 8704k + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGES += factory.bin + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata + DEVICE_PACKAGES := \ + kmod-phy-airoha-en8811h \ + kmod-gpio-button-hotplug \ + kmod-i2c-an7581 \ + uboot-envtools +endef +TARGET_DEVICES += bell_xg-140g-y003 diff --git a/target/linux/airoha/patches-6.12/092-01-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch b/target/linux/airoha/patches-6.12/092-01-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch new file mode 100644 index 0000000000..53e72bdeb8 --- /dev/null +++ b/target/linux/airoha/patches-6.12/092-01-v6.14-mtd-spinand-Introduce-a-way-to-avoid-raw-access.patch @@ -0,0 +1,88 @@ +From 6d9d6ab3a82af50e36e13e7bc8e2d1b970e39f79 Mon Sep 17 00:00:00 2001 +From: Takahiro Kuwano +Date: Tue, 3 Dec 2024 11:46:49 +0900 +Subject: [PATCH 1/1] mtd: spinand: Introduce a way to avoid raw access + +SkyHigh spinand device has ECC enable bit in configuration register but +it must be always enabled. If ECC is disabled, read and write ops +results in undetermined state. For such devices, a way to avoid raw +access is needed. + +Introduce SPINAND_NO_RAW_ACCESS flag to advertise the device does not +support raw access. In such devices, the on-die ECC engine ops returns +error to I/O request in raw mode. + +Checking and marking BBM need to be cared as special case, by adding +fallback mechanism that tries read/write OOB with ECC enabled. + +Signed-off-by: Takahiro Kuwano +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/core.c | 22 ++++++++++++++++++++-- + include/linux/mtd/spinand.h | 1 + + 2 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c +index 00e1bfa416ce..f46769eda388 100644 +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -294,6 +294,9 @@ static int spinand_ondie_ecc_prepare_io_req(struct nand_device *nand, + struct spinand_device *spinand = nand_to_spinand(nand); + bool enable = (req->mode != MTD_OPS_RAW); + ++ if (!enable && spinand->flags & SPINAND_NO_RAW_ACCESS) ++ return -EOPNOTSUPP; ++ + memset(spinand->oobbuf, 0xff, nanddev_per_page_oobsize(nand)); + + /* Only enable or disable the engine */ +@@ -901,9 +904,17 @@ static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos) + .oobbuf.in = marker, + .mode = MTD_OPS_RAW, + }; ++ int ret; + + spinand_select_target(spinand, pos->target); +- spinand_read_page(spinand, &req); ++ ++ ret = spinand_read_page(spinand, &req); ++ if (ret == -EOPNOTSUPP) { ++ /* Retry with ECC in case raw access is not supported */ ++ req.mode = MTD_OPS_PLACE_OOB; ++ spinand_read_page(spinand, &req); ++ } ++ + if (marker[0] != 0xff || marker[1] != 0xff) + return true; + +@@ -942,7 +953,14 @@ static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos) + if (ret) + return ret; + +- return spinand_write_page(spinand, &req); ++ ret = spinand_write_page(spinand, &req); ++ if (ret == -EOPNOTSUPP) { ++ /* Retry with ECC in case raw access is not supported */ ++ req.mode = MTD_OPS_PLACE_OOB; ++ ret = spinand_write_page(spinand, &req); ++ } ++ ++ return ret; + } + + static int spinand_mtd_block_markbad(struct mtd_info *mtd, loff_t offs) +diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h +index 702e5fb13dae..5cf11005b41a 100644 +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -314,6 +314,7 @@ struct spinand_ecc_info { + #define SPINAND_HAS_CR_FEAT_BIT BIT(1) + #define SPINAND_HAS_PROG_PLANE_SELECT_BIT BIT(2) + #define SPINAND_HAS_READ_PLANE_SELECT_BIT BIT(3) ++#define SPINAND_NO_RAW_ACCESS BIT(4) + + /** + * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure +-- +2.40.1 + diff --git a/target/linux/airoha/patches-6.12/092-02-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch b/target/linux/airoha/patches-6.12/092-02-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch new file mode 100644 index 0000000000..586e9cf153 --- /dev/null +++ b/target/linux/airoha/patches-6.12/092-02-v6.14-mtd-spinand-Add-support-for-SkyHigh-S35ML-3-family.patch @@ -0,0 +1,213 @@ +From 1a50e3612de9187857f55ee14a573f7f8e7d4ebc Mon Sep 17 00:00:00 2001 +From: Takahiro Kuwano +Date: Tue, 3 Dec 2024 11:46:50 +0900 +Subject: [PATCH] mtd: spinand: Add support for SkyHigh S35ML-3 family + +SkyHigh S35ML01G300, S35ML01G301, S35ML02G300, and S35ML04G300 are 1Gb, +2Gb, and 4Gb SLC SPI NAND flash family. This family of devices has +on-die ECC which parity bits are stored to hidden area. In this family +the on-die ECC cannot be disabled so raw access needs to be prevented. + +Link: https://www.skyhighmemory.com/download/SPI_S35ML01_04G3_002_19205.pdf?v=P +Co-developed-by: KR Kim +Signed-off-by: KR Kim +Signed-off-by: Takahiro Kuwano +Signed-off-by: Miquel Raynal +--- + drivers/mtd/nand/spi/Makefile | 2 +- + drivers/mtd/nand/spi/core.c | 1 + + drivers/mtd/nand/spi/skyhigh.c | 147 +++++++++++++++++++++++++++++++++ + include/linux/mtd/spinand.h | 1 + + 4 files changed, 150 insertions(+), 1 deletion(-) + create mode 100644 drivers/mtd/nand/spi/skyhigh.c + +diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile +index f725f0c..7fb8e21 100644 +--- a/drivers/mtd/nand/spi/Makefile ++++ b/drivers/mtd/nand/spi/Makefile +@@ -1,4 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0 + spinand-objs := core.o alliancememory.o ato.o esmt.o etron.o fmsh.o foresee.o gigadevice.o +-spinand-objs += macronix.o micron.o paragon.o toshiba.o winbond.o xtx.o ++spinand-objs += macronix.o micron.o paragon.o skyhigh.o toshiba.o winbond.o xtx.o + obj-$(CONFIG_MTD_SPI_NAND) += spinand.o +diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c +index 8e56ca6..61158d9 100644 +--- a/drivers/mtd/nand/spi/core.c ++++ b/drivers/mtd/nand/spi/core.c +@@ -1166,6 +1166,7 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = { + ¯onix_spinand_manufacturer, + µn_spinand_manufacturer, + ¶gon_spinand_manufacturer, ++ &skyhigh_spinand_manufacturer, + &toshiba_spinand_manufacturer, + &winbond_spinand_manufacturer, + &xtx_spinand_manufacturer, +diff --git a/drivers/mtd/nand/spi/skyhigh.c b/drivers/mtd/nand/spi/skyhigh.c +new file mode 100644 +index 0000000..8b32b74 +--- /dev/null ++++ b/drivers/mtd/nand/spi/skyhigh.c +@@ -0,0 +1,147 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2024 SkyHigh Memory Limited ++ * ++ * Author: Takahiro Kuwano ++ * Co-Author: KR Kim ++ */ ++ ++#include ++#include ++#include ++ ++#define SPINAND_MFR_SKYHIGH 0x01 ++#define SKYHIGH_STATUS_ECC_1TO2_BITFLIPS (1 << 4) ++#define SKYHIGH_STATUS_ECC_3TO6_BITFLIPS (2 << 4) ++#define SKYHIGH_STATUS_ECC_UNCOR_ERROR (3 << 4) ++#define SKYHIGH_CONFIG_PROTECT_EN BIT(1) ++ ++static SPINAND_OP_VARIANTS(read_cache_variants, ++ SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 4, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 2, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), ++ SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(write_cache_variants, ++ SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), ++ SPINAND_PROG_LOAD(true, 0, NULL, 0)); ++ ++static SPINAND_OP_VARIANTS(update_cache_variants, ++ SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), ++ SPINAND_PROG_LOAD(false, 0, NULL, 0)); ++ ++static int skyhigh_spinand_ooblayout_ecc(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ /* ECC bytes are stored in hidden area. */ ++ return -ERANGE; ++} ++ ++static int skyhigh_spinand_ooblayout_free(struct mtd_info *mtd, int section, ++ struct mtd_oob_region *region) ++{ ++ if (section) ++ return -ERANGE; ++ ++ /* ECC bytes are stored in hidden area. Reserve 2 bytes for the BBM. */ ++ region->offset = 2; ++ region->length = mtd->oobsize - 2; ++ ++ return 0; ++} ++ ++static const struct mtd_ooblayout_ops skyhigh_spinand_ooblayout = { ++ .ecc = skyhigh_spinand_ooblayout_ecc, ++ .free = skyhigh_spinand_ooblayout_free, ++}; ++ ++static int skyhigh_spinand_ecc_get_status(struct spinand_device *spinand, ++ u8 status) ++{ ++ switch (status & STATUS_ECC_MASK) { ++ case STATUS_ECC_NO_BITFLIPS: ++ return 0; ++ ++ case SKYHIGH_STATUS_ECC_UNCOR_ERROR: ++ return -EBADMSG; ++ ++ case SKYHIGH_STATUS_ECC_1TO2_BITFLIPS: ++ return 2; ++ ++ case SKYHIGH_STATUS_ECC_3TO6_BITFLIPS: ++ return 6; ++ ++ default: ++ break; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct spinand_info skyhigh_spinand_table[] = { ++ SPINAND_INFO("S35ML01G301", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x15), ++ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++ SPINAND_INFO("S35ML01G300", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x14), ++ NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++ SPINAND_INFO("S35ML02G300", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x25), ++ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++ SPINAND_INFO("S35ML04G300", ++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), ++ NAND_MEMORG(1, 2048, 128, 64, 4096, 80, 2, 1, 1), ++ NAND_ECCREQ(6, 32), ++ SPINAND_INFO_OP_VARIANTS(&read_cache_variants, ++ &write_cache_variants, ++ &update_cache_variants), ++ SPINAND_NO_RAW_ACCESS, ++ SPINAND_ECCINFO(&skyhigh_spinand_ooblayout, ++ skyhigh_spinand_ecc_get_status)), ++}; ++ ++static int skyhigh_spinand_init(struct spinand_device *spinand) ++{ ++ /* ++ * Config_Protect_En (bit 1 in Block Lock register) must be set to 1 ++ * before writing other bits. Do it here before core unlocks all blocks ++ * by writing block protection bits. ++ */ ++ return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, ++ SKYHIGH_CONFIG_PROTECT_EN); ++} ++ ++static const struct spinand_manufacturer_ops skyhigh_spinand_manuf_ops = { ++ .init = skyhigh_spinand_init, ++}; ++ ++const struct spinand_manufacturer skyhigh_spinand_manufacturer = { ++ .id = SPINAND_MFR_SKYHIGH, ++ .name = "SkyHigh", ++ .chips = skyhigh_spinand_table, ++ .nchips = ARRAY_SIZE(skyhigh_spinand_table), ++ .ops = &skyhigh_spinand_manuf_ops, ++}; +diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h +index 5cf11005b41ae2..cbbcd44ac22565 100644 +--- a/include/linux/mtd/spinand.h ++++ b/include/linux/mtd/spinand.h +@@ -268,6 +268,7 @@ extern const struct spinand_manufacturer gigadevice_spinand_manufacturer; + extern const struct spinand_manufacturer macronix_spinand_manufacturer; + extern const struct spinand_manufacturer micron_spinand_manufacturer; + extern const struct spinand_manufacturer paragon_spinand_manufacturer; ++extern const struct spinand_manufacturer skyhigh_spinand_manufacturer; + extern const struct spinand_manufacturer toshiba_spinand_manufacturer; + extern const struct spinand_manufacturer winbond_spinand_manufacturer; + extern const struct spinand_manufacturer xtx_spinand_manufacturer; +-- +2.40.1 +