[PATCH -next 09/14] kddv/core: Add test support for SPI driver

From: Zhang Xiaoxu
Date: Sat Nov 18 2023 - 05:42:18 EST


From: Zhang Xiaoxu <zhangxiaoxu5@xxxxxxxxxx>

The spi driver test case should inherit the 'SPIDriverTest'
and config the driver as below:

MAX31722_REG_CFG = 0x00
MAX31722_RESOLUTION_12BIT = 0x06

class TestMax31722(SPIDriverTest):
name = 'max31722'

@property
def regbytes(self):
return 1

@property
def valbytes(self):
return 1

@property
def configs(self):
return { CFG_REG_MASK: 0x7f }

def test_device_probe(self):
with self.assertRaisesFault():
with self.device() as dev:
self.assertRegEqual(MAX31722_REG_CFG,
MAX31722_RESOLUTION_12BIT)

The kddv can auto load the 'spi-xfer-r{regbytes}v{valbytes}.o' bpf
program as the mock device chipsets.

Signed-off-by: Wei Yongjun <weiyongjun1@xxxxxxxxxx>
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu@xxxxxxxxxx>
---
tools/testing/kddv/kddv/Makefile | 5 +
tools/testing/kddv/kddv/core/__init__.py | 6 ++
.../testing/kddv/kddv/core/buses/__init__.py | 13 +++
tools/testing/kddv/kddv/core/buses/spi.py | 74 ++++++++++++++
tools/testing/kddv/kddv/core/mockup.py | 8 ++
tools/testing/kddv/kddv/data/Makefile | 21 ++++
tools/testing/kddv/kddv/data/bpf/Makefile | 22 +++++
.../kddv/kddv/data/bpf/spi/spi-xfer-base.h | 99 +++++++++++++++++++
.../kddv/kddv/data/bpf/spi/spi-xfer-r1v1.c | 51 ++++++++++
.../kddv/kddv/data/bpf/spi/spi-xfer-r1v2.c | 51 ++++++++++
.../kddv/kddv/data/bpf/spi/spi-xfer-r1v3.c | 86 ++++++++++++++++
.../kddv/kddv/data/bpf/spi/spi-xfer-r2v1.c | 51 ++++++++++
.../kddv/kddv/data/bpf/spi/spi-xfer-r2v2.c | 51 ++++++++++
.../kddv/kddv/data/bpf/spi/spi-xfer-r3v1.c | 52 ++++++++++
.../kddv/kddv/data/bpf/spi/spi-xfer-r4v4.c | 89 +++++++++++++++++
15 files changed, 679 insertions(+)
create mode 100755 tools/testing/kddv/kddv/core/buses/__init__.py
create mode 100755 tools/testing/kddv/kddv/core/buses/spi.py
create mode 100644 tools/testing/kddv/kddv/data/Makefile
create mode 100644 tools/testing/kddv/kddv/data/bpf/Makefile
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-base.h
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v1.c
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v2.c
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v3.c
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v1.c
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v2.c
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r3v1.c
create mode 100644 tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r4v4.c

diff --git a/tools/testing/kddv/kddv/Makefile b/tools/testing/kddv/kddv/Makefile
index a5c91fcb0e9a..b7a12069e443 100644
--- a/tools/testing/kddv/kddv/Makefile
+++ b/tools/testing/kddv/kddv/Makefile
@@ -2,6 +2,7 @@
include ../../../scripts/Makefile.include

INSTALL ?= install
+SUBDIRS := data

all:
@for SUBDIR in $(SUBDIRS); do \
@@ -15,6 +16,10 @@ install:
cp -rf cmds/ $(INSTALL_PATH)
cp -rf tests/ $(INSTALL_PATH)

