开发板为 tinker board 2s ,rk3399。
使用的设备树如下:
&spi5 {
status = "okay";
max-freq = <48000000>; //spi internal clk, don't modify
spi_dev@0 {
compatible = "myspidev";
reg = <0>;
spi-max-frequency = <40000000>;
led-gpios = <&gpio3 31 GPIO_ACTIVE_HIGH>;
reset-gpios = <&gpio3 27 GPIO_ACTIVE_HIGH>;
cs-gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>;
spi-msb-first;
};
};
我们使用的是 spi 总线5 。
将开发板上的物理13引脚和物理15号引脚对接。
驱动代码如下:
include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/cdev.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/spi/spi.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/delay.h>
/**
* When you have only one slave, then you can directly connect the SS/CS pin to the ground if your slave permits it.
*
* https://embetronicx.com/tutorials/tech_devices/spi-serial-peripheral-interface-protocol-basics/
*
* https://www.cnblogs.com/tansuoxinweilai/p/11405029.html
*
*
*/
static struct spi_device *my_spi_device;
int my_spi_write(void) {
const u8 data = 0xe3;
int ret = -1;
u8 rx = 0x00;
struct spi_transfer tr = { .tx_buf = &data, .rx_buf = &rx, .len = 1, };
dev_info(&my_spi_device->dev, "rx = %d.\n", rx);
ret = spi_sync_transfer(my_spi_device, &tr, 1);
if (ret) {
pr_err("spi_sync_transfer failed\n");
return ret;
}
dev_info(&my_spi_device->dev, "spi_sync_transfer ret = %d\n", ret);
dev_info(&my_spi_device->dev, "rx = %d.\n", rx);
if (rx == data)
dev_info(&my_spi_device->dev, "spi_sync_transfer success \n");
else
dev_info(&my_spi_device->dev, "spi_sync_transfer failed \n");
return 0;
}
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "myspidev" }, { }, };
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
int my_probe(struct spi_device *spi) {
my_spi_device = spi;
dev_info(&spi->dev, "my_probe start.\n");
dev_info(&spi->dev, "master->bus_num = %d\n", spi->master->bus_num);
dev_info(&spi->dev, "chip_select = %d\n", spi->chip_select);
dev_info(&spi->dev, "bits_per_word = %d\n", spi->bits_per_word);
return my_spi_write();;
}
int my_remove(struct spi_device *spi) {
dev_info(&spi->dev, "my_remove start.\n");
return 0;
}
static struct spi_driver spidev_spi_driver = { .driver = { .name = "myspidev",
.of_match_table = of_match_ptr(spidev_dt_ids), }, .probe = my_probe,
.remove = my_remove, };
module_spi_driver(spidev_spi_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andy");
MODULE_DESCRIPTION("A sample c driver");