Merge Official Source
Signed-off-by: Tianling Shen <i@cnsztl.eu.org>
This commit is contained in:
commit
64f4b111aa
2
include/kernel-5.10
Normal file
2
include/kernel-5.10
Normal file
@ -0,0 +1,2 @@
|
||||
LINUX_VERSION-5.10 = .90
|
||||
LINUX_KERNEL_HASH-5.10.90 = 945e4264c014a3d9dfc0a4639309dd1ec2fb545416556421f931b95da78c2725
|
||||
2
include/kernel-5.4
Normal file
2
include/kernel-5.4
Normal file
@ -0,0 +1,2 @@
|
||||
LINUX_VERSION-5.4 = .170
|
||||
LINUX_KERNEL_HASH-5.4.170 = b09f74e0cf5fc7cf5de6aa932fe654c962cb10118bdbbdddb397022c6e6d382c
|
||||
@ -6,11 +6,12 @@ ifdef CONFIG_TESTING_KERNEL
|
||||
KERNEL_PATCHVER:=$(KERNEL_TESTING_PATCHVER)
|
||||
endif
|
||||
|
||||
LINUX_VERSION-5.4 = .170
|
||||
LINUX_VERSION-5.10 = .90
|
||||
KERNEL_DETAILS_FILE=$(INCLUDE_DIR)/kernel-$(KERNEL_PATCHVER)
|
||||
ifeq ($(wildcard $(KERNEL_DETAILS_FILE)),)
|
||||
$(error Missing kernel version/hash file for $(KERNEL_PATCHVER). Please create $(KERNEL_DETAILS_FILE))
|
||||
endif
|
||||
|
||||
LINUX_KERNEL_HASH-5.4.170 = b09f74e0cf5fc7cf5de6aa932fe654c962cb10118bdbbdddb397022c6e6d382c
|
||||
LINUX_KERNEL_HASH-5.10.90 = 945e4264c014a3d9dfc0a4639309dd1ec2fb545416556421f931b95da78c2725
|
||||
include $(KERNEL_DETAILS_FILE)
|
||||
|
||||
remove_uri_prefix=$(subst git://,,$(subst http://,,$(subst https://,,$(1))))
|
||||
sanitize_uri=$(call qstrip,$(subst @,_,$(subst :,_,$(subst .,_,$(subst -,_,$(subst /,_,$(1)))))))
|
||||
|
||||
@ -5,9 +5,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
|
||||
PKG_SOURCE_DATE:=2021-12-02
|
||||
PKG_SOURCE_VERSION:=5ca5e0b4d058a47d72ba4102acdcec826e203c41
|
||||
PKG_MIRROR_HASH:=8a1fd6b634a0390a5ee512483c924b3ea8fa3ea9fa863d0434e3e66949faccab
|
||||
PKG_SOURCE_DATE:=2022-01-14
|
||||
PKG_SOURCE_VERSION:=3043206e94da412eb19dd72ea68edcaca545d84c
|
||||
PKG_MIRROR_HASH:=2bf5a59e93968b00f69b8b7ebbdfd28353c36bc5e7f72225d725c24d0ac7265f
|
||||
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
@ -411,9 +411,15 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
char ssid[SSID_MAX_LEN + 1];
|
||||
char phy_name[17];
|
||||
size_t ssid_len = SSID_MAX_LEN;
|
||||
u8 channel = 0, op_class = 0;
|
||||
|
||||
if (hapd->conf->ssid.ssid_len < SSID_MAX_LEN)
|
||||
ssid_len = hapd->conf->ssid.ssid_len;
|
||||
|
||||
ieee80211_freq_to_channel_ext(hapd->iface->freq,
|
||||
hapd->iconf->secondary_channel,
|
||||
hostapd_get_oper_chwidth(hapd->iconf),
|
||||
&op_class, &channel);
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state));
|
||||
@ -424,7 +430,8 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
blobmsg_add_string(&b, "ssid", ssid);
|
||||
|
||||
blobmsg_add_u32(&b, "freq", hapd->iface->freq);
|
||||
blobmsg_add_u32(&b, "channel", ieee80211_frequency_to_channel(hapd->iface->freq));
|
||||
blobmsg_add_u32(&b, "channel", channel);
|
||||
blobmsg_add_u32(&b, "op_class", op_class);
|
||||
blobmsg_add_u32(&b, "beacon_interval", hapd->iconf->beacon_int);
|
||||
|
||||
snprintf(phy_name, 17, "%s", hapd->iface->phy);
|
||||
@ -1930,4 +1937,4 @@ int hostapd_ubus_notify_bss_transition_query(
|
||||
|
||||
return ureq.resp;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=iptables
|
||||
PKG_VERSION:=1.8.7
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_SOURCE_URL:=https://netfilter.org/projects/iptables/files
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
|
||||
@ -60,7 +60,7 @@ define Package/iptables/config
|
||||
|
||||
config IPTABLES_NFTABLES
|
||||
bool "Enable Nftables support"
|
||||
default n
|
||||
default y
|
||||
help
|
||||
This enable nftables support in iptables.
|
||||
endef
|
||||
|
||||
@ -12,9 +12,9 @@ PKG_RELEASE:=$(AUTORELEASE)
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/procd.git
|
||||
PKG_MIRROR_HASH:=3ce6f5e2c12ae276af3ffe1755a495415f77184974206a44a3b083420aba52a8
|
||||
PKG_SOURCE_DATE:=2021-12-20
|
||||
PKG_SOURCE_VERSION:=129d050b9f5725ea4c54e1d906aba43eca95b860
|
||||
PKG_MIRROR_HASH:=0e506062a992f77979bd59eb51fb5d500e45197cc7bfba3a9302415d754dbfd1
|
||||
PKG_SOURCE_DATE:=2022-01-11
|
||||
PKG_SOURCE_VERSION:=ac2b8b365bdbcbf292f77409d180ec3c0963faf3
|
||||
CMAKE_INSTALL:=1
|
||||
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
@ -127,6 +127,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
&ref {
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
&spi {
|
||||
status = "okay";
|
||||
|
||||
@ -194,7 +198,6 @@
|
||||
gmac-config {
|
||||
device = <&gmac>;
|
||||
rgmii-gmac0 = <1>;
|
||||
rgmii-enabled = <1>;
|
||||
rxd-delay = <1>;
|
||||
txd-delay = <1>;
|
||||
};
|
||||
|
||||
@ -99,7 +99,6 @@
|
||||
partition@0 {
|
||||
label = "RouterBoot";
|
||||
reg = <0x0 0x20000>;
|
||||
read-only;
|
||||
compatible = "mikrotik,routerboot-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
@ -38,7 +38,6 @@
|
||||
partition@0 {
|
||||
label = "RouterBoot";
|
||||
reg = <0x0 0x20000>;
|
||||
read-only;
|
||||
compatible = "mikrotik,routerboot-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
@ -73,7 +73,6 @@
|
||||
partition@0 {
|
||||
label = "RouterBoot";
|
||||
reg = <0x0 0x20000>;
|
||||
read-only;
|
||||
compatible = "mikrotik,routerboot-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
@ -112,8 +112,7 @@
|
||||
};
|
||||
|
||||
pll: pll-controller@18050000 {
|
||||
compatible = "qca,qca9550-pll",
|
||||
"qca,qca9550-pll", "syscon";
|
||||
compatible = "qca,qca9550-pll", "syscon";
|
||||
reg = <0x18050000 0x50>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
|
||||
@ -19,6 +19,7 @@ CONFIG_MTD_NAND_RB91X=y
|
||||
CONFIG_MTD_RAW_NAND=y
|
||||
CONFIG_MTD_ROUTERBOOT_PARTS=y
|
||||
CONFIG_MTD_SPI_NAND=y
|
||||
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
|
||||
CONFIG_MTD_SPLIT_MINOR_FW=y
|
||||
CONFIG_MTD_UBI=y
|
||||
CONFIG_MTD_UBI_BLOCK=y
|
||||
|
||||
@ -3661,6 +3661,7 @@ CONFIG_MTD_ROOTFS_ROOT_DEV=y
|
||||
# CONFIG_MTD_SPI_NOR is not set
|
||||
# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
|
||||
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT=4096
|
||||
# CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE is not set
|
||||
CONFIG_MTD_SPLIT=y
|
||||
# CONFIG_MTD_SPLIT_BCM63XX_FW is not set
|
||||
# CONFIG_MTD_SPLIT_BCM_WFI_FW is not set
|
||||
@ -3688,6 +3689,7 @@ CONFIG_MTD_SPLIT_SUPPORT=y
|
||||
# CONFIG_MTD_UBI_GLUEBI is not set
|
||||
# CONFIG_MTD_UIMAGE_SPLIT is not set
|
||||
# CONFIG_MTD_VIRT_CONCAT is not set
|
||||
# CONFIG_MTD_NAND_MTK_BMT is not set
|
||||
# CONFIG_MTK_MMC is not set
|
||||
# CONFIG_MTK_MMSYS is not set
|
||||
CONFIG_MULTIUSER=y
|
||||
|
||||
1201
target/linux/generic/files/drivers/mtd/nand/mtk_bmt.c
Normal file
1201
target/linux/generic/files/drivers/mtd/nand/mtk_bmt.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -39,7 +39,7 @@
|
||||
|
||||
#include "routerboot.h"
|
||||
|
||||
#define RB_HARDCONFIG_VER "0.06"
|
||||
#define RB_HARDCONFIG_VER "0.07"
|
||||
#define RB_HC_PR_PFX "[rb_hardconfig] "
|
||||
|
||||
/* ID values for hardware settings */
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -56,23 +56,12 @@
|
||||
|
||||
#include "routerboot.h"
|
||||
|
||||
#define RB_SOFTCONFIG_VER "0.03"
|
||||
#define RB_SOFTCONFIG_VER "0.05"
|
||||
#define RB_SC_PR_PFX "[rb_softconfig] "
|
||||
|
||||
/*
|
||||
* mtd operations before 4.17 are asynchronous, not handled by this code
|
||||
* Also make the driver act read-only if 4K_SECTORS are not enabled, since they
|
||||
* are require to handle partial erasing of the small soft_config partition.
|
||||
*/
|
||||
#if defined(CONFIG_MTD_SPI_NOR_USE_4K_SECTORS)
|
||||
#define RB_SC_HAS_WRITE_SUPPORT true
|
||||
#define RB_SC_WMODE S_IWUSR
|
||||
#define RB_SC_RMODE S_IRUSR
|
||||
#else
|
||||
#define RB_SC_HAS_WRITE_SUPPORT false
|
||||
#define RB_SC_WMODE 0
|
||||
#define RB_SC_RMODE S_IRUSR
|
||||
#endif
|
||||
#define RB_SC_HAS_WRITE_SUPPORT true
|
||||
#define RB_SC_WMODE S_IWUSR
|
||||
#define RB_SC_RMODE S_IRUSR
|
||||
|
||||
/* ID values for software settings */
|
||||
#define RB_SCID_UART_SPEED 0x01 // u32*1
|
||||
@ -705,9 +694,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 +704,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 +786,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;
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
||||
#include "routerboot.h"
|
||||
|
||||
@ -160,25 +161,57 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void routerboot_mtd_notifier_add(struct mtd_info *mtd)
|
||||
{
|
||||
/* 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
|
||||
*/
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
rb_hardconfig_init(rb_kobj);
|
||||
rb_softconfig_init(rb_kobj);
|
||||
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
|
||||
|
||||
@ -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);
|
||||
|
||||
18
target/linux/generic/files/include/linux/mtd/mtk_bmt.h
Normal file
18
target/linux/generic/files/include/linux/mtd/mtk_bmt.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef __MTK_BMT_H
|
||||
#define __MTK_BMT_H
|
||||
|
||||
#ifdef CONFIG_MTD_NAND_MTK_BMT
|
||||
int mtk_bmt_attach(struct mtd_info *mtd);
|
||||
void mtk_bmt_detach(struct mtd_info *mtd);
|
||||
#else
|
||||
static inline int mtk_bmt_attach(struct mtd_info *mtd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void mtk_bmt_detach(struct mtd_info *mtd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
23
target/linux/generic/hack-5.10/430-mtk-bmt-support.patch
Normal file
23
target/linux/generic/hack-5.10/430-mtk-bmt-support.patch
Normal file
@ -0,0 +1,23 @@
|
||||
--- a/drivers/mtd/nand/Kconfig
|
||||
+++ b/drivers/mtd/nand/Kconfig
|
||||
@@ -15,6 +15,10 @@ config MTD_NAND_ECC
|
||||
bool
|
||||
depends on MTD_NAND_CORE
|
||||
|
||||
+config MTD_NAND_MTK_BMT
|
||||
+ bool "Support MediaTek NAND Bad-block Management Table"
|
||||
+ default n
|
||||
+
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
--- a/drivers/mtd/nand/Makefile
|
||||
+++ b/drivers/mtd/nand/Makefile
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
nandcore-objs := core.o bbt.o
|
||||
obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
|
||||
+obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o
|
||||
|
||||
obj-y += onenand/
|
||||
obj-y += raw/
|
||||
@ -0,0 +1,397 @@
|
||||
From patchwork Tue Jun 8 04:07:19 2021
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
X-Patchwork-Submitter: John Thomson <git@johnthomson.fastmail.com.au>
|
||||
X-Patchwork-Id: 1489105
|
||||
X-Patchwork-Delegate: tudor.ambarus@gmail.com
|
||||
Return-Path:
|
||||
<linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org>
|
||||
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.infradead.org
|
||||
(client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org;
|
||||
envelope-from=linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org;
|
||||
receiver=<UNKNOWN>)
|
||||
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=bombadil.20210309 header.b=EMabhVoR;
|
||||
dkim=fail reason="signature verification failed" (2048-bit key;
|
||||
unprotected) header.d=fastmail.com.au header.i=@fastmail.com.au
|
||||
header.a=rsa-sha256 header.s=fm3 header.b=dLzuZ6dB;
|
||||
dkim=fail reason="signature verification failed" (2048-bit key;
|
||||
unprotected) header.d=messagingengine.com header.i=@messagingengine.com
|
||||
header.a=rsa-sha256 header.s=fm3 header.b=nSRGsW+C;
|
||||
dkim-atps=neutral
|
||||
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 ozlabs.org (Postfix) with ESMTPS id 4FzcFN1j1nz9sW8
|
||||
for <incoming@patchwork.ozlabs.org>; Tue, 8 Jun 2021 14:09:28 +1000 (AEST)
|
||||
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: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:In-Reply-To:References:
|
||||
List-Owner; bh=6mUWQd71FwsINycGYY1qOhKz+ecWJVNtwDkTebG3XkA=; b=EMabhVoRE3ad89
|
||||
o3L2AgyKrs+blSofUC3hoSsQe7gi3m4si8S9HW8Z+8SsS5TufUsvGwDl80qSYGlQOytQF+1yRUWvE
|
||||
6FJ/+bqv+TwjqZFibgJ6+9OVsQN9dZ/no1R0bBXIpmrf8ORUmv58QK4ZQquaFKbyXKpFeWOC2MSv4
|
||||
H2MAhyhTU8a3gtooH6G8+KvsJEfVgh6C+aDbwxyh2UY3chHKuw1kvL6AktbfUE2xl4zxi3x3kc70B
|
||||
Wi3LiJBFokxVdgnROXxTU5tI0XboWYkQV64gLuQNV4XKClcuhVpzloDK8Iok6NTd7b32a7TdEFlCS
|
||||
lGKsEKmxtUlW2FpfoduA==;
|
||||
Received: from localhost ([::1] helo=bombadil.infradead.org)
|
||||
by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux))
|
||||
id 1lqT1r-006OAW-DX; Tue, 08 Jun 2021 04:07:51 +0000
|
||||
Received: from new1-smtp.messagingengine.com ([66.111.4.221])
|
||||
by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux))
|
||||
id 1lqT1l-006O9b-Fq
|
||||
for linux-mtd@lists.infradead.org; Tue, 08 Jun 2021 04:07:50 +0000
|
||||
Received: from compute2.internal (compute2.nyi.internal [10.202.2.42])
|
||||
by mailnew.nyi.internal (Postfix) with ESMTP id 4456B580622;
|
||||
Tue, 8 Jun 2021 00:07:42 -0400 (EDT)
|
||||
Received: from mailfrontend2 ([10.202.2.163])
|
||||
by compute2.internal (MEProxy); Tue, 08 Jun 2021 00:07:42 -0400
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=fastmail.com.au;
|
||||
h=from:to:cc:subject:date:message-id:mime-version
|
||||
:content-transfer-encoding; s=fm3; bh=ZXRH+YluM1mHCS1EWUiCY/Sg8O
|
||||
LccfHe1oW5iAay6y8=; b=dLzuZ6dBYf7ZA8tWLOBFZYLi7ERsGe/4vnMXG+ovvb
|
||||
dNBO0+SaFGwoqYSFrfq/TeyHfKyvxrA7+LCdopIuT4abpLHxtRwtRiafQcDYCPat
|
||||
qJIqOZO+wCZC5S9Jc1OP7+t1FviGpgevqIMotci37P+RWc5u3AweMzFljZk90E8C
|
||||
uorV6rXagD+OssJQzllRnAIK88+rOAC9ZyXv2gWxy4d1HSCwSWgzx2vnV9CNp918
|
||||
YC/3tiHas9krbrPIaAsdBROr7Bvoe/ShRRzruKRuvZVgg5NN90vX+/5ZjI8u04GM
|
||||
p2bWCbC62CP6wlcgDaz+c/Sgr5ITd2GPENJsHfqmLRBA==
|
||||
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
|
||||
messagingengine.com; h=cc:content-transfer-encoding:date:from
|
||||
:message-id:mime-version:subject:to:x-me-proxy:x-me-proxy
|
||||
:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; bh=ZXRH+YluM1mHCS1EW
|
||||
UiCY/Sg8OLccfHe1oW5iAay6y8=; b=nSRGsW+CQ2Zx1RVpIUu8W/VD/k5P+32BW
|
||||
5k2ltd+UhI3dfldBPzHrYiOP/IJqGkNW+V+rHASacW/vFygnaZoxNjRYKnOsu+26
|
||||
wb2yK3jpl6lsNTg3N1Z4XJrYY2lf9H29DMFbhC67l0PTc050rcZk4XsKTLAlv14Q
|
||||
VA4WREYSaX/4IN4O+ES4TMq0a/3gKZh6nvbbJXbsXfK0WlSHTGZtZmW3fyrqvbXa
|
||||
t+R7L8vvqWvwls0pV+Sn8LeQqb7+A69w0UOnuznjkcA3sCc2YehcHbxcUEnMH+9N
|
||||
bxOjmIDeg9/4X/829tUWUJiLhE5SFmQZ1P6oFtmbWoLrDz0ZJIVBw==
|
||||
X-ME-Sender: <xms:C-2-YD2uka4HsA6gcdsV2Ia7vebY4Yjp9E8q7KBMb54jnAzGL7-67Q>
|
||||
<xme:C-2-YCEaxASy5VlcrvNO_jLFpMDGkFCRsuVNuZGEQsiRZygk8jPHWq7unPjeT6uYS
|
||||
2pUP6PrTQ2rggjEIg>
|
||||
X-ME-Received:
|
||||
<xmr:C-2-YD4exeK49N_YZWWf2BWDhVyCbCY3wwvjTyDOFxeugx7Jg08pzMUToo9oJjrBpcVTaA3kbfk>
|
||||
X-ME-Proxy-Cause:
|
||||
gggruggvucftvghtrhhoucdtuddrgeduledrfedtkedgjeduucetufdoteggodetrfdotf
|
||||
fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen
|
||||
uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne
|
||||
cujfgurhephffvufffkffoggfgsedtkeertdertddtnecuhfhrohhmpeflohhhnhcuvfhh
|
||||
ohhmshhonhcuoehgihhtsehjohhhnhhthhhomhhsohhnrdhfrghsthhmrghilhdrtghomh
|
||||
drrghuqeenucggtffrrghtthgvrhhnpefffeeihfdukedtuedufeetieeuudfhhefhkefh
|
||||
tefgtdeuffekffelleetveduieenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmh
|
||||
epmhgrihhlfhhrohhmpehgihhtsehjohhhnhhthhhomhhsohhnrdhfrghsthhmrghilhdr
|
||||
tghomhdrrghu
|
||||
X-ME-Proxy: <xmx:C-2-YI0AJZGjcB3wIbI9BoC9X8VNl4i9A7cQnBkvwZ25czWJlkKCLw>
|
||||
<xmx:C-2-YGGufw99T-O81-FeiSyEruv6_Pr0IHFhspQdxjv5k1VFTZ0lzQ>
|
||||
<xmx:C-2-YJ8BW7DhSDSCEAPSJWrwh_hHP79qreTZtWh_kOUwSh1c0MMlAg>
|
||||
<xmx:Du2-YJBeX2Fg9oFZVXGwEJ1ZrZnXHiAqNON8tbpzquYgcm2o_LM48g>
|
||||
Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue,
|
||||
8 Jun 2021 00:07:35 -0400 (EDT)
|
||||
From: John Thomson <git@johnthomson.fastmail.com.au>
|
||||
To: Miquel Raynal <miquel.raynal@bootlin.com>,
|
||||
Richard Weinberger <richard@nod.at>, Vignesh Raghavendra <vigneshr@ti.com>,
|
||||
Tudor Ambarus <tudor.ambarus@microchip.com>,
|
||||
Michael Walle <michael@walle.cc>, Pratyush Yadav <p.yadav@ti.com>,
|
||||
linux-mtd@lists.infradead.org
|
||||
Cc: linux-kernel@vger.kernel.org,
|
||||
John Thomson <git@johnthomson.fastmail.com.au>,
|
||||
kernel test robot <lkp@intel.com>, Dan Carpenter <dan.carpenter@oracle.com>
|
||||
Subject: [PATCH] mtd: spi-nor: write support for minor aligned partitions
|
||||
Date: Tue, 8 Jun 2021 14:07:19 +1000
|
||||
Message-Id: <20210608040719.14431-1-git@johnthomson.fastmail.com.au>
|
||||
X-Mailer: git-send-email 2.31.1
|
||||
MIME-Version: 1.0
|
||||
X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3
|
||||
X-CRM114-CacheID: sfid-20210607_210745_712053_67A7D864
|
||||
X-CRM114-Status: GOOD ( 26.99 )
|
||||
X-Spam-Score: -0.8 (/)
|
||||
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: Do not prevent writing to mtd partitions where a partition
|
||||
boundary sits on a minor erasesize boundary. This addresses a FIXME that
|
||||
has been present since the start of the linux git history: /* Doesn' [...]
|
||||
Content analysis details: (-0.8 points, 5.0 required)
|
||||
pts rule name description
|
||||
---- ----------------------
|
||||
--------------------------------------------------
|
||||
-0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at https://www.dnswl.org/,
|
||||
low trust [66.111.4.221 listed in list.dnswl.org]
|
||||
-0.0 SPF_PASS SPF: sender matches SPF record
|
||||
-0.0 SPF_HELO_PASS SPF: HELO matches SPF record
|
||||
0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3)
|
||||
[66.111.4.221 listed in wl.mailspike.net]
|
||||
-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
|
||||
0.0 RCVD_IN_MSPIKE_WL Mailspike good senders
|
||||
X-BeenThere: linux-mtd@lists.infradead.org
|
||||
X-Mailman-Version: 2.1.34
|
||||
Precedence: list
|
||||
List-Id: Linux MTD discussion mailing list <linux-mtd.lists.infradead.org>
|
||||
List-Unsubscribe: <http://lists.infradead.org/mailman/options/linux-mtd>,
|
||||
<mailto:linux-mtd-request@lists.infradead.org?subject=unsubscribe>
|
||||
List-Archive: <http://lists.infradead.org/pipermail/linux-mtd/>
|
||||
List-Post: <mailto:linux-mtd@lists.infradead.org>
|
||||
List-Help: <mailto:linux-mtd-request@lists.infradead.org?subject=help>
|
||||
List-Subscribe: <http://lists.infradead.org/mailman/listinfo/linux-mtd>,
|
||||
<mailto:linux-mtd-request@lists.infradead.org?subject=subscribe>
|
||||
Sender: "linux-mtd" <linux-mtd-bounces@lists.infradead.org>
|
||||
Errors-To: linux-mtd-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org
|
||||
|
||||
Do not prevent writing to mtd partitions where a partition boundary sits
|
||||
on a minor erasesize boundary.
|
||||
This addresses a FIXME that has been present since the start of the
|
||||
linux git history:
|
||||
/* Doesn't start on a boundary of major erase size */
|
||||
/* FIXME: Let it be writable if it is on a boundary of
|
||||
* _minor_ erase size though */
|
||||
|
||||
Allow a uniform erase region spi-nor device to be configured
|
||||
to use the non-uniform erase regions code path for an erase with:
|
||||
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
|
||||
|
||||
On supporting hardware (SECT_4K: majority of current SPI-NOR device)
|
||||
provide the facility for an erase to use the least number
|
||||
of SPI-NOR operations, as well as access to 4K erase without
|
||||
requiring CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
|
||||
|
||||
Introduce erasesize_minor to the mtd struct,
|
||||
the smallest erasesize supported by the device
|
||||
|
||||
On existing devices, this is useful where write support is wanted
|
||||
for data on a 4K partition, such as some u-boot-env partitions,
|
||||
or RouterBoot soft_config, while still netting the performance
|
||||
benefits of using 64K sectors
|
||||
|
||||
Performance:
|
||||
time mtd erase firmware
|
||||
OpenWrt 5.10 ramips MT7621 w25q128jv 0xfc0000 partition length
|
||||
|
||||
Without this patch
|
||||
MTD_SPI_NOR_USE_4K_SECTORS=y |n
|
||||
real 2m 11.66s |0m 50.86s
|
||||
user 0m 0.00s |0m 0.00s
|
||||
sys 1m 56.20s |0m 50.80s
|
||||
|
||||
With this patch
|
||||
MTD_SPI_NOR_USE_VARIABLE_ERASE=n|y |4K_SECTORS=y
|
||||
real 0m 51.68s |0m 50.85s |2m 12.89s
|
||||
user 0m 0.00s |0m 0.00s |0m 0.01s
|
||||
sys 0m 46.94s |0m 50.38s |2m 12.46s
|
||||
|
||||
Signed-off-by: John Thomson <git@johnthomson.fastmail.com.au>
|
||||
---
|
||||
Have not tested on variable erase regions device.
|
||||
|
||||
checkpatch does not like the printk(KERN_WARNING
|
||||
these should be changed separately beforehand?
|
||||
|
||||
Changes RFC -> v1:
|
||||
Fix uninitialized variable smatch warning
|
||||
Reported-by: kernel test robot <lkp@intel.com>
|
||||
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
|
||||
---
|
||||
drivers/mtd/mtdpart.c | 52 ++++++++++++++++++++++++++++---------
|
||||
drivers/mtd/spi-nor/Kconfig | 10 +++++++
|
||||
drivers/mtd/spi-nor/core.c | 10 +++++--
|
||||
include/linux/mtd/mtd.h | 2 ++
|
||||
4 files changed, 60 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
|
||||
index 665fd9020b76..fe7626b5020e 100644
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -38,10 +38,11 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
|
||||
struct mtd_info *master = mtd_get_master(parent);
|
||||
int wr_alignment = (parent->flags & MTD_NO_ERASE) ?
|
||||
master->writesize : master->erasesize;
|
||||
+ int wr_alignment_minor = 0;
|
||||
u64 parent_size = mtd_is_partition(parent) ?
|
||||
parent->part.size : parent->size;
|
||||
struct mtd_info *child;
|
||||
- u32 remainder;
|
||||
+ u32 remainder, remainder_minor;
|
||||
char *name;
|
||||
u64 tmp;
|
||||
|
||||
@@ -143,6 +144,7 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
|
||||
int i, max = parent->numeraseregions;
|
||||
u64 end = child->part.offset + child->part.size;
|
||||
struct mtd_erase_region_info *regions = parent->eraseregions;
|
||||
+ uint32_t erasesize_minor = child->erasesize;
|
||||
|
||||
/* Find the first erase regions which is part of this
|
||||
* partition. */
|
||||
@@ -153,15 +155,24 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
|
||||
if (i > 0)
|
||||
i--;
|
||||
|
||||
- /* Pick biggest erasesize */
|
||||
for (; i < max && regions[i].offset < end; i++) {
|
||||
+ /* Pick biggest erasesize */
|
||||
if (child->erasesize < regions[i].erasesize)
|
||||
child->erasesize = regions[i].erasesize;
|
||||
+ /* Pick smallest non-zero erasesize */
|
||||
+ if ((erasesize_minor > regions[i].erasesize) && (regions[i].erasesize > 0))
|
||||
+ erasesize_minor = regions[i].erasesize;
|
||||
}
|
||||
+
|
||||
+ if (erasesize_minor < child->erasesize)
|
||||
+ child->erasesize_minor = erasesize_minor;
|
||||
+
|
||||
BUG_ON(child->erasesize == 0);
|
||||
} else {
|
||||
/* Single erase size */
|
||||
child->erasesize = master->erasesize;
|
||||
+ if (master->erasesize_minor)
|
||||
+ child->erasesize_minor = master->erasesize_minor;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -169,26 +180,43 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
|
||||
* exposes several regions with different erasesize. Adjust
|
||||
* wr_alignment accordingly.
|
||||
*/
|
||||
- if (!(child->flags & MTD_NO_ERASE))
|
||||
+ if (!(child->flags & MTD_NO_ERASE)) {
|
||||
wr_alignment = child->erasesize;
|
||||
+ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE) && child->erasesize_minor)
|
||||
+ wr_alignment_minor = child->erasesize_minor;
|
||||
+ }
|
||||
|
||||
tmp = mtd_get_master_ofs(child, 0);
|
||||
remainder = do_div(tmp, wr_alignment);
|
||||
if ((child->flags & MTD_WRITEABLE) && remainder) {
|
||||
- /* Doesn't start on a boundary of major erase size */
|
||||
- /* FIXME: Let it be writable if it is on a boundary of
|
||||
- * _minor_ erase size though */
|
||||
- child->flags &= ~MTD_WRITEABLE;
|
||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
|
||||
- part->name);
|
||||
+ if (wr_alignment_minor) {
|
||||
+ tmp = mtd_get_master_ofs(child, 0);
|
||||
+ remainder_minor = do_div(tmp, wr_alignment_minor);
|
||||
+ if (remainder_minor == 0)
|
||||
+ child->erasesize = child->erasesize_minor;
|
||||
+ }
|
||||
+
|
||||
+ if ((!wr_alignment_minor) || (wr_alignment_minor && remainder_minor != 0)) {
|
||||
+ child->flags &= ~MTD_WRITEABLE;
|
||||
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
|
||||
+ part->name);
|
||||
+ }
|
||||
}
|
||||
|
||||
tmp = mtd_get_master_ofs(child, 0) + child->part.size;
|
||||
remainder = do_div(tmp, wr_alignment);
|
||||
if ((child->flags & MTD_WRITEABLE) && remainder) {
|
||||
- child->flags &= ~MTD_WRITEABLE;
|
||||
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
|
||||
- part->name);
|
||||
+ if (wr_alignment_minor) {
|
||||
+ tmp = mtd_get_master_ofs(child, 0) + child->part.size;
|
||||
+ remainder_minor = do_div(tmp, wr_alignment_minor);
|
||||
+ if (remainder_minor == 0)
|
||||
+ child->erasesize = child->erasesize_minor;
|
||||
+ }
|
||||
+ if ((!wr_alignment_minor) || (wr_alignment_minor && remainder_minor != 0)) {
|
||||
+ child->flags &= ~MTD_WRITEABLE;
|
||||
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
|
||||
+ part->name);
|
||||
+ }
|
||||
}
|
||||
|
||||
child->size = child->part.size;
|
||||
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
|
||||
index 24cd25de2b8b..09df9f1a8127 100644
|
||||
--- a/drivers/mtd/spi-nor/Kconfig
|
||||
+++ b/drivers/mtd/spi-nor/Kconfig
|
||||
@@ -10,6 +10,16 @@ menuconfig MTD_SPI_NOR
|
||||
|
||||
if MTD_SPI_NOR
|
||||
|
||||
+config MTD_SPI_NOR_USE_VARIABLE_ERASE
|
||||
+ bool "Disable uniform_erase to allow use of all hardware supported erasesizes"
|
||||
+ depends on !MTD_SPI_NOR_USE_4K_SECTORS
|
||||
+ default n
|
||||
+ help
|
||||
+ Allow mixed use of all hardware supported erasesizes,
|
||||
+ by forcing spi_nor to use the multiple eraseregions code path.
|
||||
+ For example: A 68K erase will use one 64K erase, and one 4K erase
|
||||
+ on supporting hardware.
|
||||
+
|
||||
config MTD_SPI_NOR_USE_4K_SECTORS
|
||||
bool "Use small 4096 B erase sectors"
|
||||
default y
|
||||
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
|
||||
index bd2c7717eb10..43d9b54e7edd 100644
|
||||
--- a/drivers/mtd/spi-nor/core.c
|
||||
+++ b/drivers/mtd/spi-nor/core.c
|
||||
@@ -1262,6 +1262,8 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
|
||||
|
||||
static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
|
||||
{
|
||||
+ if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE))
|
||||
+ return false;
|
||||
return !!nor->params->erase_map.uniform_erase_type;
|
||||
}
|
||||
|
||||
@@ -2381,6 +2383,7 @@ static int spi_nor_select_erase(struct spi_nor *nor)
|
||||
{
|
||||
struct spi_nor_erase_map *map = &nor->params->erase_map;
|
||||
const struct spi_nor_erase_type *erase = NULL;
|
||||
+ const struct spi_nor_erase_type *erase_minor = NULL;
|
||||
struct mtd_info *mtd = &nor->mtd;
|
||||
u32 wanted_size = nor->info->sector_size;
|
||||
int i;
|
||||
@@ -2413,8 +2416,9 @@ static int spi_nor_select_erase(struct spi_nor *nor)
|
||||
*/
|
||||
for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
|
||||
if (map->erase_type[i].size) {
|
||||
- erase = &map->erase_type[i];
|
||||
- break;
|
||||
+ if (!erase)
|
||||
+ erase = &map->erase_type[i];
|
||||
+ erase_minor = &map->erase_type[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2422,6 +2426,8 @@ static int spi_nor_select_erase(struct spi_nor *nor)
|
||||
return -EINVAL;
|
||||
|
||||
mtd->erasesize = erase->size;
|
||||
+ if (erase_minor && erase_minor->size < erase->size)
|
||||
+ mtd->erasesize_minor = erase_minor->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
|
||||
index a89955f3cbc8..33eafa27da50 100644
|
||||
--- a/include/linux/mtd/mtd.h
|
||||
+++ b/include/linux/mtd/mtd.h
|
||||
@@ -243,6 +243,8 @@ struct mtd_info {
|
||||
* information below if they desire
|
||||
*/
|
||||
uint32_t erasesize;
|
||||
+ /* "Minor" (smallest) erase size supported by the whole device */
|
||||
+ uint32_t erasesize_minor;
|
||||
/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
|
||||
* though individual bits can be cleared), in case of NAND flash it is
|
||||
* one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
|
||||
Binary file not shown.
@ -2,3 +2,4 @@ CONFIG_MIKROTIK=y
|
||||
CONFIG_MIKROTIK_RB_SYSFS=y
|
||||
CONFIG_MTD_ROUTERBOOT_PARTS=y
|
||||
CONFIG_MTD_SPLIT_MINOR_FW=y
|
||||
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
|
||||
|
||||
@ -33,13 +33,13 @@
|
||||
|
||||
dect {
|
||||
label = "dect";
|
||||
gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
|
||||
gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_PHONE>;
|
||||
};
|
||||
|
||||
wifi {
|
||||
label = "wifi";
|
||||
gpios = <&gpio 29 GPIO_ACTIVE_HIGH>;
|
||||
gpios = <&gpio 29 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RFKILL>;
|
||||
};
|
||||
};
|
||||
|
||||
@ -23,10 +23,9 @@ case "$FIRMWARE" in
|
||||
avm,fritz7360-v2)
|
||||
caldata_extract "urlader" 0x985 0x1000
|
||||
;;
|
||||
avm,fritz7412)
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x1e000 -e 0x207 -l 4096 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader")
|
||||
;;
|
||||
avm,fritz7412|\
|
||||
avm,fritz7430)
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x1e000 -e 0x207 -l 4096 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader") || \
|
||||
/usr/bin/fritz_cal_extract -i 1 -s 0x1e800 -e 0x207 -l 4096 -o /lib/firmware/$FIRMWARE $(find_mtd_chardev "urlader")
|
||||
;;
|
||||
bt,homehub-v5a)
|
||||
|
||||
@ -3,10 +3,13 @@
|
||||
#include "mt7622-rfb1.dts"
|
||||
/ {
|
||||
model = "MT7622_MT7531 RFB (UBI)";
|
||||
compatible = "mediatek,mt7622,ubi";
|
||||
compatible = "mediatek,mt7622-rfb1-ubi";
|
||||
};
|
||||
|
||||
&snand {
|
||||
mediatek,bmt-v2;
|
||||
mediatek,bmt-remap-range = <0x0 0x6c0000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
@ -35,22 +38,19 @@
|
||||
|
||||
factory: partition@1c0000 {
|
||||
label = "Factory";
|
||||
reg = <0x1c0000 0x0040000>;
|
||||
reg = <0x1c0000 0x0100000>;
|
||||
};
|
||||
|
||||
partition@200000 {
|
||||
label = "kernel";
|
||||
reg = <0x200000 0x400000>;
|
||||
reg = <0x2c0000 0x400000>;
|
||||
};
|
||||
|
||||
partition@600000 {
|
||||
partition@6c0000 {
|
||||
label = "ubi";
|
||||
reg = <0x600000 0x1C00000>;
|
||||
reg = <0x6c0000 0x6f00000>;
|
||||
};
|
||||
|
||||
partition@2200000 {
|
||||
label = "User_data";
|
||||
reg = <0x2200000 0x4000000>;
|
||||
};
|
||||
/delete-node/ partition@2200000;
|
||||
};
|
||||
};
|
||||
|
||||
@ -328,6 +328,10 @@
|
||||
pinctrl-0 = <&pcie_default>;
|
||||
status = "okay";
|
||||
|
||||
pcie@0,0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pcie@1,0 {
|
||||
status = "okay";
|
||||
};
|
||||
@ -337,6 +341,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
&pcie0_phy {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pcie1_phy {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@ -190,6 +190,7 @@ define Device/mediatek_mt7622-rfb1-ubi
|
||||
DEVICE_DTS := mt7622-rfb1-ubi
|
||||
DEVICE_DTS_DIR := ../dts
|
||||
DEVICE_PACKAGES := kmod-ata-ahci-mtk kmod-btmtkuart kmod-usb3
|
||||
BOARD_NAME := mediatek,mt7622-rfb1-ubi
|
||||
UBINIZE_OPTS := -E 5
|
||||
BLOCKSIZE := 128k
|
||||
PAGESIZE := 2048
|
||||
|
||||
@ -11,7 +11,8 @@ mediatek_setup_interfaces()
|
||||
bananapi,bpi-r64|\
|
||||
linksys,e8450|\
|
||||
linksys,e8450-ubi|\
|
||||
mediatek,mt7622-rfb1)
|
||||
mediatek,mt7622-rfb1|\
|
||||
mediatek,mt7622-rfb1-ubi)
|
||||
ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" wan
|
||||
;;
|
||||
buffalo,wsr-2533dhp2)
|
||||
|
||||
@ -34,8 +34,7 @@ platform_do_upgrade() {
|
||||
nand_do_upgrade "$1"
|
||||
fi
|
||||
;;
|
||||
linksys,e8450-ubi|\
|
||||
mediatek,mt7622,ubi)
|
||||
linksys,e8450-ubi)
|
||||
CI_KERNPART="fit"
|
||||
nand_do_upgrade "$1"
|
||||
;;
|
||||
@ -47,6 +46,7 @@ platform_do_upgrade() {
|
||||
fi
|
||||
default_do_upgrade "$1"
|
||||
;;
|
||||
mediatek,mt7622-rfb1-ubi|\
|
||||
totolink,a8000ru)
|
||||
nand_do_upgrade "$1"
|
||||
;;
|
||||
@ -68,6 +68,7 @@ platform_check_image() {
|
||||
buffalo,wsr-2533dhp2)
|
||||
buffalo_check_image "$board" "$magic" "$1" || return 1
|
||||
;;
|
||||
mediatek,mt7622-rfb1-ubi|\
|
||||
totolink,a8000ru)
|
||||
nand_do_platform_check "$board" "$1"
|
||||
;;
|
||||
|
||||
@ -1,871 +0,0 @@
|
||||
--- a/drivers/mtd/nand/Kconfig
|
||||
+++ b/drivers/mtd/nand/Kconfig
|
||||
@@ -15,6 +15,10 @@ config MTD_NAND_ECC
|
||||
bool
|
||||
depends on MTD_NAND_CORE
|
||||
|
||||
+config MTD_NAND_MTK_BMT
|
||||
+ bool "Support MediaTek NAND Bad-block Management Table"
|
||||
+ default n
|
||||
+
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
--- a/drivers/mtd/nand/Makefile
|
||||
+++ b/drivers/mtd/nand/Makefile
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
nandcore-objs := core.o bbt.o
|
||||
obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
|
||||
+obj-$(CONFIG_MTD_NAND_MTK_BMT) += mtk_bmt.o
|
||||
|
||||
obj-y += onenand/
|
||||
obj-y += raw/
|
||||
--- /dev/null
|
||||
+++ b/drivers/mtd/nand/mtk_bmt.c
|
||||
@@ -0,0 +1,788 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2017 MediaTek Inc.
|
||||
+ * Author: Xiangsheng Hou <xiangsheng.hou@mediatek.com>
|
||||
+ * Copyright (c) 2020 Felix Fietkau <nbd@nbd.name>
|
||||
+ *
|
||||
+ * 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.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/gfp.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/mtd/mtk_bmt.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/debugfs.h>
|
||||
+
|
||||
+#define MAIN_SIGNATURE_OFFSET 0
|
||||
+#define OOB_SIGNATURE_OFFSET 1
|
||||
+#define BBPOOL_RATIO 2
|
||||
+
|
||||
+#define BBT_LOG(fmt, ...) pr_debug("[BBT][%s|%d] "fmt"\n", __func__, __LINE__, ##__VA_ARGS__)
|
||||
+
|
||||
+/* Maximum 8k blocks */
|
||||
+#define BB_TABLE_MAX bmtd.table_size
|
||||
+#define BMT_TABLE_MAX (BB_TABLE_MAX * BBPOOL_RATIO / 100)
|
||||
+#define BMT_TBL_DEF_VAL 0x0
|
||||
+
|
||||
+/*
|
||||
+ * Burner Bad Block Table
|
||||
+ * --------- Only support SLC Nand Chips!!!!!!!!!!! ----------
|
||||
+ */
|
||||
+
|
||||
+struct bbbt {
|
||||
+ char signature[3];
|
||||
+ /* This version is used to distinguish the legacy and new algorithm */
|
||||
+#define BBMT_VERSION 2
|
||||
+ unsigned char version;
|
||||
+ /* Below 2 tables will be written in SLC */
|
||||
+ u16 bb_tbl[];
|
||||
+};
|
||||
+
|
||||
+struct bbmt {
|
||||
+ u16 block;
|
||||
+#define NO_MAPPED 0
|
||||
+#define NORMAL_MAPPED 1
|
||||
+#define BMT_MAPPED 2
|
||||
+ u16 mapped;
|
||||
+};
|
||||
+
|
||||
+static struct bmt_desc {
|
||||
+ struct mtd_info *mtd;
|
||||
+
|
||||
+ int (*_read_oob) (struct mtd_info *mtd, loff_t from,
|
||||
+ struct mtd_oob_ops *ops);
|
||||
+ int (*_write_oob) (struct mtd_info *mtd, loff_t to,
|
||||
+ struct mtd_oob_ops *ops);
|
||||
+ int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
|
||||
+ int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
|
||||
+ int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
|
||||
+
|
||||
+ struct bbbt *bbt;
|
||||
+
|
||||
+ struct dentry *debugfs_dir;
|
||||
+
|
||||
+ u32 table_size;
|
||||
+ u32 pg_size;
|
||||
+ u32 blk_size;
|
||||
+ u16 pg_shift;
|
||||
+ u16 blk_shift;
|
||||
+ /* bbt logical address */
|
||||
+ u16 pool_lba;
|
||||
+ /* bbt physical address */
|
||||
+ u16 pool_pba;
|
||||
+ /* Maximum count of bad blocks that the vendor guaranteed */
|
||||
+ u16 bb_max;
|
||||
+ /* Total blocks of the Nand Chip */
|
||||
+ u16 total_blks;
|
||||
+ /* The block(n) BMT is located at (bmt_tbl[n]) */
|
||||
+ u16 bmt_blk_idx;
|
||||
+ /* How many pages needs to store 'struct bbbt' */
|
||||
+ u32 bmt_pgs;
|
||||
+
|
||||
+ /* to compensate for driver level remapping */
|
||||
+ u8 oob_offset;
|
||||
+} bmtd = {0};
|
||||
+
|
||||
+static unsigned char *nand_bbt_buf;
|
||||
+static unsigned char *nand_data_buf;
|
||||
+
|
||||
+/* -------- Unit conversions -------- */
|
||||
+static inline u32 blk_pg(u16 block)
|
||||
+{
|
||||
+ return (u32)(block << (bmtd.blk_shift - bmtd.pg_shift));
|
||||
+}
|
||||
+
|
||||
+/* -------- Nand operations wrapper -------- */
|
||||
+static inline int
|
||||
+bbt_nand_read(u32 page, unsigned char *dat, int dat_len,
|
||||
+ unsigned char *fdm, int fdm_len)
|
||||
+{
|
||||
+ struct mtd_oob_ops ops = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = bmtd.oob_offset,
|
||||
+ .oobbuf = fdm,
|
||||
+ .ooblen = fdm_len,
|
||||
+ .datbuf = dat,
|
||||
+ .len = dat_len,
|
||||
+ };
|
||||
+
|
||||
+ return bmtd._read_oob(bmtd.mtd, page << bmtd.pg_shift, &ops);
|
||||
+}
|
||||
+
|
||||
+static inline int bbt_nand_erase(u16 block)
|
||||
+{
|
||||
+ struct mtd_info *mtd = bmtd.mtd;
|
||||
+ struct erase_info instr = {
|
||||
+ .addr = (loff_t)block << bmtd.blk_shift,
|
||||
+ .len = bmtd.blk_size,
|
||||
+ };
|
||||
+
|
||||
+ return bmtd._erase(mtd, &instr);
|
||||
+}
|
||||
+
|
||||
+/* -------- Bad Blocks Management -------- */
|
||||
+static inline struct bbmt *bmt_tbl(struct bbbt *bbbt)
|
||||
+{
|
||||
+ return (struct bbmt *)&bbbt->bb_tbl[bmtd.table_size];
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+read_bmt(u16 block, unsigned char *dat, unsigned char *fdm, int fdm_len)
|
||||
+{
|
||||
+ u32 len = bmtd.bmt_pgs << bmtd.pg_shift;
|
||||
+
|
||||
+ return bbt_nand_read(blk_pg(block), dat, len, fdm, fdm_len);
|
||||
+}
|
||||
+
|
||||
+static int write_bmt(u16 block, unsigned char *dat)
|
||||
+{
|
||||
+ struct mtd_oob_ops ops = {
|
||||
+ .mode = MTD_OPS_PLACE_OOB,
|
||||
+ .ooboffs = OOB_SIGNATURE_OFFSET + bmtd.oob_offset,
|
||||
+ .oobbuf = "bmt",
|
||||
+ .ooblen = 3,
|
||||
+ .datbuf = dat,
|
||||
+ .len = bmtd.bmt_pgs << bmtd.pg_shift,
|
||||
+ };
|
||||
+ loff_t addr = (loff_t)block << bmtd.blk_shift;
|
||||
+
|
||||
+ return bmtd._write_oob(bmtd.mtd, addr, &ops);
|
||||
+}
|
||||
+
|
||||
+static u16 find_valid_block(u16 block)
|
||||
+{
|
||||
+ u8 fdm[4];
|
||||
+ int ret;
|
||||
+ int loop = 0;
|
||||
+
|
||||
+retry:
|
||||
+ if (block >= bmtd.total_blks)
|
||||
+ return 0;
|
||||
+
|
||||
+ ret = bbt_nand_read(blk_pg(block), nand_data_buf, bmtd.pg_size,
|
||||
+ fdm, sizeof(fdm));
|
||||
+ /* Read the 1st byte of FDM to judge whether it's a bad
|
||||
+ * or not
|
||||
+ */
|
||||
+ if (ret || fdm[0] != 0xff) {
|
||||
+ pr_info("nand: found bad block 0x%x\n", block);
|
||||
+ if (loop >= bmtd.bb_max) {
|
||||
+ pr_info("nand: FATAL ERR: too many bad blocks!!\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ loop++;
|
||||
+ block++;
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ return block;
|
||||
+}
|
||||
+
|
||||
+/* Find out all bad blocks, and fill in the mapping table */
|
||||
+static int scan_bad_blocks(struct bbbt *bbt)
|
||||
+{
|
||||
+ int i;
|
||||
+ u16 block = 0;
|
||||
+
|
||||
+ /* First time download, the block0 MUST NOT be a bad block,
|
||||
+ * this is guaranteed by vendor
|
||||
+ */
|
||||
+ bbt->bb_tbl[0] = 0;
|
||||
+
|
||||
+ /*
|
||||
+ * Construct the mapping table of Normal data area(non-PMT/BMTPOOL)
|
||||
+ * G - Good block; B - Bad block
|
||||
+ * ---------------------------
|
||||
+ * physical |G|G|B|G|B|B|G|G|G|G|B|G|B|
|
||||
+ * ---------------------------
|
||||
+ * What bb_tbl[i] looks like:
|
||||
+ * physical block(i):
|
||||
+ * 0 1 2 3 4 5 6 7 8 9 a b c
|
||||
+ * mapped block(bb_tbl[i]):
|
||||
+ * 0 1 3 6 7 8 9 b ......
|
||||
+ * ATTENTION:
|
||||
+ * If new bad block ocurred(n), search bmt_tbl to find
|
||||
+ * a available block(x), and fill in the bb_tbl[n] = x;
|
||||
+ */
|
||||
+ for (i = 1; i < bmtd.pool_lba; i++) {
|
||||
+ bbt->bb_tbl[i] = find_valid_block(bbt->bb_tbl[i - 1] + 1);
|
||||
+ BBT_LOG("bb_tbl[0x%x] = 0x%x", i, bbt->bb_tbl[i]);
|
||||
+ if (bbt->bb_tbl[i] == 0)
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* Physical Block start Address of BMT pool */
|
||||
+ bmtd.pool_pba = bbt->bb_tbl[i - 1] + 1;
|
||||
+ if (bmtd.pool_pba >= bmtd.total_blks - 2) {
|
||||
+ pr_info("nand: FATAL ERR: Too many bad blocks!!\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ BBT_LOG("pool_pba=0x%x", bmtd.pool_pba);
|
||||
+ i = 0;
|
||||
+ block = bmtd.pool_pba;
|
||||
+ /*
|
||||
+ * The bmt table is used for runtime bad block mapping
|
||||
+ * G - Good block; B - Bad block
|
||||
+ * ---------------------------
|
||||
+ * physical |G|G|B|G|B|B|G|G|G|G|B|G|B|
|
||||
+ * ---------------------------
|
||||
+ * block: 0 1 2 3 4 5 6 7 8 9 a b c
|
||||
+ * What bmt_tbl[i] looks like in initial state:
|
||||
+ * i:
|
||||
+ * 0 1 2 3 4 5 6 7
|
||||
+ * bmt_tbl[i].block:
|
||||
+ * 0 1 3 6 7 8 9 b
|
||||
+ * bmt_tbl[i].mapped:
|
||||
+ * N N N N N N N B
|
||||
+ * N - Not mapped(Available)
|
||||
+ * M - Mapped
|
||||
+ * B - BMT
|
||||
+ * ATTENTION:
|
||||
+ * BMT always in the last valid block in pool
|
||||
+ */
|
||||
+ while ((block = find_valid_block(block)) != 0) {
|
||||
+ bmt_tbl(bbt)[i].block = block;
|
||||
+ bmt_tbl(bbt)[i].mapped = NO_MAPPED;
|
||||
+ BBT_LOG("bmt_tbl[%d].block = 0x%x", i, block);
|
||||
+ block++;
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ /* i - How many available blocks in pool, which is the length of bmt_tbl[]
|
||||
+ * bmtd.bmt_blk_idx - bmt_tbl[bmtd.bmt_blk_idx].block => the BMT block
|
||||
+ */
|
||||
+ bmtd.bmt_blk_idx = i - 1;
|
||||
+ bmt_tbl(bbt)[bmtd.bmt_blk_idx].mapped = BMT_MAPPED;
|
||||
+
|
||||
+ if (i < 1) {
|
||||
+ pr_info("nand: FATAL ERR: no space to store BMT!!\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ pr_info("[BBT] %d available blocks in BMT pool\n", i);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static bool is_valid_bmt(unsigned char *buf, unsigned char *fdm)
|
||||
+{
|
||||
+ struct bbbt *bbt = (struct bbbt *)buf;
|
||||
+ u8 *sig = (u8*)bbt->signature + MAIN_SIGNATURE_OFFSET;
|
||||
+
|
||||
+
|
||||
+ if (memcmp(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3) == 0 &&
|
||||
+ memcmp(fdm + OOB_SIGNATURE_OFFSET, "bmt", 3) == 0) {
|
||||
+ if (bbt->version == BBMT_VERSION)
|
||||
+ return true;
|
||||
+ }
|
||||
+ BBT_LOG("[BBT] BMT Version not match,upgrage preloader and uboot please! sig=%02x%02x%02x, fdm=%02x%02x%02x",
|
||||
+ sig[0], sig[1], sig[2],
|
||||
+ fdm[1], fdm[2], fdm[3]);
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static u16 get_bmt_index(struct bbmt *bmt)
|
||||
+{
|
||||
+ int i = 0;
|
||||
+
|
||||
+ while (bmt[i].block != BMT_TBL_DEF_VAL) {
|
||||
+ if (bmt[i].mapped == BMT_MAPPED)
|
||||
+ return i;
|
||||
+ i++;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct bbbt *scan_bmt(u16 block)
|
||||
+{
|
||||
+ u8 fdm[4];
|
||||
+
|
||||
+ if (block < bmtd.pool_lba)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (read_bmt(block, nand_bbt_buf, fdm, sizeof(fdm)))
|
||||
+ return scan_bmt(block - 1);
|
||||
+
|
||||
+ if (is_valid_bmt(nand_bbt_buf, fdm)) {
|
||||
+ bmtd.bmt_blk_idx = get_bmt_index(bmt_tbl((struct bbbt *)nand_bbt_buf));
|
||||
+ if (bmtd.bmt_blk_idx == 0) {
|
||||
+ pr_info("[BBT] FATAL ERR: bmt block index is wrong!\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ pr_info("[BBT] BMT.v2 is found at 0x%x\n", block);
|
||||
+ return (struct bbbt *)nand_bbt_buf;
|
||||
+ } else
|
||||
+ return scan_bmt(block - 1);
|
||||
+}
|
||||
+
|
||||
+/* Write the Burner Bad Block Table to Nand Flash
|
||||
+ * n - write BMT to bmt_tbl[n]
|
||||
+ */
|
||||
+static u16 upload_bmt(struct bbbt *bbt, int n)
|
||||
+{
|
||||
+ u16 block;
|
||||
+
|
||||
+retry:
|
||||
+ if (n < 0 || bmt_tbl(bbt)[n].mapped == NORMAL_MAPPED) {
|
||||
+ pr_info("nand: FATAL ERR: no space to store BMT!\n");
|
||||
+ return (u16)-1;
|
||||
+ }
|
||||
+
|
||||
+ block = bmt_tbl(bbt)[n].block;
|
||||
+ BBT_LOG("n = 0x%x, block = 0x%x", n, block);
|
||||
+ if (bbt_nand_erase(block)) {
|
||||
+ bmt_tbl(bbt)[n].block = 0;
|
||||
+ /* erase failed, try the previous block: bmt_tbl[n - 1].block */
|
||||
+ n--;
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ /* The signature offset is fixed set to 0,
|
||||
+ * oob signature offset is fixed set to 1
|
||||
+ */
|
||||
+ memcpy(bbt->signature + MAIN_SIGNATURE_OFFSET, "BMT", 3);
|
||||
+ bbt->version = BBMT_VERSION;
|
||||
+
|
||||
+ if (write_bmt(block, (unsigned char *)bbt)) {
|
||||
+ bmt_tbl(bbt)[n].block = 0;
|
||||
+
|
||||
+ /* write failed, try the previous block in bmt_tbl[n - 1] */
|
||||
+ n--;
|
||||
+ goto retry;
|
||||
+ }
|
||||
+
|
||||
+ /* Return the current index(n) of BMT pool (bmt_tbl[n]) */
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+static u16 find_valid_block_in_pool(struct bbbt *bbt)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ if (bmtd.bmt_blk_idx == 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ for (i = 0; i < bmtd.bmt_blk_idx; i++) {
|
||||
+ if (bmt_tbl(bbt)[i].block != 0 && bmt_tbl(bbt)[i].mapped == NO_MAPPED) {
|
||||
+ bmt_tbl(bbt)[i].mapped = NORMAL_MAPPED;
|
||||
+ return bmt_tbl(bbt)[i].block;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+error:
|
||||
+ pr_info("nand: FATAL ERR: BMT pool is run out!\n");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* We met a bad block, mark it as bad and map it to a valid block in pool,
|
||||
+ * if it's a write failure, we need to write the data to mapped block
|
||||
+ */
|
||||
+static bool update_bmt(u16 block)
|
||||
+{
|
||||
+ u16 mapped_blk;
|
||||
+ struct bbbt *bbt;
|
||||
+
|
||||
+ bbt = bmtd.bbt;
|
||||
+ mapped_blk = find_valid_block_in_pool(bbt);
|
||||
+ if (mapped_blk == 0)
|
||||
+ return false;
|
||||
+
|
||||
+ /* Map new bad block to available block in pool */
|
||||
+ bbt->bb_tbl[block] = mapped_blk;
|
||||
+ bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+u16 get_mapping_block_index(int block)
|
||||
+{
|
||||
+ int mapping_block;
|
||||
+
|
||||
+ if (block < bmtd.pool_lba)
|
||||
+ mapping_block = bmtd.bbt->bb_tbl[block];
|
||||
+ else
|
||||
+ mapping_block = block;
|
||||
+ BBT_LOG("0x%x mapped to 0x%x", block, mapping_block);
|
||||
+
|
||||
+ return mapping_block;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mtk_bmt_read(struct mtd_info *mtd, loff_t from,
|
||||
+ struct mtd_oob_ops *ops)
|
||||
+{
|
||||
+ struct mtd_oob_ops cur_ops = *ops;
|
||||
+ int retry_count = 0;
|
||||
+ loff_t cur_from;
|
||||
+ int ret;
|
||||
+
|
||||
+ ops->retlen = 0;
|
||||
+ ops->oobretlen = 0;
|
||||
+
|
||||
+ while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) {
|
||||
+ u32 offset = from & (bmtd.blk_size - 1);
|
||||
+ u32 block = from >> bmtd.blk_shift;
|
||||
+ u32 cur_block;
|
||||
+
|
||||
+ cur_block = get_mapping_block_index(block);
|
||||
+ cur_from = ((loff_t)cur_block << bmtd.blk_shift) + offset;
|
||||
+
|
||||
+ cur_ops.oobretlen = 0;
|
||||
+ cur_ops.retlen = 0;
|
||||
+ cur_ops.len = min_t(u32, mtd->erasesize - offset,
|
||||
+ ops->len - ops->retlen);
|
||||
+ ret = bmtd._read_oob(mtd, cur_from, &cur_ops);
|
||||
+ if (ret < 0) {
|
||||
+ update_bmt(block);
|
||||
+ if (retry_count++ < 10)
|
||||
+ continue;
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ops->retlen += cur_ops.retlen;
|
||||
+ ops->oobretlen += cur_ops.oobretlen;
|
||||
+
|
||||
+ cur_ops.ooboffs = 0;
|
||||
+ cur_ops.datbuf += cur_ops.retlen;
|
||||
+ cur_ops.oobbuf += cur_ops.oobretlen;
|
||||
+ cur_ops.ooblen -= cur_ops.oobretlen;
|
||||
+
|
||||
+ if (!cur_ops.len)
|
||||
+ cur_ops.len = mtd->erasesize - offset;
|
||||
+
|
||||
+ from += cur_ops.len;
|
||||
+ retry_count = 0;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mtk_bmt_write(struct mtd_info *mtd, loff_t to,
|
||||
+ struct mtd_oob_ops *ops)
|
||||
+{
|
||||
+ struct mtd_oob_ops cur_ops = *ops;
|
||||
+ int retry_count = 0;
|
||||
+ loff_t cur_to;
|
||||
+ int ret;
|
||||
+
|
||||
+ ops->retlen = 0;
|
||||
+ ops->oobretlen = 0;
|
||||
+
|
||||
+ while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) {
|
||||
+ u32 offset = to & (bmtd.blk_size - 1);
|
||||
+ u32 block = to >> bmtd.blk_shift;
|
||||
+ u32 cur_block;
|
||||
+
|
||||
+ cur_block = get_mapping_block_index(block);
|
||||
+ cur_to = ((loff_t)cur_block << bmtd.blk_shift) + offset;
|
||||
+
|
||||
+ cur_ops.oobretlen = 0;
|
||||
+ cur_ops.retlen = 0;
|
||||
+ cur_ops.len = min_t(u32, bmtd.blk_size - offset,
|
||||
+ ops->len - ops->retlen);
|
||||
+ ret = bmtd._write_oob(mtd, cur_to, &cur_ops);
|
||||
+ if (ret < 0) {
|
||||
+ update_bmt(block);
|
||||
+ if (retry_count++ < 10)
|
||||
+ continue;
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ops->retlen += cur_ops.retlen;
|
||||
+ ops->oobretlen += cur_ops.oobretlen;
|
||||
+
|
||||
+ cur_ops.ooboffs = 0;
|
||||
+ cur_ops.datbuf += cur_ops.retlen;
|
||||
+ cur_ops.oobbuf += cur_ops.oobretlen;
|
||||
+ cur_ops.ooblen -= cur_ops.oobretlen;
|
||||
+
|
||||
+ if (!cur_ops.len)
|
||||
+ cur_ops.len = mtd->erasesize - offset;
|
||||
+
|
||||
+ to += cur_ops.len;
|
||||
+ retry_count = 0;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mtk_bmt_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
+{
|
||||
+ struct erase_info mapped_instr = {
|
||||
+ .len = bmtd.blk_size,
|
||||
+ };
|
||||
+ int retry_count = 0;
|
||||
+ u64 start_addr, end_addr;
|
||||
+ int ret;
|
||||
+ u16 orig_block, block;
|
||||
+
|
||||
+ start_addr = instr->addr & (~mtd->erasesize_mask);
|
||||
+ end_addr = instr->addr + instr->len;
|
||||
+
|
||||
+ while (start_addr < end_addr) {
|
||||
+ orig_block = start_addr >> bmtd.blk_shift;
|
||||
+ block = get_mapping_block_index(orig_block);
|
||||
+ mapped_instr.addr = (loff_t)block << bmtd.blk_shift;
|
||||
+ ret = bmtd._erase(mtd, &mapped_instr);
|
||||
+ if (ret) {
|
||||
+ update_bmt(orig_block);
|
||||
+ if (retry_count++ < 10)
|
||||
+ continue;
|
||||
+ instr->fail_addr = start_addr;
|
||||
+ break;
|
||||
+ }
|
||||
+ start_addr += mtd->erasesize;
|
||||
+ retry_count = 0;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+static int
|
||||
+mtk_bmt_block_isbad(struct mtd_info *mtd, loff_t ofs)
|
||||
+{
|
||||
+ int retry_count = 0;
|
||||
+ u16 orig_block = ofs >> bmtd.blk_shift;
|
||||
+ u16 block;
|
||||
+ int ret;
|
||||
+
|
||||
+retry:
|
||||
+ block = get_mapping_block_index(orig_block);
|
||||
+ ret = bmtd._block_isbad(mtd, (loff_t)block << bmtd.blk_shift);
|
||||
+ if (ret) {
|
||||
+ update_bmt(orig_block);
|
||||
+ if (retry_count++ < 10)
|
||||
+ goto retry;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mtk_bmt_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
||||
+{
|
||||
+ u16 orig_block = ofs >> bmtd.blk_shift;
|
||||
+ u16 block = get_mapping_block_index(orig_block);
|
||||
+ update_bmt(orig_block);
|
||||
+ return bmtd._block_markbad(mtd, (loff_t)block << bmtd.blk_shift);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+mtk_bmt_replace_ops(struct mtd_info *mtd)
|
||||
+{
|
||||
+ bmtd._read_oob = mtd->_read_oob;
|
||||
+ bmtd._write_oob = mtd->_write_oob;
|
||||
+ bmtd._erase = mtd->_erase;
|
||||
+ bmtd._block_isbad = mtd->_block_isbad;
|
||||
+ bmtd._block_markbad = mtd->_block_markbad;
|
||||
+
|
||||
+ mtd->_read_oob = mtk_bmt_read;
|
||||
+ mtd->_write_oob = mtk_bmt_write;
|
||||
+ mtd->_erase = mtk_bmt_mtd_erase;
|
||||
+ mtd->_block_isbad = mtk_bmt_block_isbad;
|
||||
+ mtd->_block_markbad = mtk_bmt_block_markbad;
|
||||
+}
|
||||
+
|
||||
+static int mtk_bmt_debug_mark_good(void *data, u64 val)
|
||||
+{
|
||||
+ u32 block = val >> bmtd.blk_shift;
|
||||
+
|
||||
+ bmtd.bbt->bb_tbl[block] = block;
|
||||
+ bmtd.bmt_blk_idx = upload_bmt(bmtd.bbt, bmtd.bmt_blk_idx);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mtk_bmt_debug_mark_bad(void *data, u64 val)
|
||||
+{
|
||||
+ u32 block = val >> bmtd.blk_shift;
|
||||
+
|
||||
+ update_bmt(block);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_good, NULL, mtk_bmt_debug_mark_good, "%llu\n");
|
||||
+DEFINE_DEBUGFS_ATTRIBUTE(fops_mark_bad, NULL, mtk_bmt_debug_mark_bad, "%llu\n");
|
||||
+
|
||||
+static void
|
||||
+mtk_bmt_add_debugfs(void)
|
||||
+{
|
||||
+ struct dentry *dir;
|
||||
+
|
||||
+ dir = bmtd.debugfs_dir = debugfs_create_dir("mtk-bmt", NULL);
|
||||
+ if (!dir)
|
||||
+ return;
|
||||
+
|
||||
+ debugfs_create_file_unsafe("mark_good", S_IWUSR, dir, NULL, &fops_mark_good);
|
||||
+ debugfs_create_file_unsafe("mark_bad", S_IWUSR, dir, NULL, &fops_mark_bad);
|
||||
+}
|
||||
+
|
||||
+void mtk_bmt_detach(struct mtd_info *mtd)
|
||||
+{
|
||||
+ if (bmtd.mtd != mtd)
|
||||
+ return;
|
||||
+
|
||||
+ if (bmtd.debugfs_dir)
|
||||
+ debugfs_remove_recursive(bmtd.debugfs_dir);
|
||||
+ bmtd.debugfs_dir = NULL;
|
||||
+
|
||||
+ kfree(nand_bbt_buf);
|
||||
+ kfree(nand_data_buf);
|
||||
+
|
||||
+ mtd->_read_oob = bmtd._read_oob;
|
||||
+ mtd->_write_oob = bmtd._write_oob;
|
||||
+ mtd->_erase = bmtd._erase;
|
||||
+ mtd->_block_isbad = bmtd._block_isbad;
|
||||
+ mtd->_block_markbad = bmtd._block_markbad;
|
||||
+ mtd->size = bmtd.total_blks << bmtd.blk_shift;
|
||||
+
|
||||
+ memset(&bmtd, 0, sizeof(bmtd));
|
||||
+}
|
||||
+
|
||||
+/* total_blocks - The total count of blocks that the Nand Chip has */
|
||||
+int mtk_bmt_attach(struct mtd_info *mtd)
|
||||
+{
|
||||
+ struct device_node *np;
|
||||
+ struct bbbt *bbt;
|
||||
+ u32 bufsz;
|
||||
+ u32 block;
|
||||
+ u16 total_blocks, pmt_block;
|
||||
+ int ret = 0;
|
||||
+ u32 bmt_pool_size, bmt_table_size;
|
||||
+
|
||||
+ if (bmtd.mtd)
|
||||
+ return -ENOSPC;
|
||||
+
|
||||
+ np = mtd_get_of_node(mtd);
|
||||
+ if (!np)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!of_property_read_bool(np, "mediatek,bmt-v2"))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (of_property_read_u32(np, "mediatek,bmt-pool-size",
|
||||
+ &bmt_pool_size) != 0)
|
||||
+ bmt_pool_size = 80;
|
||||
+
|
||||
+ if (of_property_read_u8(np, "mediatek,bmt-oob-offset",
|
||||
+ &bmtd.oob_offset) != 0)
|
||||
+ bmtd.oob_offset = 0;
|
||||
+
|
||||
+ if (of_property_read_u32(np, "mediatek,bmt-table-size",
|
||||
+ &bmt_table_size) != 0)
|
||||
+ bmt_table_size = 0x2000U;
|
||||
+
|
||||
+ bmtd.mtd = mtd;
|
||||
+ mtk_bmt_replace_ops(mtd);
|
||||
+
|
||||
+ bmtd.table_size = bmt_table_size;
|
||||
+ bmtd.blk_size = mtd->erasesize;
|
||||
+ bmtd.blk_shift = ffs(bmtd.blk_size) - 1;
|
||||
+ bmtd.pg_size = mtd->writesize;
|
||||
+ bmtd.pg_shift = ffs(bmtd.pg_size) - 1;
|
||||
+ total_blocks = mtd->size >> bmtd.blk_shift;
|
||||
+ pmt_block = total_blocks - bmt_pool_size - 2;
|
||||
+
|
||||
+ mtd->size = pmt_block << bmtd.blk_shift;
|
||||
+
|
||||
+ /*
|
||||
+ * ---------------------------------------
|
||||
+ * | PMT(2blks) | BMT POOL(totalblks * 2%) |
|
||||
+ * ---------------------------------------
|
||||
+ * ^ ^
|
||||
+ * | |
|
||||
+ * pmt_block pmt_block + 2blocks(pool_lba)
|
||||
+ *
|
||||
+ * ATTETION!!!!!!
|
||||
+ * The blocks ahead of the boundary block are stored in bb_tbl
|
||||
+ * and blocks behind are stored in bmt_tbl
|
||||
+ */
|
||||
+
|
||||
+ bmtd.pool_lba = (u16)(pmt_block + 2);
|
||||
+ bmtd.total_blks = total_blocks;
|
||||
+ bmtd.bb_max = bmtd.total_blks * BBPOOL_RATIO / 100;
|
||||
+
|
||||
+ /* 3 buffers we need */
|
||||
+ bufsz = round_up(sizeof(struct bbbt) +
|
||||
+ bmt_table_size * sizeof(struct bbmt), bmtd.pg_size);
|
||||
+ bmtd.bmt_pgs = bufsz >> bmtd.pg_shift;
|
||||
+
|
||||
+ nand_bbt_buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
+ nand_data_buf = kzalloc(bmtd.pg_size, GFP_KERNEL);
|
||||
+
|
||||
+ if (!nand_bbt_buf || !nand_data_buf) {
|
||||
+ pr_info("nand: FATAL ERR: allocate buffer failed!\n");
|
||||
+ ret = -1;
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ memset(nand_bbt_buf, 0xff, bufsz);
|
||||
+ memset(nand_data_buf, 0xff, bmtd.pg_size);
|
||||
+
|
||||
+ BBT_LOG("bbtbuf=0x%p(0x%x) dat=0x%p(0x%x)",
|
||||
+ nand_bbt_buf, bufsz, nand_data_buf, bmtd.pg_size);
|
||||
+ BBT_LOG("pool_lba=0x%x total_blks=0x%x bb_max=0x%x",
|
||||
+ bmtd.pool_lba, bmtd.total_blks, bmtd.bb_max);
|
||||
+
|
||||
+ /* Scanning start from the first page of the last block
|
||||
+ * of whole flash
|
||||
+ */
|
||||
+ bbt = scan_bmt(bmtd.total_blks - 1);
|
||||
+ if (!bbt) {
|
||||
+ /* BMT not found */
|
||||
+ if (bmtd.total_blks > BB_TABLE_MAX + BMT_TABLE_MAX) {
|
||||
+ pr_info("nand: FATAL: Too many blocks, can not support!\n");
|
||||
+ ret = -1;
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ bbt = (struct bbbt *)nand_bbt_buf;
|
||||
+ memset(bmt_tbl(bbt), BMT_TBL_DEF_VAL, bmtd.table_size * sizeof(struct bbmt));
|
||||
+
|
||||
+ if (scan_bad_blocks(bbt)) {
|
||||
+ ret = -1;
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ /* BMT always in the last valid block in pool */
|
||||
+ bmtd.bmt_blk_idx = upload_bmt(bbt, bmtd.bmt_blk_idx);
|
||||
+ block = bmt_tbl(bbt)[bmtd.bmt_blk_idx].block;
|
||||
+ pr_notice("[BBT] BMT.v2 is written into PBA:0x%x\n", block);
|
||||
+
|
||||
+ if (bmtd.bmt_blk_idx == 0)
|
||||
+ pr_info("nand: Warning: no available block in BMT pool!\n");
|
||||
+ else if (bmtd.bmt_blk_idx == (u16)-1) {
|
||||
+ ret = -1;
|
||||
+ goto error;
|
||||
+ }
|
||||
+ }
|
||||
+ mtk_bmt_add_debugfs();
|
||||
+
|
||||
+ bmtd.bbt = bbt;
|
||||
+ return 0;
|
||||
+
|
||||
+error:
|
||||
+ mtk_bmt_detach(mtd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Xiangsheng Hou <xiangsheng.hou@mediatek.com>, Felix Fietkau <nbd@nbd.name>");
|
||||
+MODULE_DESCRIPTION("Bad Block mapping management v2 for MediaTek NAND Flash Driver");
|
||||
+
|
||||
--- /dev/null
|
||||
+++ b/include/linux/mtd/mtk_bmt.h
|
||||
@@ -0,0 +1,18 @@
|
||||
+#ifndef __MTK_BMT_H
|
||||
+#define __MTK_BMT_H
|
||||
+
|
||||
+#ifdef CONFIG_MTD_NAND_MTK_BMT
|
||||
+int mtk_bmt_attach(struct mtd_info *mtd);
|
||||
+void mtk_bmt_detach(struct mtd_info *mtd);
|
||||
+#else
|
||||
+static inline int mtk_bmt_attach(struct mtd_info *mtd)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline void mtk_bmt_detach(struct mtd_info *mtd)
|
||||
+{
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--- a/drivers/mtd/mtk-snand/mtk-snand-mtd.c
|
||||
+++ b/drivers/mtd/mtk-snand/mtk-snand-mtd.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/mtk_bmt.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
@@ -612,6 +613,8 @@ static int mtk_snand_probe(struct platfo
|
||||
mtd->_block_isbad = mtk_snand_mtd_block_isbad;
|
||||
mtd->_block_markbad = mtk_snand_mtd_block_markbad;
|
||||
|
||||
+ mtk_bmt_attach(mtd);
|
||||
+
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(msm->pdev.dev, "failed to register mtd partition\n");
|
||||
@@ -623,6 +626,7 @@ static int mtk_snand_probe(struct platfo
|
||||
return 0;
|
||||
|
||||
errout4:
|
||||
+ mtk_bmt_detach(mtd);
|
||||
devm_kfree(msm->pdev.dev, msm->page_cache);
|
||||
|
||||
errout3:
|
||||
@@ -650,6 +654,8 @@ static int mtk_snand_remove(struct platf
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ mtk_bmt_detach(mtd);
|
||||
+
|
||||
mtk_snand_cleanup(msm->snf);
|
||||
|
||||
if (msm->irq >= 0)
|
||||
@ -0,0 +1,36 @@
|
||||
--- a/drivers/mtd/mtk-snand/mtk-snand-mtd.c
|
||||
+++ b/drivers/mtd/mtk-snand/mtk-snand-mtd.c
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/mtk_bmt.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
@@ -612,6 +613,8 @@ static int mtk_snand_probe(struct platfo
|
||||
mtd->_block_isbad = mtk_snand_mtd_block_isbad;
|
||||
mtd->_block_markbad = mtk_snand_mtd_block_markbad;
|
||||
|
||||
+ mtk_bmt_attach(mtd);
|
||||
+
|
||||
ret = mtd_device_register(mtd, NULL, 0);
|
||||
if (ret) {
|
||||
dev_err(msm->pdev.dev, "failed to register mtd partition\n");
|
||||
@@ -623,6 +626,7 @@ static int mtk_snand_probe(struct platfo
|
||||
return 0;
|
||||
|
||||
errout4:
|
||||
+ mtk_bmt_detach(mtd);
|
||||
devm_kfree(msm->pdev.dev, msm->page_cache);
|
||||
|
||||
errout3:
|
||||
@@ -650,6 +654,8 @@ static int mtk_snand_remove(struct platf
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+ mtk_bmt_detach(mtd);
|
||||
+
|
||||
mtk_snand_cleanup(msm->snf);
|
||||
|
||||
if (msm->irq >= 0)
|
||||
@ -76,6 +76,11 @@
|
||||
&nand {
|
||||
status = "okay";
|
||||
|
||||
mediatek,bbt;
|
||||
mediatek,bmt-remap-range =
|
||||
<0x180000 0x580000>,
|
||||
<0x2980000 0x2d80000>;
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
|
||||
@ -37,7 +37,6 @@
|
||||
partition@0 {
|
||||
label = "RouterBoot";
|
||||
reg = <0x0 0x40000>;
|
||||
read-only;
|
||||
compatible = "mikrotik,routerboot-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
@ -154,10 +154,12 @@ CONFIG_MTD_NAND_CORE=y
|
||||
CONFIG_MTD_NAND_ECC=y
|
||||
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
|
||||
CONFIG_MTD_NAND_MT7621=y
|
||||
CONFIG_MTD_NAND_MTK_BMT=y
|
||||
CONFIG_MTD_PHYSMAP=y
|
||||
CONFIG_MTD_RAW_NAND=y
|
||||
CONFIG_MTD_ROUTERBOOT_PARTS=y
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
|
||||
CONFIG_MTD_SPLIT_FIT_FW=y
|
||||
CONFIG_MTD_SPLIT_MINOR_FW=y
|
||||
CONFIG_MTD_SPLIT_SEAMA_FW=y
|
||||
|
||||
@ -1022,7 +1022,7 @@ Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
|
||||
+ vall |= (u32)oobptr[j] << (j * 8);
|
||||
+
|
||||
+ for (j = 0; j < 4; j++)
|
||||
+ valm |= (u32)oobptr[j + 4] << ((j - 4) * 8);
|
||||
+ valm |= (u32)oobptr[j + 4] << (j * 8);
|
||||
+
|
||||
+ nfi_write32(nfc, NFI_FDML(i), vall);
|
||||
+ nfi_write32(nfc, NFI_FDMM(i), valm);
|
||||
|
||||
@ -11,9 +11,9 @@ PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL=$(PROJECT_GIT)/project/firmware-utils.git
|
||||
PKG_SOURCE_DATE:=2021-12-02
|
||||
PKG_SOURCE_VERSION:=56e8e19151743c923f48604c457850cf8eb52076
|
||||
PKG_MIRROR_HASH:=91f1bac08af2d856e93e651dc7c1ce6745f0b32b6fe4fb1917660494d7518057
|
||||
PKG_SOURCE_DATE:=2022-01-14
|
||||
PKG_SOURCE_VERSION:=84dbf8ee49f522d3a4528763c9473cf3dd7c8c52
|
||||
PKG_MIRROR_HASH:=aabf70dbc155d10175ee3b25f375953bef31bf7e25a2391fda8687aa93ea79e6
|
||||
|
||||
include $(INCLUDE_DIR)/host-build.mk
|
||||
include $(INCLUDE_DIR)/cmake.mk
|
||||
|
||||
Loading…
Reference in New Issue
Block a user