QSPI Flash驱动代码分析 (QSPI控制器初始化)

QSPI Flash驱动代码分析 (QSPI控制器初始化)

1. 函数cqspi_controller_enable()

        该函数主要使能和去能QSPI控制器。QSPI配置寄存器(偏移量0x00)的bit[0]位为可读写QSPI使能位。1表示并行SPI使能;当该位设置为0时,所有SPI信号输出使能全部无效,SPI信号的所有接口被设置为输入模式。

        参数enable,0为去能;1为使能。

static void cqspi_controller_enable(struct cqspi_st *cqspi, bool enable)
{
	void __iomem *reg_base = cqspi->iobase;
	unsigned int reg;

	reg = readl(reg_base + CQSPI_REG_CONFIG);

	if (enable)
		reg |= CQSPI_REG_CONFIG_ENABLE_MASK;
	else
		reg &= ~CQSPI_REG_CONFIG_ENABLE_MASK;

	writel(reg, reg_base + CQSPI_REG_CONFIG);
}

        QSPI控制器的初始化一开始需要关闭QSPI控制器,初始化结束后将QSPI使能。

2. 当前驱动关闭了直接访问模式

        quirk是驱动特征调整标志变量,quirks仅仅定义了DAC模式关闭特征。

static const struct cqspi_driver_platdata cdns_qspi = {
	.quirks = CQSPI_DISABLE_DAC_MODE,
};

        函数of_device_get_match_data()获取了quirks变量,并根据quirks变量设置核心结构的相关变量。

	ddata  = of_device_get_match_data(dev);
	if (ddata) {
		if (ddata->quirks & CQSPI_NEEDS_WR_DELAY)
			cqspi->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC,
						cqspi->master_ref_clk_hz);
		if (ddata->hwcaps_mask & CQSPI_SUPPORTS_OCTAL)
			master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL;
		if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE))
			cqspi->use_direct_mode = true;
	}

        其中,根据当前quirks变量,cqspi->use_direct_mode 并没有被设置为true。

        QSPI配置寄存器的bit[7]是可读写的DAC使能,0表示关闭(如果当前正在传输数据,当前传输结束后再关闭);1表示使能。

	/* Disable direct access controller */
	if (!cqspi->use_direct_mode) {
		reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
		reg &= ~CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL;
		writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
	}

3. 函数cqspi_controller_init()

        驱动程序首次对qspi控制器进行初始化操作。

  1. AHB总线地址重映射地址为0x0。
  2. 写全零关闭中断。
  3. 配置内部SDRAM的读缓冲大小。注意:写缓冲大小就是SDRAM剩余部分。
  4. 配置内部SDRAM在AHB总线上的物理起始地址。
  5. 定义间接模式的读/写水印寄存器。
  6. 关闭DAC模式。
static void cqspi_controller_init(struct cqspi_st *cqspi)
{
	u32 reg;

	cqspi_controller_enable(cqspi, 0);

	/* Configure the remap address register, no remap */
	writel(0, cqspi->iobase + CQSPI_REG_REMAP);

	/* Disable all interrupts. */
	writel(0, cqspi->iobase + CQSPI_REG_IRQMASK);

	/* Configure the SRAM split to 1:1 . */
	writel(cqspi->fifo_depth / 2, cqspi->iobase + CQSPI_REG_SRAMPARTITION);

	/* Load indirect trigger address. */
	writel(cqspi->trigger_address,
	       cqspi->iobase + CQSPI_REG_INDIRECTTRIGGER);

	/* Program read watermark -- 1/2 of the FIFO. */
	writel(cqspi->fifo_depth * cqspi->fifo_width / 2,
	       cqspi->iobase + CQSPI_REG_INDIRECTRDWATERMARK);
	/* Program write watermark -- 1/8 of the FIFO. */
	writel(cqspi->fifo_depth * cqspi->fifo_width / 8,
	       cqspi->iobase + CQSPI_REG_INDIRECTWRWATERMARK);

	/* Disable direct access controller */
	if (!cqspi->use_direct_mode) {
		reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
		reg &= ~CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL;
		writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
	}

	cqspi_controller_enable(cqspi, 1);
}

注意:

设备树需要定义"cdns,fifo-depth" 、"cdns,fifo-width" 和"cdns,trigger-address"三个量,这直接定义了cqspi->fifo_depth/fifo_width/trigger_address。

猜你喜欢

转载自blog.csdn.net/lsshao/article/details/119924277