drivers/spi/spi-mtk-nor.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-mtk-nor.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-mtk-nor.c- Extension
.c- Size
- 25896 bytes
- Lines
- 1010
- Domain
- Driver Families
- Bucket
- drivers/spi
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bits.hlinux/clk.hlinux/completion.hlinux/dma-mapping.hlinux/interrupt.hlinux/io.hlinux/iopoll.hlinux/kernel.hlinux/module.hlinux/of.hlinux/platform_device.hlinux/pm_runtime.hlinux/spi/spi.hlinux/spi/spi-mem.hlinux/string.h
Detected Declarations
struct mtk_nor_capsstruct mtk_norfunction mtk_nor_rmwfunction mtk_nor_cmd_execfunction mtk_nor_resetfunction mtk_nor_set_addrfunction need_bouncefunction mtk_nor_match_readfunction mtk_nor_match_prgfunction mtk_nor_adj_prg_sizefunction mtk_nor_adjust_op_sizefunction mtk_nor_supports_opfunction mtk_nor_setup_busfunction mtk_nor_dma_execfunction mtk_nor_read_bouncefunction mtk_nor_read_dmafunction mtk_nor_read_piofunction mtk_nor_setup_write_bufferfunction mtk_nor_pp_bufferedfunction mtk_nor_pp_unbufferedfunction mtk_nor_spi_mem_prgfunction mtk_nor_exec_opfunction mtk_nor_setupfunction mtk_nor_transfer_one_messagefunction list_for_each_entryfunction mtk_nor_disable_clkfunction mtk_nor_enable_clkfunction mtk_nor_initfunction mtk_nor_irq_handlerfunction mtk_max_msg_sizefunction mtk_nor_probefunction mtk_nor_removefunction mtk_nor_runtime_suspendfunction mtk_nor_runtime_resumefunction mtk_nor_suspendfunction mtk_nor_resume
Annotated Snippet
struct mtk_nor_caps {
u8 dma_bits;
/* extra_dummy_bit is adding for the IP of new SoCs.
* Some new SoCs modify the timing of fetching registers' values
* and IDs of nor flash, they need a extra_dummy_bit which can add
* more clock cycles for fetching data.
*/
u8 extra_dummy_bit;
};
struct mtk_nor {
struct spi_controller *ctlr;
struct device *dev;
void __iomem *base;
u8 *buffer;
dma_addr_t buffer_dma;
struct clk *spi_clk;
struct clk *ctlr_clk;
struct clk *axi_clk;
struct clk *axi_s_clk;
unsigned int spi_freq;
bool wbuf_en;
bool has_irq;
bool high_dma;
struct completion op_done;
const struct mtk_nor_caps *caps;
};
static inline void mtk_nor_rmw(struct mtk_nor *sp, u32 reg, u32 set, u32 clr)
{
u32 val = readl(sp->base + reg);
val &= ~clr;
val |= set;
writel(val, sp->base + reg);
}
static inline int mtk_nor_cmd_exec(struct mtk_nor *sp, u32 cmd, ulong clk)
{
ulong delay = CLK_TO_US(sp, clk);
u32 reg;
int ret;
writel(cmd, sp->base + MTK_NOR_REG_CMD);
ret = readl_poll_timeout(sp->base + MTK_NOR_REG_CMD, reg, !(reg & cmd),
delay / 3, (delay + 1) * 200);
if (ret < 0)
dev_err(sp->dev, "command %u timeout.\n", cmd);
return ret;
}
static void mtk_nor_reset(struct mtk_nor *sp)
{
mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, 0, MTK_NOR_SFC_SW_RST);
mb(); /* flush previous writes */
mtk_nor_rmw(sp, MTK_NOR_REG_CG_DIS, MTK_NOR_SFC_SW_RST, 0);
mb(); /* flush previous writes */
writel(MTK_NOR_ENABLE_SF_CMD, sp->base + MTK_NOR_REG_WP);
}
static void mtk_nor_set_addr(struct mtk_nor *sp, const struct spi_mem_op *op)
{
u32 addr = op->addr.val;
int i;
for (i = 0; i < 3; i++) {
writeb(addr & 0xff, sp->base + MTK_NOR_REG_RADR(i));
addr >>= 8;
}
if (op->addr.nbytes == 4) {
writeb(addr & 0xff, sp->base + MTK_NOR_REG_RADR3);
mtk_nor_rmw(sp, MTK_NOR_REG_BUSCFG, MTK_NOR_4B_ADDR, 0);
} else {
mtk_nor_rmw(sp, MTK_NOR_REG_BUSCFG, 0, MTK_NOR_4B_ADDR);
}
}
static bool need_bounce(struct mtk_nor *sp, const struct spi_mem_op *op)
{
return ((uintptr_t)op->data.buf.in & MTK_NOR_DMA_ALIGN_MASK);
}
static bool mtk_nor_match_read(const struct spi_mem_op *op)
{
int dummy = 0;
if (op->dummy.nbytes)
dummy = op->dummy.nbytes * BITS_PER_BYTE / op->dummy.buswidth;
Annotation
- Immediate include surface: `linux/bits.h`, `linux/clk.h`, `linux/completion.h`, `linux/dma-mapping.h`, `linux/interrupt.h`, `linux/io.h`, `linux/iopoll.h`, `linux/kernel.h`.
- Detected declarations: `struct mtk_nor_caps`, `struct mtk_nor`, `function mtk_nor_rmw`, `function mtk_nor_cmd_exec`, `function mtk_nor_reset`, `function mtk_nor_set_addr`, `function need_bounce`, `function mtk_nor_match_read`, `function mtk_nor_match_prg`, `function mtk_nor_adj_prg_size`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.