[Mod] 目录结构调整,按驱动类型
This commit is contained in:
70
03-Bus/03-SPI/01-NFC_PN5180/Makefile
Normal file
70
03-Bus/03-SPI/01-NFC_PN5180/Makefile
Normal file
@ -0,0 +1,70 @@
|
||||
#------------------------------------------------------------------------------#
|
||||
# All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Description :
|
||||
# Note : gaoyang3513@163.com Modified 202x.01.01
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Path information
|
||||
#------------------------------------------------------------------------------#
|
||||
# Top directories
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
KERNEL_DIR ?= $(realpath $(LOCAL_DIR)/../../../../../linux_5.10/build/kernel_output)
|
||||
|
||||
# Subdirectories
|
||||
|
||||
# Output directories
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Variables
|
||||
#------------------------------------------------------------------------------#
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Compile configure
|
||||
#------------------------------------------------------------------------------#
|
||||
export ARCH ?= riscv
|
||||
export CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Targets
|
||||
#------------------------------------------------------------------------------#
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-m += pn5180.o
|
||||
|
||||
else
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
|
||||
all: init
|
||||
@$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES)
|
||||
# @$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private
|
||||
|
||||
clean:
|
||||
# File
|
||||
@for n in *.o *.ko *.mod.c *.mod *.cmd *.symvers *.order; do \
|
||||
find $(LOCAL_DIR) -type f -name $$n -exec rm {} \;;\
|
||||
done
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
@if [ -d $(LOCAL_DIR)/.tmp_versions ]; then rm -rf $(LOCAL_DIR)/.tmp_versions; fi;
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
75
03-Bus/03-SPI/01-NFC_PN5180/pn5180.c
Normal file
75
03-Bus/03-SPI/01-NFC_PN5180/pn5180.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define IS_USE_STATIC_PLATFORM_DATA 0
|
||||
|
||||
struct CHIP {
|
||||
struct spi_device *spi;
|
||||
};
|
||||
|
||||
#if IS_USE_STATIC_PLATFORM_DATA
|
||||
struct CHIP_platform_data {
|
||||
int spi_ch;
|
||||
};
|
||||
#endif // IS_USE_STATIC_PLATFORM_DATA
|
||||
|
||||
static int CHIP_probe(struct spi_device *spi)
|
||||
{
|
||||
struct CHIP *chip;
|
||||
#if IS_USE_STATIC_PLATFORM_DATA
|
||||
struct CHIP_platform_data *pdata;
|
||||
|
||||
/* assuming the driver requires board-specific data: */
|
||||
pdata = (struct CHIP_platform_data *)&spi->dev.platform_data;
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
#endif // IS_USE_STATIC_PLATFORM_DATA
|
||||
|
||||
/* get memory for driver's per-chip state */
|
||||
chip = kzalloc(sizeof *chip, GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CHIP_remove(struct spi_device *spi)
|
||||
{
|
||||
struct CHIP *chip = NULL;
|
||||
|
||||
chip = (struct CHIP *)spi_get_drvdata(spi);
|
||||
|
||||
kfree(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id CHIP_of_match[] = {
|
||||
{ .compatible = "nxp,pn5180", },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, CHIP_of_match); // Used by file2alias, which indicated what devices are support with this drive.
|
||||
#endif // CONFIG_OF
|
||||
|
||||
static struct spi_driver CHIP_driver = {
|
||||
.driver = {
|
||||
.name = "CHIP",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_OF
|
||||
.of_match_table = CHIP_of_match,
|
||||
#endif // CONFIG_OF
|
||||
},
|
||||
.probe = CHIP_probe,
|
||||
.remove = CHIP_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(CHIP_driver);
|
||||
|
||||
MODULE_AUTHOR("Gao yang <gaoyang3513@163.com>");
|
||||
MODULE_DESCRIPTION("NXP PN5180 NFC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
70
03-Bus/03-SPI/02-Sub1G_CMT2301/Makefile
Normal file
70
03-Bus/03-SPI/02-Sub1G_CMT2301/Makefile
Normal file
@ -0,0 +1,70 @@
|
||||
#------------------------------------------------------------------------------#
|
||||
# All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Description :
|
||||
# Note : gaoyang3513@163.com Modified 202x.01.01
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Path information
|
||||
#------------------------------------------------------------------------------#
|
||||
# Top directories
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
KERNEL_DIR ?= $(realpath $(LOCAL_DIR)/../../../../../linux_5.10/build/kernel_output)
|
||||
|
||||
# Subdirectories
|
||||
|
||||
# Output directories
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Variables
|
||||
#------------------------------------------------------------------------------#
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Compile configure
|
||||
#------------------------------------------------------------------------------#
|
||||
export ARCH ?= riscv
|
||||
export CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Targets
|
||||
#------------------------------------------------------------------------------#
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-m += cmt2301.o
|
||||
|
||||
else
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
|
||||
all: init
|
||||
@$(MAKE) modules -C $(KERNEL_DIR) M=$(LOCAL_DIR) -j$(MULTI_CORES)
|
||||
# @$(MAKE) modules_install -C $(KERNEL_DIR) M=$(LOCAL_DIR) INSTALL_MOD_PATH=$(KERNEL_DIR)/_install_modules INSTALL_MOD_DIR=private
|
||||
|
||||
clean:
|
||||
# File
|
||||
@for n in *.o *.ko *.mod.c *.mod *.cmd *.symvers *.order; do \
|
||||
find $(LOCAL_DIR) -type f -name $$n -exec rm {} \;;\
|
||||
done
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
@if [ -d $(LOCAL_DIR)/.tmp_versions ]; then rm -rf $(LOCAL_DIR)/.tmp_versions; fi;
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
endif # ifeq ($(KERNELRELEASE),)
|
||||
75
03-Bus/03-SPI/02-Sub1G_CMT2301/cmt2301.c
Normal file
75
03-Bus/03-SPI/02-Sub1G_CMT2301/cmt2301.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#define IS_USE_STATIC_PLATFORM_DATA 0
|
||||
|
||||
struct CHIP {
|
||||
struct spi_device *spi;
|
||||
};
|
||||
|
||||
#if IS_USE_STATIC_PLATFORM_DATA
|
||||
struct CHIP_platform_data {
|
||||
int spi_ch;
|
||||
};
|
||||
#endif // IS_USE_STATIC_PLATFORM_DATA
|
||||
|
||||
static int CHIP_probe(struct spi_device *spi)
|
||||
{
|
||||
struct CHIP *chip;
|
||||
#if IS_USE_STATIC_PLATFORM_DATA
|
||||
struct CHIP_platform_data *pdata;
|
||||
|
||||
/* assuming the driver requires board-specific data: */
|
||||
pdata = (struct CHIP_platform_data *)&spi->dev.platform_data;
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
#endif // IS_USE_STATIC_PLATFORM_DATA
|
||||
|
||||
/* get memory for driver's per-chip state */
|
||||
chip = kzalloc(sizeof *chip, GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
spi_set_drvdata(spi, chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CHIP_remove(struct spi_device *spi)
|
||||
{
|
||||
struct CHIP *chip = NULL;
|
||||
|
||||
chip = (struct CHIP *)spi_get_drvdata(spi);
|
||||
|
||||
kfree(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id CHIP_of_match[] = {
|
||||
{ .compatible = "nxp,pn5180", },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, CHIP_of_match); // Used by file2alias, which indicated what devices are support with this drive.
|
||||
#endif // CONFIG_OF
|
||||
|
||||
static struct spi_driver CHIP_driver = {
|
||||
.driver = {
|
||||
.name = "CHIP",
|
||||
.owner = THIS_MODULE,
|
||||
#ifdef CONFIG_OF
|
||||
.of_match_table = CHIP_of_match,
|
||||
#endif // CONFIG_OF
|
||||
},
|
||||
.probe = CHIP_probe,
|
||||
.remove = CHIP_remove,
|
||||
};
|
||||
|
||||
module_spi_driver(CHIP_driver);
|
||||
|
||||
MODULE_AUTHOR("Gao yang <gaoyang3513@163.com>");
|
||||
MODULE_DESCRIPTION("NXP PN5180 NFC driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
76
03-Bus/03-SPI/Makefile
Normal file
76
03-Bus/03-SPI/Makefile
Normal file
@ -0,0 +1,76 @@
|
||||
#------------------------------------------------------------------------------#
|
||||
# All Right Reserved.
|
||||
# Author :
|
||||
# Version : V1.0.0 202x.01.01
|
||||
# Description :
|
||||
# Note : gaoyang3513@163.com Modified 202x.01.01
|
||||
#------------------------------------------------------------------------------#
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Path information
|
||||
#------------------------------------------------------------------------------#
|
||||
LOCAL_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
# Subdirectory
|
||||
PN5180_DIR := $(LOCAL_DIR)/01-NFC_PN5180
|
||||
CMT2301_DIR := $(LOCAL_DIR)/02-Sub1G_CMT2301
|
||||
|
||||
OUTPUT_DIR := $(LOCAL_DIR)/output
|
||||
INSTALL_DIR ?= $(LOCAL_DIR)/__install
|
||||
#$(info Output directoty : $(OUTPUT_DIR))
|
||||
#$(info Install directoty: $(INSTALL_DIR))
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Variables
|
||||
#------------------------------------------------------------------------------#
|
||||
MULTI_CORES ?= $(shell grep -c ^processor /proc/cpuinfo)
|
||||
|
||||
SUB_DIRS := $(CMT2301_DIR) $(PN5180_DIR)
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Compile configure
|
||||
#------------------------------------------------------------------------------#
|
||||
ARCH ?= riscv
|
||||
CROSS_COMPILE ?= riscv64-unknown-linux-musl-
|
||||
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
LD := $(CROSS_COMPILE)ld
|
||||
AR := $(CROSS_COMPILE)ar
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
|
||||
export ARCH CROSS_COMPILE
|
||||
|
||||
#------------------------------------------------------------------------------#
|
||||
# Targets
|
||||
#------------------------------------------------------------------------------#
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
# called from kernel build system: just declare what our modules are
|
||||
obj-y += $(SUB_DIRS)
|
||||
|
||||
#INC_DIRS := $(INCLUDE_DIR)/generated
|
||||
#subdir-ccflags-y += $(addprefix -I, $(INC_DIRS))
|
||||
|
||||
else # !KERNELRELEASE
|
||||
.PHONY: init all clean distclean install menuconfig
|
||||
|
||||
all: init
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) -C $$sub; \
|
||||
$(MAKE) install INSTALL_DIR=$(OUTPUT_DIR) -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
|
||||
clean:
|
||||
@for sub in $(SUB_DIRS); do \
|
||||
$(MAKE) clean -C $$sub || exit "$$?"; \
|
||||
done;
|
||||
# Directory
|
||||
@if [ -d $(LOCAL_DIR)/output ]; then rm -rf $(LOCAL_DIR)/output; fi;
|
||||
@if [ -d $(LOCAL_DIR)/__install ]; then rm -rf $(LOCAL_DIR)/__install; fi;
|
||||
|
||||
install:
|
||||
@mkdir -p $(INSTALL_DIR)
|
||||
@cp -arf $(OUTPUT_DIR)/. $(INSTALL_DIR)
|
||||
|
||||
init:
|
||||
@mkdir -p $(OUTPUT_DIR);
|
||||
endif # !KERNELRELEASE
|
||||
333
03-Bus/03-SPI/ReadMe.md
Normal file
333
03-Bus/03-SPI/ReadMe.md
Normal file
@ -0,0 +1,333 @@
|
||||
|
||||
|
||||
|
||||
## 参考
|
||||
|
||||
- linux_5.10/Documentation/spi/spi-summary.rst
|
||||
|
||||
|
||||
## 概念
|
||||
|
||||
### 工作原理
|
||||
|
||||
SPI 请求将提交至IO对列。这些请求按照“先进先出(FIFO)”原则执行,在完成后将通过回调方式告知。
|
||||
当然,也有一些简单的异步封装回调方法,包含发送命令并接收应答的一类接口。
|
||||
|
||||
### 两种SPI驱动
|
||||
|
||||
#### Controller drivers ...
|
||||
|
||||
此类驱动的对象为SOC片上的SPI控制器,这些控制器通常支持“Master”与“Slave”角色切换。
|
||||
此类驱动常直接访问硬件寄存器并使用DMA来提高数据传递效率,或许也可以通过CPU控制数据的每一位来控制可编程GPIO管脚。
|
||||
|
||||
#### Protocol drivers ...
|
||||
|
||||
此类驱动的对象为SOC片外接的SPI设备,这些设备以“Master”或“Slave”角色接入SPI控制器,进而完成数据的传输。
|
||||
在SPI驱动之上,可能被具象化为MTD、Audio等设备接入更上一级的子系统。
|
||||
|
||||
### 数据结构
|
||||
|
||||
`struct spi_device` 结构体是两种驱动的基类。
|
||||
|
||||
```c
|
||||
#---- linux_5.10/include/linux/spi/spi.h
|
||||
struct spi_device {
|
||||
struct device dev;
|
||||
struct spi_controller *controller;
|
||||
struct spi_controller *master; /* compatibility layer */
|
||||
...
|
||||
```
|
||||
|
||||
### 框架
|
||||
|
||||
input layer, ALSA, networking, MTD, the character device framework,
|
||||
or other Linux subsystems.
|
||||
|
||||
### Messages
|
||||
|
||||
If you like, spi_message_alloc() and spi_message_free() convenience
|
||||
|
||||
### 内存管理
|
||||
|
||||
SPI设备必须管理以下两种类型内存:
|
||||
|
||||
- I/O 数据;
|
||||
|
||||
- spi_message\spi_transfer数据;
|
||||
可以使用spi_message_alloc()、spi_message_free()代为管理。
|
||||
|
||||
|
||||
## 示例
|
||||
|
||||
### 设备
|
||||
|
||||
#### 板级静态定义
|
||||
|
||||
##### Master
|
||||
|
||||
- `struct platform_device`, 基于平台设备开发;
|
||||
|
||||
路径:`arch/.../mach-*/board-*.c`:
|
||||
|
||||
```c
|
||||
#include <mach/spi.h> /* for mysoc_spi_data */
|
||||
|
||||
/* if your mach-* infrastructure doesn't support kernels that can
|
||||
* run on multiple boards, pdata wouldn't benefit from "__init".
|
||||
*/
|
||||
static struct mysoc_spi_data pdata __initdata = { ... };
|
||||
|
||||
static __init board_init(void)
|
||||
{
|
||||
...
|
||||
/* this board only uses SPI controller #2 */
|
||||
mysoc_register_spi(2, &pdata);
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
```c
|
||||
#include <mach/spi.h>
|
||||
|
||||
static struct platform_device spi2 = { ... };
|
||||
|
||||
void mysoc_register_spi(unsigned n, struct mysoc_spi_data *pdata)
|
||||
{
|
||||
struct mysoc_spi_data *pdata2;
|
||||
|
||||
pdata2 = kmalloc(sizeof *pdata2, GFP_KERNEL);
|
||||
*pdata2 = pdata;
|
||||
...
|
||||
if (n == 2) {
|
||||
spi2->dev.platform_data = pdata2;
|
||||
register_platform_device(&spi2);
|
||||
|
||||
/* also: set up pin modes so the spi2 signals are
|
||||
* visible on the relevant pins ... bootloaders on
|
||||
* production boards may already have done this, but
|
||||
* developer boards will often need Linux to do it.
|
||||
*/
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
##### Slave
|
||||
|
||||
文件:`arch/.../mach-*/board-*.c`:
|
||||
|
||||
```c
|
||||
static struct ads7846_platform_data ads_info = {
|
||||
.vref_delay_usecs = 100,
|
||||
.x_plate_ohms = 580,
|
||||
.y_plate_ohms = 410,
|
||||
};
|
||||
|
||||
static struct spi_board_info spi_board_info[] __initdata = {
|
||||
{
|
||||
.modalias = "ads7846",
|
||||
.platform_data = &ads_info,
|
||||
.mode = SPI_MODE_0,
|
||||
.irq = GPIO_IRQ(31),
|
||||
.max_speed_hz = 120000 /* max sample rate at 3V */ * 16,
|
||||
.bus_num = 1,
|
||||
.chip_select = 0,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
```c
|
||||
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
|
||||
```
|
||||
|
||||
#### DTS动态定义
|
||||
|
||||
##### Master
|
||||
|
||||
```dts
|
||||
#---- build/boards/default/dts/cv181x/cv181x_base.dtsi
|
||||
/ {
|
||||
spi3:spi3@041B0000 {
|
||||
interrupts = <57 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&plic0>;
|
||||
};
|
||||
...
|
||||
```
|
||||
|
||||
##### Slave
|
||||
|
||||
- 独占总线
|
||||
|
||||
```dts
|
||||
#---- build/boards/default/dts/cv181x/cv181x_asic_bga.dtsi
|
||||
&spi3 {
|
||||
status = "okay";
|
||||
num-cs = <1>;
|
||||
spidev@0 {
|
||||
compatible = "rohm,dh2228fv";
|
||||
spi-max-frequency = <1000000>;
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
#---- build/boards/cv181x/cv1813h_milkv_duos_sd/dts_riscv/cv1813h_milkv_duos_sd.dts
|
||||
&spi3 {
|
||||
status = "okay";
|
||||
|
||||
spidev@0 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
- 多设备
|
||||
|
||||
参考内核文档:
|
||||
|
||||
1. linux_5.10/Documentation/devicetree/bindings/spi/spi-bus.txt;
|
||||
2. linux_5.10/arch/arm/boot/dts/imx6ul-imx6ull-opos6uldev.dtsi
|
||||
|
||||
```dts
|
||||
#---- linux_5.10/arch/arm/boot/dts/imx6ull-opos6uldev.dts
|
||||
/dts-v1/;
|
||||
#include "imx6ull-opos6ul.dtsi" # 1
|
||||
# include "imx6ul.dtsi" # 1.1
|
||||
#include "imx6ul-imx6ull-opos6uldev.dtsi" # 2
|
||||
|
||||
/ {
|
||||
model = "Armadeus Systems OPOS6UL SoM (i.MX6ULL) on OPOS6ULDev board";
|
||||
compatible = "armadeus,imx6ull-opos6uldev", "armadeus,imx6ull-opos6ul", "fsl,imx6ull";
|
||||
};
|
||||
|
||||
#1.1- linux_5.10/arch/arm/boot/dts/imx6ul.dtsi
|
||||
/ {
|
||||
...
|
||||
soc {
|
||||
...
|
||||
aips1: bus@2000000 {
|
||||
...
|
||||
spba-bus@2000000 {
|
||||
...
|
||||
ecspi4: spi@2014000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
|
||||
reg = <0x02014000 0x4000>;
|
||||
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clks IMX6UL_CLK_ECSPI4>,
|
||||
<&clks IMX6UL_CLK_ECSPI4>;
|
||||
clock-names = "ipg", "per";
|
||||
dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
#2--- linux_5.10/arch/arm/boot/dts/imx6ul-imx6ull-opos6uldev.dtsi
|
||||
&ecspi4 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_ecspi4>;
|
||||
num-cs = 2;
|
||||
cs-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>, <&gpio4 3 GPIO_ACTIVE_LOW>;
|
||||
status = "okay";
|
||||
|
||||
spidev0: spi@0 {
|
||||
compatible = "spidev";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <5000000>;
|
||||
};
|
||||
|
||||
spidev1: spi@1 {
|
||||
compatible = "spidev";
|
||||
reg = <1>;
|
||||
spi-max-frequency = <5000000>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
#### 总结
|
||||
|
||||
1. `spi-max-frequency`,多通道时,需要定义设备允许的最大速率;---- 待确认;
|
||||
|
||||
### 驱动
|
||||
|
||||
- `spi_busnum_to_master()`, 查找目标SPI控制器;
|
||||
- `spi_new_device()`, 创建;
|
||||
- `spi_unregister_device()`销毁;
|
||||
|
||||
#### SPI Controller Driver
|
||||
|
||||
```c
|
||||
struct spi_master *master;
|
||||
struct CONTROLLER *c;
|
||||
|
||||
master = spi_alloc_master(dev, sizeof *c);
|
||||
if (!master)
|
||||
return -ENODEV;
|
||||
|
||||
c = spi_master_get_devdata(master);
|
||||
```
|
||||
|
||||
- `spi_[un]register_master()`注册至系统;
|
||||
|
||||
master操作集
|
||||
|
||||
- `master->setup(struct spi_device *spi)`, clock rate, SPI mode, and word sizes.
|
||||
- `master->cleanup(struct spi_device *spi)`, 清除之前由`spi_device.controller_state`锁定的状态;
|
||||
...
|
||||
- `master->transfer_one_message(struct spi_master *master, struct spi_message *mesg)`, 发送一个mesg;
|
||||
|
||||
#### SPI Protocol Driver
|
||||
|
||||
```c
|
||||
static int CHIP_probe(struct spi_device *spi)
|
||||
{
|
||||
struct CHIP *chip;
|
||||
struct CHIP_platform_data *pdata;
|
||||
|
||||
/* assuming the driver requires board-specific data: */
|
||||
pdata = &spi->dev.platform_data;
|
||||
if (!pdata)
|
||||
return -ENODEV;
|
||||
|
||||
/* get memory for driver's per-chip state */
|
||||
chip = kzalloc(sizeof *chip, GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
spi_set_drvdata(spi, chip);
|
||||
|
||||
... etc
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver CHIP_driver = {
|
||||
.driver = {
|
||||
.name = "CHIP",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &CHIP_pm_ops,
|
||||
},
|
||||
|
||||
.probe = CHIP_probe,
|
||||
.remove = CHIP_remove,
|
||||
};
|
||||
```
|
||||
|
||||
spi_setup(),
|
||||
|
||||
## 属性
|
||||
|
||||
- `spi_message.is_dma_mapped`,
|
||||
|
||||
## 调试
|
||||
|
||||
#### sys节点
|
||||
|
||||
- `/sys/bus/spi/devices/spiB.C` 总线B,设备C, 都是从0开始编号;
|
||||
- `/sys/class/spi_master/spiB` spi_master类,总线B;
|
||||
- `/sys/class/spi_slave/spiB`
|
||||
|
||||
|
||||
## 备注
|
||||
|
||||
- `master->transfer(struct spi_device *spi, struct spi_message *message)`,
|
||||
1. 已经被弃用;
|
||||
2. 可以打断IO对列,提前发送;
|
||||
Reference in New Issue
Block a user