mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-05-05 04:36:13 +02:00
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
This commit is contained in:
commit
9d3bc111ef
@ -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>,
|
||||
|
||||
@ -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>,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
#include <configs/mt8188.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8390-genio-700-evk"
|
||||
CONFIG_IDENT_STRING="mt8390-genio-700-evk"
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
#include <configs/mt8195.config>
|
||||
|
||||
CONFIG_DEFAULT_DEVICE_TREE="mediatek/mt8395-genio-1200-evk"
|
||||
CONFIG_IDENT_STRING="mt8395-genio-1200-evk"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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[] = {
|
||||
|
||||
@ -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 },
|
||||
{ }
|
||||
};
|
||||
|
||||
@ -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 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user