RK3328-SPI驱动移植

1、查看电路原理图,确定spi对应的引脚GPIO口

2、根据RK-SPI手册添加dts节点并检查对应的GPIO口设置是否有问题,是否被占用

   

3、检查到有引脚(GPIO3_A2、GPIO3_B0)与spi的引脚占用,注释掉,不然编译后的系统可能会启动失败,或者驱动功能有问题

    

4、修改完后,将对应的驱动加载进内核,对应的文件如下:

5、查看生成的spi节点,ls -l | grep spi,会出现类似spi32766.0的设备节点,如果没有,请看下内核报错信息

6、通过应用层调用spi设备节点,发现SPI的时钟引脚没有信号产生,检查dts文档也没有引脚占用,因此需要排查io口的复用情况; 通过在rock_set_mux()函数中加入dump_stack()函数打印该函数的调用情况,因为所有RK的GPIO口复用都会调用该函数;其次通过“io -4 寄存器地址”来查看CLK引脚有无被其它驱动占用

7、上面的步骤做完后,发现时钟引脚被该驱动占用,关闭它之后,时钟就有信号了

8、如果根据项目需要自己去更改时钟频率,可以在spi-rockchip.c文件中rockchip_spi_config函数进行修改,修改函数中的clk_set_rate()来修改频率,spi_set_clk修改时钟的分频系数

static void rockchip_spi_config(struct rockchip_spi *rs)
{
	u32 div = 0;
	u32 dmacr = 0;
	int rsd = 0;

	u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET)
		| (CR0_SSD_ONE << CR0_SSD_OFFSET)
		| (CR0_EM_BIG << CR0_EM_OFFSET);

	cr0 |= (rs->n_bytes << CR0_DFS_OFFSET);
	cr0 |= ((rs->mode & 0x3) << CR0_SCPH_OFFSET);
	if (rs->mode & SPI_LSB_FIRST)
		cr0 |= (1 << CR0_FBM_OFFSET);/* First Bit Mode */
	cr0 |= (rs->tmode << CR0_XFM_OFFSET);
	cr0 |= (rs->type << CR0_FRF_OFFSET);

	if (rs->use_dma) {
		if (rs->tx)
			dmacr |= TF_DMA_EN;
		if (rs->rx)
			dmacr |= RF_DMA_EN;
	}

	if (WARN_ON(rs->speed > MAX_SCLK_OUT))
		rs->speed = MAX_SCLK_OUT;

	/* the minimum divisor is 2 */
	if (rs->max_freq < 2 * rs->speed) {
		clk_set_rate(rs->spiclk, 2 * rs->speed);    //设置时钟频率
		rs->max_freq = clk_get_rate(rs->spiclk);
	}

	/* div doesn't support odd number */
	div = DIV_ROUND_UP(rs->max_freq, rs->speed);
	div = (div + 1) & 0xfffe;

	/*
	 * If speed is larger than IO_DRIVER_4MA_MAX_SCLK_OUT,
	 * set higher driver strength.
	 */
	if (rs->high_speed_state) {
		if (rs->speed > IO_DRIVER_4MA_MAX_SCLK_OUT)
			pinctrl_select_state(rs->dev->pins->p,
					     rs->high_speed_state);
		else
			pinctrl_select_state(rs->dev->pins->p,
					     rs->dev->pins->default_state);
	}

	/* Rx sample delay is expressed in parent clock cycles (max 3) */
	rsd = DIV_ROUND_CLOSEST(rs->rsd_nsecs * (rs->max_freq >> 8),
				1000000000 >> 8);
	if (!rsd && rs->rsd_nsecs) {
		pr_warn_once("rockchip-spi: %u Hz are too slow to express %u ns delay\n",
			     rs->max_freq, rs->rsd_nsecs);
	} else if (rsd > 3) {
		rsd = 3;
		pr_warn_once("rockchip-spi: %u Hz are too fast to express %u ns delay, clamping at %u ns\n",
			     rs->max_freq, rs->rsd_nsecs,
			     rsd * 1000000000U / rs->max_freq);
	}
	cr0 |= rsd << CR0_RSD_OFFSET;

    /* write_relaxed()往寄存器写入值 */
	writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);

	if (rs->n_bytes == 1)
		writel_relaxed(rs->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
	else if (rs->n_bytes == 2)
		writel_relaxed((rs->len / 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
	else
		writel_relaxed((rs->len * 2) - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);

	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR);
	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);

	writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_DMATDLR);
	writel_relaxed(rockchip_spi_calc_burst_size(rs->len / rs->n_bytes) - 1,
		       rs->regs + ROCKCHIP_SPI_DMARDLR);
	writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);

	spi_set_clk(rs, div);     //设置分频系数

	dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div);
}

9、如果想通过GPIO模拟的方式来控制对应的GPIO管脚,也可以在dts中关闭对应引脚的spi模式并复用为GPIO口后,通过gpio模拟的方式达到自己需要的功能;

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值