summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-04-29 14:49:24 -0600
committerTom Rini <[email protected]>2026-04-29 17:09:13 -0600
commit9d3bc111efe1c600a1475bbdfb6da6269e02c5c2 (patch)
tree9b594932d142f5f8e136c8dd85ede0d510de7b78
parent6211462c922f3a40ca0764303809771c23a7d701 (diff)
parenta97c82bfdf52aab727ecb4ce3a81ef585e4c55d3 (diff)
Merge tag 'mediatek-for-master-2026-04-29' of https://source.denx.de/u-boot/custodians/u-boot-mediatek
* MMC fixes for Genio 520/720 (mt8189) * SPI NOR Flash controller fixes * SPI NOR Flash support for Genio 520/720 * PMIC controller fixes * PMIC support for Genio 1200 (mt8195) * Drop CONFIG_IDENT_STRING to be consistent across the platform * Remove empty header on mt7622
-rw-r--r--arch/arm/dts/mt8189.dtsi17
-rw-r--r--arch/arm/dts/mt8371-genio-common.dtsi31
-rw-r--r--arch/arm/mach-mediatek/Kconfig1
-rw-r--r--board/mediatek/mt7622/MAINTAINERS1
-rw-r--r--configs/mt8189.config6
-rw-r--r--configs/mt8365_evk_defconfig1
-rw-r--r--configs/mt8370_genio_510_evk_defconfig1
-rw-r--r--configs/mt8390_genio_700_evk_defconfig1
-rw-r--r--configs/mt8395_genio_1200_evk_defconfig1
-rw-r--r--configs/mt8395_genio_1200_evk_ufs_defconfig1
-rw-r--r--drivers/mmc/mtk-sd.c4
-rw-r--r--drivers/power/pmic/mtk-pwrap.c118
-rw-r--r--drivers/spi/mtk_snor.c197
-rw-r--r--include/configs/mt7622.h12
14 files changed, 247 insertions, 145 deletions
diff --git a/arch/arm/dts/mt8189.dtsi b/arch/arm/dts/mt8189.dtsi
index e550745ac5d..891d3249ecd 100644
--- a/arch/arm/dts/mt8189.dtsi
+++ b/arch/arm/dts/mt8189.dtsi
@@ -181,6 +181,23 @@
status = "disabled";
};
+ nor_flash: spi@11018000 {
+ compatible = "mediatek,mt8189-nor","mediatek,mt8186-nor";
+ reg = <0 0x11018000 0 0x1000>;
+ clocks = <&topckgen_clk CLK_TOP_SFLASH_SEL>,
+ <&pericfg_ao_clk CLK_PERAO_SFLASH>,
+ <&pericfg_ao_clk CLK_PERAO_SFLASH_F>,
+ <&pericfg_ao_clk CLK_PERAO_SFLASH_H>,
+ <&pericfg_ao_clk CLK_PERAO_SFLASH_P>;
+ clock-names = "spi", "sf", "axi_f", "axi_h", "axi_p";
+ assigned-clocks = <&topckgen_clk CLK_TOP_SFLASH_SEL>;
+ assigned-clock-parents = <&topckgen_clk CLK_TOP_UNIVPLL_D6_D8>;
+ interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH 0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
xhci0: usb@11200000 {
compatible = "mediatek,mt8189-xhci", "mediatek,mtk-xhci";
reg = <0 0x11200000 0 0x1000>,
diff --git a/arch/arm/dts/mt8371-genio-common.dtsi b/arch/arm/dts/mt8371-genio-common.dtsi
index 046e9d57752..1d4728e3732 100644
--- a/arch/arm/dts/mt8371-genio-common.dtsi
+++ b/arch/arm/dts/mt8371-genio-common.dtsi
@@ -162,6 +162,21 @@
regulator-always-on;
};
+&nor_flash {
+ pinctrl-names = "default";
+ pinctrl-0 = <&nor_pins>;
+
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <52000000>;
+ spi-rx-bus-width = <2>;
+ spi-tx-bus-width = <2>;
+ };
+};
+
&pio {
mmc0_default_pins: mmc0-default-pins {
pins-clk {
@@ -274,6 +289,22 @@
};
};
+ nor_pins: nor-pins {
+ pins-ck-io {
+ pinmux = <PINMUX_GPIO150__FUNC_SPINOR_CK>,
+ <PINMUX_GPIO152__FUNC_SPINOR_IO0>,
+ <PINMUX_GPIO153__FUNC_SPINOR_IO1>;
+ drive-strength = <8>;
+ bias-pull-down;
+ };
+
+ pins-cs {
+ pinmux = <PINMUX_GPIO151__FUNC_SPINOR_CS>;
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
uart0_pins: uart0-pins {
pins {
pinmux = <PINMUX_GPIO31__FUNC_UTXD0>,
diff --git a/arch/arm/mach-mediatek/Kconfig b/arch/arm/mach-mediatek/Kconfig
index b5b06f4e5b2..80f7185e929 100644
--- a/arch/arm/mach-mediatek/Kconfig
+++ b/arch/arm/mach-mediatek/Kconfig
@@ -195,7 +195,6 @@ config SYS_BOARD
be used.
config SYS_CONFIG_NAME
- default "mt7622" if TARGET_MT7622
default "mt7623" if TARGET_MT7623
default "mt7629" if TARGET_MT7629
default "mt7981" if TARGET_MT7981
diff --git a/board/mediatek/mt7622/MAINTAINERS b/board/mediatek/mt7622/MAINTAINERS
index a3e0e75ca07..067f33bb39f 100644
--- a/board/mediatek/mt7622/MAINTAINERS
+++ b/board/mediatek/mt7622/MAINTAINERS
@@ -2,5 +2,4 @@ MT7622
M: Sam Shih <[email protected]>
S: Maintained
F: board/mediatek/mt7622
-F: include/configs/mt7622.h
F: configs/mt7622_rfb_defconfig
diff --git a/configs/mt8189.config b/configs/mt8189.config
index ecf8c5f4b4b..763f20b1063 100644
--- a/configs/mt8189.config
+++ b/configs/mt8189.config
@@ -23,6 +23,9 @@ CONFIG_CLK=y
# CONFIG_MMC_QUIRKS is not set
CONFIG_MMC_HS200_SUPPORT=y
CONFIG_MMC_MTK=y
+CONFIG_MTD=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_PHY=y
CONFIG_PHY_MTK_TPHY=y
CONFIG_PHY_MTK_XSPHY=y
@@ -37,6 +40,9 @@ CONFIG_DM_REGULATOR_MT6359=y
CONFIG_BAUDRATE=921600
CONFIG_DM_SERIAL=y
CONFIG_MTK_SERIAL=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_MTK_SNOR=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_MTK=y
diff --git a/configs/mt8365_evk_defconfig b/configs/mt8365_evk_defconfig
index 9b403cd7aab..1a385492547 100644
--- a/configs/mt8365_evk_defconfig
+++ b/configs/mt8365_evk_defconfig
@@ -8,7 +8,6 @@ CONFIG_NR_DRAM_BANKS=1
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8365-evk"
CONFIG_TARGET_MT8365=y
CONFIG_SYS_LOAD_ADDR=0x4c000000
-CONFIG_IDENT_STRING=" mt8365-evk"
CONFIG_DEFAULT_FDT_FILE="mt8365-evk"
# CONFIG_BOARD_INIT is not set
CONFIG_CMD_CLK=y
diff --git a/configs/mt8370_genio_510_evk_defconfig b/configs/mt8370_genio_510_evk_defconfig
index e3530571cc4..2ddd8d2a36a 100644
--- a/configs/mt8370_genio_510_evk_defconfig
+++ b/configs/mt8370_genio_510_evk_defconfig
@@ -2,4 +2,3 @@
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8370-genio-510-evk"
CONFIG_MTK_MEM_MAP_DDR_SIZE=0x100000000
-CONFIG_IDENT_STRING="mt8370-genio-510-evk"
diff --git a/configs/mt8390_genio_700_evk_defconfig b/configs/mt8390_genio_700_evk_defconfig
index 0b07e3be2c4..fe4f6ad9016 100644
--- a/configs/mt8390_genio_700_evk_defconfig
+++ b/configs/mt8390_genio_700_evk_defconfig
@@ -1,4 +1,3 @@
#include <configs/mt8188.config>
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8390-genio-700-evk"
-CONFIG_IDENT_STRING="mt8390-genio-700-evk"
diff --git a/configs/mt8395_genio_1200_evk_defconfig b/configs/mt8395_genio_1200_evk_defconfig
index 47c10757c52..e2e5480f55c 100644
--- a/configs/mt8395_genio_1200_evk_defconfig
+++ b/configs/mt8395_genio_1200_evk_defconfig
@@ -1,4 +1,3 @@
#include <configs/mt8195.config>
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8395-genio-1200-evk"
-CONFIG_IDENT_STRING="mt8395-genio-1200-evk"
diff --git a/configs/mt8395_genio_1200_evk_ufs_defconfig b/configs/mt8395_genio_1200_evk_ufs_defconfig
index e927365a03a..525638f5800 100644
--- a/configs/mt8395_genio_1200_evk_ufs_defconfig
+++ b/configs/mt8395_genio_1200_evk_ufs_defconfig
@@ -1,7 +1,6 @@
#include <configs/mt8195.config>
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8395-genio-1200-evk-ufs"
-CONFIG_IDENT_STRING=" mt8395-genio-1200-evk-ufs"
CONFIG_CMD_UFS=y
CONFIG_PHY=y
CONFIG_SCSI=y
diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c
index 7a4bdee7496..51c9c0a3fad 100644
--- a/drivers/mmc/mtk-sd.c
+++ b/drivers/mmc/mtk-sd.c
@@ -539,7 +539,7 @@ static bool msdc_cmd_is_ready(struct msdc_host *host)
return false;
}
- if (host->last_resp_type == MMC_RSP_R1b && host->last_data_write) {
+ if (host->last_resp_type == MMC_RSP_R1b || host->last_data_write) {
ret = readl_poll_timeout(&host->base->msdc_ps, reg,
reg & MSDC_PS_DAT0, 1000000);
@@ -1983,10 +1983,12 @@ static const struct msdc_compatible mt8189_compat = {
.clk_div_bits = 12,
.pad_tune0 = true,
.async_fifo = true,
+ .async_fifo_crcsts = true,
.data_tune = true,
.busy_check = true,
.stop_clk_fix = true,
.enhance_rx = true,
+ .use_dma_mode = true,
};
static const struct udevice_id msdc_ids[] = {
diff --git a/drivers/power/pmic/mtk-pwrap.c b/drivers/power/pmic/mtk-pwrap.c
index 3e3a691d9e8..47347785519 100644
--- a/drivers/power/pmic/mtk-pwrap.c
+++ b/drivers/power/pmic/mtk-pwrap.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * MT6357 regulator driver
+ * MediaTek PMIC Wrapper driver
*
* Copyright (c) 2026 BayLibre, SAS.
* Author: Julien Masson <[email protected]>
@@ -59,9 +59,11 @@ static const struct pmic_child_info mt6359_pmic_children_info[] = {
#define HAS_CAP(_c, _x_val) (((_c) & (_x_val)) == (_x_val))
/* Group of bits used for shown pwrap capability */
-#define PWRAP_CAP_INT1_EN BIT(3)
-#define PWRAP_CAP_WDT_SRC1 BIT(4)
-#define PWRAP_CAP_ARB BIT(5)
+#define PWRAP_CAP_WDT_SRC BIT(4)
+#define PWRAP_CAP_WDT_SRC1 BIT(5)
+#define PWRAP_CAP_ARB BIT(6)
+/* To implement this capability, the registers used in pwrap_init() must be defined. */
+#define PWRAP_CAP_INIT BIT(7)
/* defines for slave device wrapper registers */
enum dew_regs {
@@ -249,20 +251,20 @@ enum pwrap_regs {
};
static int mt8188_regs[] = {
- [PWRAP_INIT_DONE2] = 0x0,
- [PWRAP_STAUPD_CTRL] = 0x4C,
- [PWRAP_TIMER_EN] = 0x3E4,
- [PWRAP_INT_EN] = 0x420,
- [PWRAP_INT_FLG] = 0x428,
- [PWRAP_INT_CLR] = 0x42C,
- [PWRAP_INT1_EN] = 0x450,
- [PWRAP_INT1_FLG] = 0x458,
- [PWRAP_INT1_CLR] = 0x45C,
- [PWRAP_WACS2_CMD] = 0x880,
- [PWRAP_SWINF_2_WDATA_31_0] = 0x884,
- [PWRAP_SWINF_2_RDATA_31_0] = 0x894,
- [PWRAP_WACS2_VLDCLR] = 0x8A4,
- [PWRAP_WACS2_RDATA] = 0x8A8,
+ [PWRAP_INIT_DONE2] = 0x0,
+ [PWRAP_STAUPD_CTRL] = 0x4C,
+ [PWRAP_TIMER_EN] = 0x3E4,
+ [PWRAP_INT_EN] = 0x420,
+ [PWRAP_INT_FLG] = 0x428,
+ [PWRAP_INT_CLR] = 0x42C,
+ [PWRAP_INT1_EN] = 0x450,
+ [PWRAP_INT1_FLG] = 0x458,
+ [PWRAP_INT1_CLR] = 0x45C,
+ [PWRAP_WACS2_CMD] = 0x880,
+ [PWRAP_SWINF_2_WDATA_31_0] = 0x884,
+ [PWRAP_SWINF_2_RDATA_31_0] = 0x894,
+ [PWRAP_WACS2_VLDCLR] = 0x8A4,
+ [PWRAP_WACS2_RDATA] = 0x8A8,
};
static int mt8189_regs[] = {
@@ -276,6 +278,23 @@ static int mt8189_regs[] = {
[PWRAP_WACS2_RDATA] = 0x8A8,
};
+static int mt8195_regs[] = {
+ [PWRAP_INIT_DONE2] = 0x0,
+ [PWRAP_STAUPD_CTRL] = 0x4C,
+ [PWRAP_TIMER_EN] = 0x3E4,
+ [PWRAP_INT_EN] = 0x420,
+ [PWRAP_INT_FLG] = 0x428,
+ [PWRAP_INT_CLR] = 0x42C,
+ [PWRAP_INT1_EN] = 0x450,
+ [PWRAP_INT1_FLG] = 0x458,
+ [PWRAP_INT1_CLR] = 0x45C,
+ [PWRAP_WACS2_CMD] = 0x880,
+ [PWRAP_SWINF_2_WDATA_31_0] = 0x884,
+ [PWRAP_SWINF_2_RDATA_31_0] = 0x894,
+ [PWRAP_WACS2_VLDCLR] = 0x8A4,
+ [PWRAP_WACS2_RDATA] = 0x8A8,
+};
+
static int mt8365_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
@@ -338,12 +357,6 @@ static int mt8365_regs[] = {
[PWRAP_WDT_SRC_EN_1] = 0xf8,
};
-enum pwrap_type {
- PWRAP_MT8188,
- PWRAP_MT8189,
- PWRAP_MT8365,
-};
-
struct pwrap_slv_type {
const u32 *dew_regs;
u32 caps;
@@ -362,10 +375,7 @@ struct pmic_wrapper {
struct pmic_wrapper_type {
int *regs;
- enum pwrap_type type;
u32 arb_en_all;
- u32 int_en_all;
- u32 int1_en_all;
u32 spi_w;
u32 wdt_src;
/* Flags indicating the capability for the target pwrap */
@@ -644,7 +654,7 @@ static const struct pwrap_slv_type pmic_mt6357 = {
static const struct pwrap_slv_type pmic_mt6359 = {
.dew_regs = mt6359_regs,
- .caps = PWRAP_SLV_CAP_DUALIO,
+ .caps = 0,
};
static const struct udevice_id mtk_pmic_ids[] = {
@@ -734,6 +744,11 @@ static int mtk_pwrap_probe(struct udevice *dev)
* Skip initialization here in this case.
*/
if (!pwrap_readl(wrp, PWRAP_INIT_DONE2)) {
+ if (!HAS_CAP(wrp->master->caps, PWRAP_CAP_INIT)) {
+ dev_err(dev, "initialization is required but not supported\n");
+ return -EOPNOTSUPP;
+ }
+
ret = pwrap_init(wrp);
if (ret) {
dev_err(dev, "init failed with %d\n", ret);
@@ -755,7 +770,8 @@ static int mtk_pwrap_probe(struct udevice *dev)
* Since STAUPD was not used on mt8173 platform,
* so STAUPD of WDT_SRC which should be turned off
*/
- pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN);
+ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_WDT_SRC))
+ pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN);
if (HAS_CAP(wrp->master->caps, PWRAP_CAP_WDT_SRC1))
pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN_1);
@@ -765,15 +781,6 @@ static int mtk_pwrap_probe(struct udevice *dev)
else
pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
- pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN);
-
- /*
- * We add INT1 interrupt to handle starvation and request exception
- * If we support it, we should enable it here.
- */
- if (HAS_CAP(wrp->master->caps, PWRAP_CAP_INT1_EN))
- pwrap_writel(wrp, wrp->master->int1_en_all, PWRAP_INT1_EN);
-
return 0;
}
@@ -782,7 +789,6 @@ static int mtk_pwrap_bind(struct udevice *dev)
ofnode pmic_node, regulators_node;
int children;
const struct pmic_child_info *pmic_children_info;
- struct pmic_wrapper_type *pw_type = (void *)dev_get_driver_data(dev);
pmic_node = dev_read_first_subnode(dev);
if (!ofnode_valid(pmic_node)) {
@@ -790,16 +796,13 @@ static int mtk_pwrap_bind(struct udevice *dev)
return -ENXIO;
}
- switch (pw_type->type) {
- case PWRAP_MT8365:
+ if (ofnode_device_is_compatible(pmic_node, "mediatek,mt6357")) {
pmic_children_info = mt6357_pmic_children_info;
- break;
- case PWRAP_MT8188:
- case PWRAP_MT8189:
+ } else if (ofnode_device_is_compatible(pmic_node, "mediatek,mt6359")) {
pmic_children_info = mt6359_pmic_children_info;
- break;
- default:
- dev_err(dev, "pwrap type %d not supported\n", pw_type->type);
+ } else {
+ dev_err(dev, "pmic type %s not supported\n",
+ ofnode_read_string(pmic_node, "compatible"));
return -ENXIO;
}
@@ -848,20 +851,23 @@ static struct dm_pmic_ops mtk_pwrap_ops = {
static struct pmic_wrapper_type pwrap_mt8188 = {
.regs = mt8188_regs,
- .type = PWRAP_MT8188,
.arb_en_all = 0x777f,
- .int_en_all = 0x180000,
- .int1_en_all = 0x0,
.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
- .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_ARB,
+ .caps = PWRAP_CAP_ARB,
};
static struct pmic_wrapper_type pwrap_mt8189 = {
.regs = mt8189_regs,
- .type = PWRAP_MT8189,
.arb_en_all = 0x777f,
- .int_en_all = 0x180000,
+ .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+ .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+ .caps = PWRAP_CAP_ARB,
+};
+
+static const struct pmic_wrapper_type pwrap_mt8195 = {
+ .regs = mt8195_regs,
+ .arb_en_all = 0x777f, /* NEED CONFIRM */
.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
.caps = PWRAP_CAP_ARB,
@@ -869,18 +875,16 @@ static struct pmic_wrapper_type pwrap_mt8189 = {
static const struct pmic_wrapper_type pwrap_mt8365 = {
.regs = mt8365_regs,
- .type = PWRAP_MT8365,
.arb_en_all = 0x3ffff,
- .int_en_all = 0x7f1fffff,
- .int1_en_all = 0x0,
.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
- .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_WDT_SRC1,
+ .caps = PWRAP_CAP_WDT_SRC1 | PWRAP_CAP_INIT,
};
static const struct udevice_id mtk_pwrap_ids[] = {
{ .compatible = "mediatek,mt8188-pwrap", .data = (ulong)&pwrap_mt8188 },
{ .compatible = "mediatek,mt8189-pwrap", .data = (ulong)&pwrap_mt8189 },
+ { .compatible = "mediatek,mt8195-pwrap", .data = (ulong)&pwrap_mt8195 },
{ .compatible = "mediatek,mt8365-pwrap", .data = (ulong)&pwrap_mt8365 },
{ }
};
diff --git a/drivers/spi/mtk_snor.c b/drivers/spi/mtk_snor.c
index f202b2f49f5..40fc1826db6 100644
--- a/drivers/spi/mtk_snor.c
+++ b/drivers/spi/mtk_snor.c
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-//
-// Mediatek SPI-NOR controller driver
-//
-// Copyright (C) 2020 SkyLake Huang <[email protected]>
-//
-// Some parts are based on drivers/spi/spi-mtk-nor.c of linux version
+/*
+ * Mediatek SPI-NOR controller driver
+ *
+ * Copyright (C) 2020 SkyLake Huang <[email protected]>
+ *
+ * Some parts are based on drivers/spi/spi-mtk-nor.c of linux version
+ */
#include <clk.h>
#include <cpu_func.h>
@@ -89,22 +90,33 @@
#define MTK_NOR_REG_DMA_END_DADR 0x724
#define MTK_NOR_PRG_MAX_SIZE 6
-// Reading DMA src/dst addresses have to be 16-byte aligned
+#define MTK_NOR_PRG_CNT_MAX 56
+/* Reading DMA src/dst addresses have to be 16-byte aligned */
#define MTK_NOR_DMA_ALIGN 16
#define MTK_NOR_DMA_ALIGN_MASK (MTK_NOR_DMA_ALIGN - 1)
-// and we allocate a bounce buffer if destination address isn't aligned.
+/* and we allocate a bounce buffer if destination address isn't aligned. */
#define MTK_NOR_BOUNCE_BUF_SIZE PAGE_SIZE
-// Buffered page program can do one 128-byte transfer
+/* Buffered page program can do one 128-byte transfer */
#define MTK_NOR_PP_SIZE 128
#define CLK_TO_US(priv, clkcnt) DIV_ROUND_UP(clkcnt, (priv)->spi_freq / 1000000)
#define MTK_NOR_UNLOCK_ALL 0x0
+struct mtk_snor_caps {
+ /*
+ * Some new SoCs modify the timing of fetching registers' values and IDs
+ * of NOR flash, they need a extra_bit which can add more clock cycles
+ * for fetching data.
+ */
+ u8 extra_bit;
+};
+
struct mtk_snor_priv {
struct device *dev;
void __iomem *base;
+ const struct mtk_snor_caps *caps;
u8 *buffer;
struct clk spi_clk;
struct clk ctlr_clk;
@@ -168,8 +180,8 @@ static int mtk_snor_adjust_op_size(struct spi_slave *slave,
return 0;
if (op->addr.nbytes == 3 || op->addr.nbytes == 4) {
- if (op->data.dir == SPI_MEM_DATA_IN) { //&&
- // limit size to prevent timeout calculation overflow
+ if (op->data.dir == SPI_MEM_DATA_IN) {
+ /* limit size to prevent timeout calculation overflow */
if (op->data.nbytes > 0x400000)
op->data.nbytes = 0x400000;
if (op->addr.val & MTK_NOR_DMA_ALIGN_MASK ||
@@ -262,6 +274,7 @@ static int mtk_snor_read_bounce(struct mtk_snor_priv *priv,
{
unsigned int rdlen;
int ret;
+ dma_addr_t bounce_dma;
if (op->data.nbytes & MTK_NOR_DMA_ALIGN_MASK)
rdlen = (op->data.nbytes + MTK_NOR_DMA_ALIGN) &
@@ -269,11 +282,21 @@ static int mtk_snor_read_bounce(struct mtk_snor_priv *priv,
else
rdlen = op->data.nbytes;
- ret = mtk_snor_dma_exec(priv, op->addr.val, rdlen,
- (dma_addr_t)priv->buffer);
+ /* Map bounce buffer for DMA */
+ bounce_dma = dma_map_single(priv->buffer, rdlen, DMA_FROM_DEVICE);
+ if (dma_mapping_error(priv->dev, bounce_dma)) {
+ dev_err(priv->dev, "bounce buffer dma map failed\n");
+ return -EINVAL;
+ }
- if (!ret)
+ ret = mtk_snor_dma_exec(priv, op->addr.val, rdlen, bounce_dma);
+ /* Ensure DMA writes are visible to CPU and copy the requested bytes */
+ if (!ret) {
+ /* Synchronize cached data to CPU visible memory if needed */
memcpy(op->data.buf.in, priv->buffer, op->data.nbytes);
+ }
+ /* Unmap bounce buffer regardless of success/failure */
+ dma_unmap_single(bounce_dma, rdlen, DMA_FROM_DEVICE);
return ret;
}
@@ -361,8 +384,12 @@ static int mtk_snor_pp_buffered(struct mtk_snor_priv *priv,
buf[i];
writel(val, priv->base + MTK_NOR_REG_PP_DATA);
}
- mtk_snor_cmd_exec(priv, MTK_NOR_CMD_WRITE,
- (op->data.nbytes + 5) * BITS_PER_BYTE);
+
+ ret = mtk_snor_cmd_exec(priv, MTK_NOR_CMD_WRITE,
+ (op->data.nbytes + 5) * BITS_PER_BYTE);
+ if (ret)
+ return ret;
+
return mtk_snor_write_buffer_disable(priv);
}
@@ -382,50 +409,83 @@ static int mtk_snor_pp_unbuffered(struct mtk_snor_priv *priv,
static int mtk_snor_cmd_program(struct mtk_snor_priv *priv,
const struct spi_mem_op *op)
{
- u32 tx_len = 0;
- u32 trx_len = 0;
+ int rx_len = 0;
int reg_offset = MTK_NOR_REG_PRGDATA_MAX;
+ int tx_len, prg_len;
+ int i, ret;
void __iomem *reg;
- u8 *txbuf;
- int tx_cnt = 0;
- u8 *rxbuf = op->data.buf.in;
- int i = 0;
+ u8 val;
- tx_len = 1 + op->addr.nbytes + op->dummy.nbytes;
- trx_len = tx_len + op->data.nbytes;
- if (op->data.dir == SPI_MEM_DATA_OUT)
- tx_len += op->data.nbytes;
-
- txbuf = kmalloc_array(tx_len, sizeof(u8), GFP_KERNEL);
- memset(txbuf, 0x0, tx_len * sizeof(u8));
-
- /* Join all bytes to be transferred */
- txbuf[tx_cnt] = op->cmd.opcode;
- tx_cnt++;
- for (i = op->addr.nbytes; i > 0; i--, tx_cnt++)
- txbuf[tx_cnt] = ((u8 *)&op->addr.val)[i - 1];
- for (i = op->dummy.nbytes; i > 0; i--, tx_cnt++)
- txbuf[tx_cnt] = 0x0;
+ tx_len = op->cmd.nbytes + op->addr.nbytes;
+
+ /* count dummy bytes only if we need to write data after it */
if (op->data.dir == SPI_MEM_DATA_OUT)
- for (i = op->data.nbytes; i > 0; i--, tx_cnt++)
- txbuf[tx_cnt] = ((u8 *)op->data.buf.out)[i - 1];
+ tx_len += op->dummy.nbytes + op->data.nbytes;
+ else if (op->data.dir == SPI_MEM_DATA_IN)
+ rx_len = op->data.nbytes;
- for (i = MTK_NOR_REG_PRGDATA_MAX; i >= 0; i--)
- writeb(0, priv->base + MTK_NOR_REG_PRGDATA(i));
+ prg_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes +
+ op->data.nbytes;
- for (i = 0; i < tx_len; i++, reg_offset--)
- writeb(txbuf[i], priv->base + MTK_NOR_REG_PRGDATA(reg_offset));
+ /*
+ * An invalid op may reach here if the caller calls exec_op without
+ * adjust_op_size. return -EINVAL instead of -ENOTSUPP so that
+ * spi-mem won't try this op again with generic spi transfers.
+ */
+ if ((tx_len > MTK_NOR_REG_PRGDATA_MAX + 1) ||
+ (rx_len > MTK_NOR_REG_SHIFT_MAX + 1) ||
+ (prg_len > MTK_NOR_PRG_CNT_MAX / 8))
+ return -EINVAL;
- kfree(txbuf);
+ /* fill tx data */
- writel(trx_len * BITS_PER_BYTE, priv->base + MTK_NOR_REG_PRG_CNT);
+ for (i = op->cmd.nbytes; i > 0; i--, reg_offset--) {
+ reg = priv->base + MTK_NOR_REG_PRGDATA(reg_offset);
+ val = (op->cmd.opcode >> ((i - 1) * BITS_PER_BYTE)) & 0xff;
+ writeb(val, reg);
+ }
- mtk_snor_cmd_exec(priv, MTK_NOR_CMD_PROGRAM, trx_len * BITS_PER_BYTE);
+ for (i = op->addr.nbytes; i > 0; i--, reg_offset--) {
+ reg = priv->base + MTK_NOR_REG_PRGDATA(reg_offset);
+ val = (op->addr.val >> ((i - 1) * BITS_PER_BYTE)) & 0xff;
+ writeb(val, reg);
+ }
+
+ if (op->data.dir == SPI_MEM_DATA_OUT) {
+ for (i = 0; i < op->dummy.nbytes; i++, reg_offset--) {
+ reg = priv->base + MTK_NOR_REG_PRGDATA(reg_offset);
+ writeb(0, reg);
+ }
- reg_offset = op->data.nbytes - 1;
- for (i = 0; i < op->data.nbytes; i++, reg_offset--) {
- reg = priv->base + MTK_NOR_REG_SHIFT(reg_offset);
- rxbuf[i] = readb(reg);
+ for (i = 0; i < op->data.nbytes; i++, reg_offset--) {
+ reg = priv->base + MTK_NOR_REG_PRGDATA(reg_offset);
+ writeb(((const u8 *)(op->data.buf.out))[i], reg);
+ }
+ }
+
+ for (; reg_offset >= 0; reg_offset--) {
+ reg = priv->base + MTK_NOR_REG_PRGDATA(reg_offset);
+ writeb(0, reg);
+ }
+
+ /* trigger op */
+ if (rx_len)
+ writel(prg_len * BITS_PER_BYTE + priv->caps->extra_bit,
+ priv->base + MTK_NOR_REG_PRG_CNT);
+ else
+ writel(prg_len * BITS_PER_BYTE, priv->base + MTK_NOR_REG_PRG_CNT);
+
+ ret = mtk_snor_cmd_exec(priv, MTK_NOR_CMD_PROGRAM, prg_len * BITS_PER_BYTE);
+ if (ret)
+ return ret;
+
+ /* fetch read data */
+ reg_offset = 0;
+ if (op->data.dir == SPI_MEM_DATA_IN) {
+ for (i = op->data.nbytes - 1; i >= 0; i--, reg_offset++) {
+ reg = priv->base + MTK_NOR_REG_SHIFT(reg_offset);
+ ((u8 *)(op->data.buf.in))[i] = readb(reg);
+ }
}
return 0;
@@ -467,12 +527,13 @@ static int mtk_snor_probe(struct udevice *bus)
struct mtk_snor_priv *priv = dev_get_priv(bus);
u8 *buffer;
int ret;
- u32 reg;
priv->base = devfdt_get_addr_ptr(bus);
if (!priv->base)
return -EINVAL;
+ priv->caps = (const void *)dev_get_driver_data(bus);
+
ret = clk_get_by_name(bus, "spi", &priv->spi_clk);
if (ret < 0)
return ret;
@@ -496,7 +557,8 @@ static int mtk_snor_probe(struct udevice *bus)
priv->spi_freq = clk_get_rate(&priv->spi_clk);
printf("spi frequency: %d Hz\n", priv->spi_freq);
- /* With this setting, we issue one command at a time to
+ /*
+ * With this setting, we issue one command at a time to
* accommodate to SPI-mem framework.
*/
writel(MTK_NOR_ENABLE_SF_CMD, priv->base + MTK_NOR_REG_WP);
@@ -504,24 +566,13 @@ static int mtk_snor_probe(struct udevice *bus)
mtk_snor_rmw(priv, MTK_NOR_REG_CFG3,
MTK_NOR_DISABLE_WREN | MTK_NOR_DISABLE_SR_POLL, 0);
- /* Unlock all blocks using write status command.
- * SPI-MEM hasn't implemented unlock procedure on MXIC devices.
- * We may remove this later.
- */
- writel(2 * BITS_PER_BYTE, priv->base + MTK_NOR_REG_PRG_CNT);
- writel(MTK_NOR_UNLOCK_ALL, priv->base + MTK_NOR_REG_PRGDATA(5));
- writel(MTK_NOR_IRQ_WRSR, priv->base + MTK_NOR_REG_IRQ_EN);
- writel(MTK_NOR_CMD_WRSR, priv->base + MTK_NOR_REG_CMD);
- ret = readl_poll_timeout(priv->base + MTK_NOR_REG_IRQ_STAT, reg,
- !(reg & MTK_NOR_IRQ_WRSR),
- ((3 * BITS_PER_BYTE) + 1) * 200);
-
return 0;
}
static int mtk_snor_set_speed(struct udevice *bus, uint speed)
{
- /* MTK's SNOR controller does not have a bus clock divider.
+ /*
+ * MTK's SNOR controller does not have a bus clock divider.
* We setup maximum bus clock in dts.
*/
@@ -530,8 +581,7 @@ static int mtk_snor_set_speed(struct udevice *bus, uint speed)
static int mtk_snor_set_mode(struct udevice *bus, uint mode)
{
- /* We set up mode later for each transmission.
- */
+ /* We set up mode later for each transmission. */
return 0;
}
@@ -547,8 +597,19 @@ static const struct dm_spi_ops mtk_snor_ops = {
.set_mode = mtk_snor_set_mode,
};
+static const struct mtk_snor_caps mtk_snor_caps_default = {
+ .extra_bit = 0,
+};
+
+static const struct mtk_snor_caps mtk_snor_caps_extra_bit = {
+ .extra_bit = 1,
+};
+
static const struct udevice_id mtk_snor_ids[] = {
- { .compatible = "mediatek,mtk-snor" },
+ { .compatible = "mediatek,mtk-snor", .data = (ulong)&mtk_snor_caps_default },
+ { .compatible = "mediatek,mt8188-nor", .data = (ulong)&mtk_snor_caps_extra_bit },
+ { .compatible = "mediatek,mt8189-nor", .data = (ulong)&mtk_snor_caps_extra_bit },
+ { .compatible = "mediatek,mt8195-nor", .data = (ulong)&mtk_snor_caps_default },
{}
};
diff --git a/include/configs/mt7622.h b/include/configs/mt7622.h
deleted file mode 100644
index 4a056954bf8..00000000000
--- a/include/configs/mt7622.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Configuration for MediaTek MT7629 SoC
- *
- * Copyright (C) 2019 MediaTek Inc.
- * Author: Sam Shih <[email protected]>
- */
-
-#ifndef __MT7622_H
-#define __MT7622_H
-
-#endif