* 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
This commit is contained in:
Tom Rini 2026-04-29 14:49:24 -06:00
commit 9d3bc111ef
14 changed files with 245 additions and 143 deletions

View File

@ -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>,

View File

@ -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>,

View File

@ -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

View File

@ -2,5 +2,4 @@ MT7622
M: Sam Shih <sam.shih@mediatek.com>
S: Maintained
F: board/mediatek/mt7622
F: include/configs/mt7622.h
F: configs/mt7622_rfb_defconfig

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -1,4 +1,3 @@
#include <configs/mt8188.config>
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8390-genio-700-evk"
CONFIG_IDENT_STRING="mt8390-genio-700-evk"

View File

@ -1,4 +1,3 @@
#include <configs/mt8195.config>
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8395-genio-1200-evk"
CONFIG_IDENT_STRING="mt8395-genio-1200-evk"

View File

@ -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

View File

@ -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[] = {

View File

@ -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 <jmasson@baylibre.com>
@ -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 },
{ }
};

View File

@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
//
// Mediatek SPI-NOR controller driver
//
// Copyright (C) 2020 SkyLake Huang <SkyLake.Huang@mediatek.com>
//
// Some parts are based on drivers/spi/spi-mtk-nor.c of linux version
/*
* Mediatek SPI-NOR controller driver
*
* Copyright (C) 2020 SkyLake Huang <SkyLake.Huang@mediatek.com>
*
* 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;
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)
tx_len += op->data.nbytes;
tx_len += op->dummy.nbytes + op->data.nbytes;
else if (op->data.dir == SPI_MEM_DATA_IN)
rx_len = op->data.nbytes;
txbuf = kmalloc_array(tx_len, sizeof(u8), GFP_KERNEL);
memset(txbuf, 0x0, tx_len * sizeof(u8));
prg_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes +
op->data.nbytes;
/* 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;
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];
/*
* 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;
for (i = MTK_NOR_REG_PRGDATA_MAX; i >= 0; i--)
writeb(0, priv->base + MTK_NOR_REG_PRGDATA(i));
/* fill tx data */
for (i = 0; i < tx_len; i++, reg_offset--)
writeb(txbuf[i], priv->base + MTK_NOR_REG_PRGDATA(reg_offset));
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);
}
kfree(txbuf);
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);
}
writel(trx_len * BITS_PER_BYTE, priv->base + MTK_NOR_REG_PRG_CNT);
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);
}
mtk_snor_cmd_exec(priv, MTK_NOR_CMD_PROGRAM, trx_len * BITS_PER_BYTE);
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);
}
}
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 (; 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 },
{}
};

View File

@ -1,12 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Configuration for MediaTek MT7629 SoC
*
* Copyright (C) 2019 MediaTek Inc.
* Author: Sam Shih <sam.shih@mediatek.com>
*/
#ifndef __MT7622_H
#define __MT7622_H
#endif