+ @for SUBDIR in $(SUBDIRS); do \
+ $(MAKE) INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR -C $$SUBDIR install; \
+ done;
+
clean:
@for SUBDIR in $(SUBDIRS); do \
$(MAKE) -C $$SUBDIR clean; \
diff --git a/tools/testing/kddv/kddv/core/__init__.py b/tools/testing/kddv/kddv/core/__init__.py
index 45a35c909e86..601464c0e9ed 100755
--- a/tools/testing/kddv/kddv/core/__init__.py
+++ b/tools/testing/kddv/kddv/core/__init__.py
@@ -5,3 +5,9 @@
#
# Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
# Author: Wei Yongjun <weiyongjun1@xxxxxxxxxx>
+
+__all__ = [
+ 'SPIDriverTest',
+]
+
+from .buses import SPIDriverTest
diff --git a/tools/testing/kddv/kddv/core/buses/__init__.py b/tools/testing/kddv/kddv/core/buses/__init__.py
new file mode 100755
index 000000000000..1cbd4bed181a
--- /dev/null
+++ b/tools/testing/kddv/kddv/core/buses/__init__.py
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# Kernel device driver verification
+#
+# Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+# Author: Wei Yongjun <weiyongjun1@xxxxxxxxxx>
+
+__all__ = [
+ 'SPIDriverTest',
+]
+
+from .spi import SPIDriverTest
diff --git a/tools/testing/kddv/kddv/core/buses/spi.py b/tools/testing/kddv/kddv/core/buses/spi.py
new file mode 100755
index 000000000000..13c96de5b7bd
--- /dev/null
+++ b/tools/testing/kddv/kddv/core/buses/spi.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# Kernel device driver verification
+#
+# Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+# Author: Wei Yongjun <weiyongjun1@xxxxxxxxxx>
+
+import logging
+
+from pathlib import Path
+
+from ..ddunit import DriverTest
+from ..device import Device
+from ..mockup import Mockup
+
+logger = logging.getLogger(__name__)
+
+class SPIDriverTest(DriverTest):
+ bus = 'spi'
+
+ @property
+ def bpf(self):
+ return f'spi-xfer-r{self.regbytes}v{self.valbytes}'
+
+class SPIDevice(Device):
+ bus = 'spi'
+
+ @property
+ def device_id(self):
+ return f"{self.bus}{self.busid}.{self.addr}"
+
+SPI_MASTER_PATH = '/sys/class/spi_master/spi0'
+
+class SPIMockup(Mockup):
+ bus = 'spi'
+ host = Path('/sys/kernel/config/spi-mockup/spi0')
+ live = Path('/sys/kernel/config/spi-mockup/spi0/live')
+
+ def setup(self):
+ logger.debug('setup')
+ if not self.host.exists():
+ self.host.mkdir()
+
+ self.live.write_text('true')
+
+ def teardown(self):
+ logger.debug('spi mockup teardown')
+ self.live.write_text('false')
+ self.host.rmdir()
+
+ @property
+ def device_id(self):
+ return f"{self.devid} {self.addr}"
+
+ def create_device(self):
+ logger.debug(f'new device {self.devid} to spi bus')
+ dev = Path(f'/sys/kernel/config/spi-mockup/spi0/targets/{self.devid}')
+ if not dev.exists():
+ dev.mkdir()
+ device_id = Path(f'/sys/kernel/config/spi-mockup/spi0/targets/{self.devid}/device_id')
+ device_id.write_text(self.devid)
+
+ device_live = Path(f'/sys/kernel/config/spi-mockup/spi0/targets/{self.devid}/live')
+ device_live.write_text('true')
+
+ def remove_device(self):
+ logger.debug(f'delete device {self.devid} from spi bus')
+ logger.debug(f'delete device {self.devid} to spi bus')
+ device_live = Path(f'/sys/kernel/config/spi-mockup/spi0/targets/{self.devid}/live')
+ device_live.write_text('false')
+ dev = Path(f'/sys/kernel/config/spi-mockup/spi0/targets/{self.devid}')
+ dev.rmdir()
+
diff --git a/tools/testing/kddv/kddv/core/mockup.py b/tools/testing/kddv/kddv/core/mockup.py
index 8bea2db97232..cf23dd711ca0 100755
--- a/tools/testing/kddv/kddv/core/mockup.py
+++ b/tools/testing/kddv/kddv/core/mockup.py
@@ -101,7 +101,14 @@ class Mockup(object):
def remove_device(self):
pass

+ def setup(self):
+ pass
+
+ def teardown(self):
+ pass
+
def load(self):
+ self.setup()
self.load_bpf()
self.load_regmaps()
self.load_configs()
@@ -110,6 +117,7 @@ class Mockup(object):
def unload(self):
self.remove_device()
self.unload_bpf()
+ self.teardown()

