diff options
| author | Tom Rini <[email protected]> | 2026-04-29 14:49:24 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2026-04-29 17:09:13 -0600 |
| commit | 9d3bc111efe1c600a1475bbdfb6da6269e02c5c2 (patch) | |
| tree | 9b594932d142f5f8e136c8dd85ede0d510de7b78 | |
| parent | 6211462c922f3a40ca0764303809771c23a7d701 (diff) | |
| parent | a97c82bfdf52aab727ecb4ce3a81ef585e4c55d3 (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.dtsi | 17 | ||||
| -rw-r--r-- | arch/arm/dts/mt8371-genio-common.dtsi | 31 | ||||
| -rw-r--r-- | arch/arm/mach-mediatek/Kconfig | 1 | ||||
| -rw-r--r-- | board/mediatek/mt7622/MAINTAINERS | 1 | ||||
| -rw-r--r-- | configs/mt8189.config | 6 | ||||
| -rw-r--r-- | configs/mt8365_evk_defconfig | 1 | ||||
| -rw-r--r-- | configs/mt8370_genio_510_evk_defconfig | 1 | ||||
| -rw-r--r-- | configs/mt8390_genio_700_evk_defconfig | 1 | ||||
| -rw-r--r-- | configs/mt8395_genio_1200_evk_defconfig | 1 | ||||
| -rw-r--r-- | configs/mt8395_genio_1200_evk_ufs_defconfig | 1 | ||||
| -rw-r--r-- | drivers/mmc/mtk-sd.c | 4 | ||||
| -rw-r--r-- | drivers/power/pmic/mtk-pwrap.c | 118 | ||||
| -rw-r--r-- | drivers/spi/mtk_snor.c | 197 | ||||
| -rw-r--r-- | include/configs/mt7622.h | 12 |
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 |
