LS1028ARDB开发板FlexSPI时钟无法降至18MHz以下求助
LS1028 FlexSPI时钟无法降至18MHz以下的问题排查与解决需求
硬件连接与背景
使用LS1028ARDB开发板验证LS1028的FlexSPI与自定义设备的通信可行性,连接方式:
LS1028ARDB <--- QSPI port (managed by FlexSPI) <----> My device.
开发板QSPI端口引脚电压为1.8V,目标设备工作在3.3V,因此采用电压转换芯片,但这类芯片速度较慢,导致通信不可靠。测试不需要高速通信,仅需可靠通信,SPI频率越低越好。
时钟配置问题
无法将SPI时钟配置到18MHz以下:
- 通过设备树的
spi-max-frequency属性设置频率时,设为50MHz可正常生效(实际约48MHz,通过/sys/kernel/debug/clk/fspi_clk/clk_rate验证); - 设为10MHz、5MHz、1MHz等低于18MHz的值时,实际时钟仍维持在18MHz左右,且所有操作无报错。
所有时钟配置均由主线驱动管理,未修改驱动代码,仅添加设备树节点并编写了触发SPI操作的简易驱动。
相关代码片段
主线fsl-ls-1028a.dtsi中的fspi节点
fspi: spi@20c0000 { compatible = "nxp,lx2160a-fspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x0 0x20c0000 0x0 0x10000>, <0x0 0x20000000 0x0 0x10000000>; reg-names = "fspi_base", "fspi_mmap"; interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>; clocks = <&fspi_clk>, <&fspi_clk>; clock-names = "fspi_en", "fspi"; status = "disabled"; };
主线fsl-ls-1028a-rdb.dts中的修改
&fspi { status = "okay"; pbspimem: pbspimem@0 { compatible = "pb,pb-spi-mem"; #address-cells = <1>; #size-cells = <1>; spi-max-frequency = <5000000>; spi-rx-bus-width = <1>; /* 1 SPI Rx lines */ spi-tx-bus-width = <1>; /* 1 SPI Tx line */ reg = <0>; }; };
自定义简易SPI驱动
#include "linux/types.h" #include <linux/module.h> #include <linux/printk.h> #include <linux/spi/spi-mem.h> #include <linux/dma-mapping.h> static int pb_spi_mem_probe(struct spi_mem *spimem) { int ret; uint8_t buf[64]; memset(buf, 0, sizeof(buf)); struct spi_mem_op op = SPI_MEM_OP( SPI_MEM_OP_CMD(0x80, 1), SPI_MEM_OP_ADDR(3, 0x000004, 1), SPI_MEM_OP_NO_DUMMY, SPI_MEM_OP_DATA_IN(4, buf, 1) ); ret = spi_mem_exec_op(spimem, &op); if (ret) { pr_info("Cannot execute op\n"); } return ret; } static int pb_spi_mem_remove(struct spi_mem *spimem) { pr_info("%s\n", __func__); return 0; } static const struct spi_device_id spi_nor_dev_ids[] = { {"pb-spi-mem"}, { } /* sentinel */ }; MODULE_DEVICE_TABLE(spi, spi_nor_dev_ids); static const struct of_device_id pb_spi_mem_of_table[] = { { .compatible = "pb,pb-spi-mem" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, pb_spi_mem_of_table); static struct spi_mem_driver pb_spi_mem_driver = { .spidrv = { .driver = { .name = "pb-spi-mem-namer", .of_match_table = pb_spi_mem_of_table }, .id_table = spi_nor_dev_ids }, .probe = pb_spi_mem_probe, .remove = pb_spi_mem_remove }; module_spi_mem_driver(pb_spi_mem_driver); MODULE_LICENSE("GPL");
FlexSPI驱动相关代码片段
驱动底层调用nxp_fspi_exec_op函数,跟踪调用栈确认会执行以下代码:
static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi) { unsigned long rate = spi->max_speed_hz; int ret; uint64_t size_kb; [...] nxp_fspi_clk_disable_unprep(f); ret = clk_set_rate(f->clk, rate); if (ret) return; ret = nxp_fspi_clk_prep_enable(f); if (ret) return; f->selected = spi->chip_select; } static int nxp_fspi_clk_prep_enable(struct nxp_fspi *f) { int ret; if (is_acpi_node(f->dev->fwnode)) return 0; ret = clk_prepare_enable(f->clk_en); if (ret) return ret; ret = clk_prepare_enable(f->clk); if (ret) { clk_disable_unprepare(f->clk_en); return ret; } return 0; }
可见代码中调用了clk_set_rate(f->clk, rate),该函数在设置50MHz等高频时可正常生效,但无法将频率设置到18MHz以下。
需求
寻求将SPI时钟降至18MHz以下的方法,以满足低速可靠通信的测试需求。
内容的提问来源于stack exchange,提问作者bielu000
相关产品推荐
相关产品推荐