def bpf_map_name(self):
bpf_name = re.sub("-", "_", self.bpf)
diff --git a/tools/testing/kddv/kddv/data/Makefile b/tools/testing/kddv/kddv/data/Makefile
new file mode 100644
index 000000000000..0e82984b99a9
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/Makefile
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0
+include ../../../../scripts/Makefile.include
+
+SUBDIRS := bpf
+
+all:
+ @for SUBDIR in $(SUBDIRS); do \
+ $(MAKE) -C $$SUBDIR;\
+ done;
+
+install:
+ @for SUBDIR in $(SUBDIRS); do \
+ $(MAKE) INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR -C $$SUBDIR install;\
+ done;
+
+clean:
+ @for SUBDIR in $(SUBDIRS); do \
+ $(MAKE) -C $$SUBDIR clean;\
+ done;
+
+.PHONY: all install clean
diff --git a/tools/testing/kddv/kddv/data/bpf/Makefile b/tools/testing/kddv/kddv/data/bpf/Makefile
new file mode 100644
index 000000000000..f693f8da1034
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+include ../../../../../scripts/Makefile.include
+
+CC = clang
+INSTALL ?= install
+
+bpf-objs-y := $(patsubst %.c,%.o,$(wildcard */*.c))
+
+CFLAGS += -I../../../../../bpf/bpftool/ -I../../../../../bpf/bpftool/libbpf/include
+CFLAGS += -Iinclude -Ispi
+
+all: $(bpf-objs-y)
+
+%.o: %.c
+ $(CC) -target bpf -Wall -O2 $(CFLAGS) -g -c $< -o $@
+
+install:
+ $(INSTALL) -m 0755 -d $(INSTALL_PATH)
+ $(INSTALL) $(bpf-objs-y) $(INSTALL_PATH)
+
+clean:
+ rm -rf $(bpf-objs-y)
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-base.h b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-base.h
new file mode 100644
index 000000000000..8a33e6049dbc
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-base.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * The spi xfer helpers for bpf program
+ *
+ * Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+ */
+
+#ifndef __SPI_XFER_BASE_
+#define __SPI_XFER_BASE_
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+
+int spi_xfer_read_u8(struct spi_msg_ctx *msg, unsigned int len,
+ void *map, unsigned int reg, int offset)
+{
+ unsigned int i, key = reg;
+ u8 *value;
+
+ for (i = offset; i < len && i < sizeof(msg->data); i++, key++) {
+ value = bpf_map_lookup_elem(map, &key);
+ if (!value) {
+ bpf_printk("key 0x%x not exists", key);
+ return -1;
+ }
+
+ msg->data[i] = *value;
+
+ bpf_printk("SPI R8 [0x%x]=0x%x", key, msg->data[i]);
+ }
+
+ return 0;
+}
+
+int spi_xfer_write_u8(struct spi_msg_ctx *msg, unsigned int len,
+ void *map, unsigned int reg, int offset)
+{
+ unsigned int i, key = reg;
+ u8 value;
+
+ for (i = offset; i < len && i < sizeof(msg->data); i++, key++) {
+ value = msg->data[i];
+
+ if (bpf_map_update_elem(map, &key, &value, BPF_EXIST)) {
+ bpf_printk("key 0x%x not exists", key);
+ return -1;
+ }
+
+ bpf_printk("SPI W8 [0x%x]=0x%x [%u/%u]", key, value, i, len);
+ }
+
+ return 0;
+}
+
+int spi_xfer_read_u16(struct spi_msg_ctx *msg, unsigned int len,
+ void *map, unsigned int reg, int offset)
+{
+ unsigned int i, key = reg;
+ u16 *value;
+
+ for (i = offset; i < len && i < sizeof(msg->data) - 1; i += 2, key++) {
+ value = bpf_map_lookup_elem(map, &key);
+ if (!value) {
+ bpf_printk("key 0x%x not exists", key);
+ return -1;
+ }
+
+ msg->data[i + 0] = *value >> 8;
+ msg->data[i + 1] = *value & 0xff;
+
+ bpf_printk("SPI R16 [0x%x]=0x%x [%u/%u]", key, *value, i, len);
+ }
+
+ return 0;
+}
+
+int spi_xfer_write_u16(struct spi_msg_ctx *msg, unsigned int len,
+ void *map, unsigned int reg, int offset)
+{
+ unsigned int i, key = reg;
+ u16 value;
+
+ for (i = offset; i < len && i < sizeof(msg->data) - 1; i += 2, key++) {
+ value = msg->data[i];
+ value = (value << 8) | msg->data[i + 1];
+
+ if (bpf_map_update_elem(map, &key, &value, BPF_EXIST)) {
+ bpf_printk("key 0x%x not exists", key);
+ return -1;
+ }
+
+ bpf_printk("SPI W16 [0x%x]=0x%x [%u/%u]", key, value, i, len);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v1.c b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v1.c
new file mode 100644
index 000000000000..3e7252207e23
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v1.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#include "bpf-xfer-conf.h"
+#include "spi-xfer-base.h"
+
+#define CHIP_REGS_SIZE 0x100
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, CHIP_REGS_SIZE);
+ __type(key, __u32);
+ __type(value, __u8);
+} regs_spi_xfer_r1v1 SEC(".maps");
+
+static unsigned int chip_reg;
+
+static int spi_xfer_read(struct spi_msg_ctx *msg, unsigned int len)
+{
+ return spi_xfer_read_u8(msg, len, &regs_spi_xfer_r1v1, chip_reg, 0);
+}
+
+static int spi_xfer_write(struct spi_msg_ctx *msg, unsigned int len)
+{
+ chip_reg = bpf_xfer_reg_u8(msg->data[0]);
+ return spi_xfer_write_u8(msg, len, &regs_spi_xfer_r1v1, chip_reg, 1);
+}
+
+SEC("raw_tp.w/spi_transfer_writeable")
+int BPF_PROG(spi_xfer_r1v1, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+{
+ if (bpf_xfer_should_fault()) {
+ msg->ret = -EIO;
+ return 0;
+ }
+
+ if (msg->tx_nbits)
+ msg->ret = spi_xfer_write(msg, len);
+ else if (msg->rx_nbits)
+ msg->ret = spi_xfer_read(msg, len);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v2.c b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v2.c
new file mode 100644
index 000000000000..ef9ff13a573d
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v2.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#include "bpf-xfer-conf.h"
+#include "spi-xfer-base.h"
+
+#define CHIP_REGS_SIZE 0x100
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, CHIP_REGS_SIZE);
+ __type(key, __u32);
+ __type(value, __u16);
+} regs_spi_xfer_r1v2 SEC(".maps");
+
+static unsigned int chip_reg;
+
+static int spi_xfer_read(struct spi_msg_ctx *msg, unsigned int len)
+{
+ return spi_xfer_read_u16(msg, len, &regs_spi_xfer_r1v2, chip_reg, 0);
+}
+
+static int spi_xfer_write(struct spi_msg_ctx *msg, unsigned int len)
+{
+ chip_reg = bpf_xfer_reg_u8(msg->data[0]);
+ return spi_xfer_write_u16(msg, len, &regs_spi_xfer_r1v2, chip_reg, 1);
+}
+
+SEC("raw_tp.w/spi_transfer_writeable")
+int BPF_PROG(spi_xfer_r1v2, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+{
+ if (bpf_xfer_should_fault()) {
+ msg->ret = -EIO;
+ return 0;
+ }
+
+ if (msg->tx_nbits)
+ msg->ret = spi_xfer_write(msg, len);
+ else if (msg->rx_nbits)
+ msg->ret = spi_xfer_read(msg, len);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v3.c b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v3.c
new file mode 100644
index 000000000000..b720115d16d2
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r1v3.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#include "bpf-xfer-conf.h"
+#include "spi-xfer-base.h"
+
+#define CHIP_REGS_SIZE 0x100
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, CHIP_REGS_SIZE);
+ __type(key, __u32);
+ __type(value, __u32);
+} regs_spi_xfer_r1v3 SEC(".maps");
+
+static unsigned int chip_reg;
+
+static int spi_xfer_read(struct spi_msg_ctx *msg, unsigned int len)
+{
+ unsigned int i, key = chip_reg;
+ u32 *value;
+
+ for (i = 0; i < len && i < sizeof(msg->data) - 2; i += 3, key++) {
+ value = bpf_map_lookup_elem(&regs_spi_xfer_r1v3, &key);
+ if (!value) {
+ bpf_printk("key 0x%x not exists", key);
+ return -EINVAL;
+ }
+
+ msg->data[i + 0] = (*value >> 16) & 0xff;
+ msg->data[i + 1] = (*value >> 8) & 0xff;
+ msg->data[i + 2] = *value & 0xff;
+
+ bpf_printk("SPI R24 [0x%x]=0x%x [%u/%u]", key, *value, i, len);
+ }
+
+ return 0;
+}
+
+static int spi_xfer_write(struct spi_msg_ctx *msg, unsigned int len)
+{
+ unsigned int i, key;
+ u32 value;
+
+ chip_reg = bpf_xfer_reg_u8(msg->data[0]);
+ key = chip_reg;
+
+ for (i = 1; i < len && i < sizeof(msg->data) - 2; i += 3, key++) {
+ value = msg->data[i];
+ value = (value << 8) | msg->data[i + 1];
+ value = (value << 8) | msg->data[i + 2];
+
+ if (bpf_map_update_elem(&regs_spi_xfer_r1v3, &key, &value, BPF_EXIST)) {
+ bpf_printk("key 0x%x not exists", key);
+ return -EINVAL;
+ }
+
+ bpf_printk("SPI W24 [0x%x]=0x%x", key, value);
+ }
+
+ return 0;
+}
+
+SEC("raw_tp.w/spi_transfer_writeable")
+int BPF_PROG(spi_xfer_r1v3, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+{
+ if (bpf_xfer_should_fault()) {
+ msg->ret = -EIO;
+ return 0;
+ }
+
+ if (msg->tx_nbits)
+ msg->ret = spi_xfer_write(msg, len);
+ else if (msg->rx_nbits)
+ msg->ret = spi_xfer_read(msg, len);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v1.c b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v1.c
new file mode 100644
index 000000000000..c1e7942be327
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v1.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#include "bpf-xfer-conf.h"
+#include "spi-xfer-base.h"
+
+#define CHIP_REGS_SIZE 0x1000
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, CHIP_REGS_SIZE);
+ __type(key, __u32);
+ __type(value, __u8);
+} regs_spi_xfer_r2v1 SEC(".maps");
+
+static unsigned int chip_reg;
+
+static int spi_xfer_read(struct spi_msg_ctx *msg, unsigned int len)
+{
+ return spi_xfer_read_u8(msg, len, &regs_spi_xfer_r2v1, chip_reg, 0);
+}
+
+static int spi_xfer_write(struct spi_msg_ctx *msg, unsigned int len)
+{
+ chip_reg = bpf_xfer_reg_u16(msg->data[0] << 8 | msg->data[1]);
+ return spi_xfer_write_u8(msg, len, &regs_spi_xfer_r2v1, chip_reg, 2);
+}
+
+SEC("raw_tp.w/spi_transfer_writeable")
+int BPF_PROG(spi_xfer_r2v1, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+{
+ if (bpf_xfer_should_fault()) {
+ msg->ret = -EIO;
+ return 0;
+ }
+
+ if (msg->tx_nbits)
+ msg->ret = spi_xfer_write(msg, len);
+ else if (msg->rx_nbits)
+ msg->ret = spi_xfer_read(msg, len);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v2.c b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v2.c
new file mode 100644
index 000000000000..4076722824ba
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r2v2.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#include "bpf-xfer-conf.h"
+#include "spi-xfer-base.h"
+
+#define CHIP_REGS_SIZE 0x1000
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, CHIP_REGS_SIZE);
+ __type(key, __u32);
+ __type(value, __u16);
+} regs_spi_xfer_r2v2 SEC(".maps");
+
+static unsigned int chip_reg;
+
+static int spi_xfer_read(struct spi_msg_ctx *msg, unsigned int len)
+{
+ return spi_xfer_read_u16(msg, len, &regs_spi_xfer_r2v2, chip_reg, 0);
+}
+
+static int spi_xfer_write(struct spi_msg_ctx *msg, unsigned int len)
+{
+ chip_reg = bpf_xfer_reg_u16(msg->data[0] << 8 | msg->data[1]);
+ return spi_xfer_write_u16(msg, len, &regs_spi_xfer_r2v2, chip_reg, 2);
+}
+
+SEC("raw_tp.w/spi_transfer_writeable")
+int BPF_PROG(spi_xfer_r2v2, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+{
+ if (bpf_xfer_should_fault()) {
+ msg->ret = -EIO;
+ return 0;
+ }
+
+ if (msg->tx_nbits)
+ msg->ret = spi_xfer_write(msg, len);
+ else if (msg->rx_nbits)
+ msg->ret = spi_xfer_read(msg, len);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r3v1.c b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r3v1.c
new file mode 100644
index 000000000000..7f056b8a7bdb
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r3v1.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#include "bpf-xfer-conf.h"
+#include "spi-xfer-base.h"
+
+#define CHIP_REGS_SIZE 0x1000
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, CHIP_REGS_SIZE);
+ __type(key, __u32);
+ __type(value, __u8);
+} regs_spi_xfer_r3v1 SEC(".maps");
+
+static unsigned int chip_reg;
+
+static int spi_xfer_read(struct spi_msg_ctx *msg, unsigned int len)
+{
+ return spi_xfer_read_u8(msg, len, &regs_spi_xfer_r3v1, chip_reg, 0);
+}
+
+static int spi_xfer_write(struct spi_msg_ctx *msg, unsigned int len)
+{
+ chip_reg = bpf_xfer_reg_u24((msg->data[0] << 16) | (msg->data[1] << 8) |
+ msg->data[2]);
+ return spi_xfer_write_u8(msg, len, &regs_spi_xfer_r3v1, chip_reg, 3);
+}
+
+SEC("raw_tp.w/spi_transfer_writeable")
+int BPF_PROG(spi_xfer_r3v1, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+{
+ if (bpf_xfer_should_fault()) {
+ msg->ret = -EIO;
+ return 0;
+ }
+
+ if (msg->tx_nbits)
+ msg->ret = spi_xfer_write(msg, len);
+ else if (msg->rx_nbits)
+ msg->ret = spi_xfer_read(msg, len);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
diff --git a/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r4v4.c b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r4v4.c
new file mode 100644
index 000000000000..70f839a2222a
--- /dev/null
+++ b/tools/testing/kddv/kddv/data/bpf/spi/spi-xfer-r4v4.c
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2022-2023 Huawei Technologies Co., Ltd
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <errno.h>
+
+#include "bpf-xfer-conf.h"
+#include "spi-xfer-base.h"
+
+#define CHIP_REGS_SIZE 0x8000
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, CHIP_REGS_SIZE);
+ __type(key, __u32);
+ __type(value, __u32);
+} regs_spi_xfer_r4v4 SEC(".maps");
+
+static unsigned int chip_reg;
+
+static int spi_xfer_read(struct spi_msg_ctx *msg, unsigned int len)
+{
+ unsigned int i, key = chip_reg;
+ u32 *value;
+
+ for (i = 0; i < len && i < sizeof(msg->data) - 3; i += 4, key++) {
+ value = bpf_map_lookup_elem(&regs_spi_xfer_r4v4, &key);
+ if (!value) {
+ bpf_printk("key 0x%x not exists", key);
+ return -EINVAL;
+ }
+
+ msg->data[i + 0] = (*value >> 24) & 0xff;
+ msg->data[i + 1] = (*value >> 16) & 0xff;
+ msg->data[i + 2] = (*value >> 8) & 0xff;
+ msg->data[i + 3] = *value & 0xff;
+
+ bpf_printk("SPI R32 [0x%x]=0x%x [%u/%u]", key, *value, i, len);
+ }
+
+ return 0;
+}
+
+static int spi_xfer_write(struct spi_msg_ctx *msg, unsigned int len)
+{
+ unsigned int i, key;
+ u32 value;
+
+ key = bpf_xfer_reg_u32((msg->data[0] << 24) | (msg->data[1] << 16) |
+ (msg->data[2] << 8) | msg->data[3]);
+ chip_reg = key;
+
+ for (i = 4; i < len && i < sizeof(msg->data) - 3; i += 4, key++) {
+ value = msg->data[i];
+ value = (value << 8) | msg->data[i + 1];
+ value = (value << 8) | msg->data[i + 2];
+ value = (value << 8) | msg->data[i + 3];
+
+ if (bpf_map_update_elem(&regs_spi_xfer_r4v4, &key, &value, 0)) {
+ bpf_printk("key 0x%x not exists", key);
+ return -EINVAL;
+ }
+
+ bpf_printk("SPI W32 [0x%x]=0x%x [%u/%u]", key, value, i, len);
+ }
+
+ return 0;
+}
+
+SEC("raw_tp.w/spi_transfer_writeable")
+int BPF_PROG(spi_xfer_r4v4, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+{
+ if (bpf_xfer_should_fault()) {
+ msg->ret = -EIO;
+ return 0;
+ }
+
+ if (msg->tx_nbits)
+ msg->ret = spi_xfer_write(msg, len);
+ else if (msg->rx_nbits)
+ msg->ret = spi_xfer_read(msg, len);
+
+ return 0;
+}
+
+char LICENSE[] SEC("license") = "GPL";
--
2.34.1