-2

I am trying to build a driver for my IP in an FPGA. I have:

static const struct of_device_id myip_of_match[] = {
 { .compatible = "xlnx,myip-controller-1.022", },
 {},
};
MODULE_DEVICE_TABLE(of, myip_of_match);
static struct platform_driver myip_driver = {
.probe = myip_probe,
.remove = myip_remove,
.driver = {
.name = "myip",
.of_match_table = myip_of_match,
 },
};
module_platform_driver(myip_driver);

Of course, I also have a function in the file: static int myip_probe(struct platform_device *pdev).

I am building this using Yocto as my additional layer.

However, after copying the .ko file to Linux on Zynq-7000, when I do insmod myip.ko myip_probe does not start.

I read that the .ko file should contain an alias with which it is matched with devicetree. But modinfo does not show this alias at all.

What am I doing wrong?

I am correcting my negligence. My devicetree is built from several files. Crucial in this matter is a fragment of the auto-generated pl.dtsi file by Vivado. Here in the tree under amba_pl is the entry regarding my controller:

/ {
 amba_pl: amba_pl {
 ...
 <other_stuff>
 ...
 myip_control_0: myip_controller@42030000 {
 compatible = "xlnx,myip-controller-1.022";
 reg = <0x42030000 0x1000>;
 };
 ...

In addition, I have my own extension of this node with some parameters in another .dtsi file:

&myip_control_0 {
 memory-region = <&myip_mem>;
 interrupt-parent = <&intc>;
 interrupts = <0 34 1>, <0 35 1>, <0 36 1>;
};

In the system after startup I have:

cat /proc/device-tree/amba_pl/myip_controller\@42030000/

Output:

compatible
xlnx,myip-controller-1.022

and such a catalog is also available: /sys/bus/platform/devices/42030000.myip_controller/

I've made a patch to print out what's going on in the functions looking for a match between device and driver in the kernel, and as far as I can see, there isn't any driver to match on boot for my node in the devicetree:

[2025年07月20日 15:54:45.758] of_match_device: matching device node: /amba_pl/myip_controller@42030000
[2025年07月20日 15:54:45.758] OF: of_match_node: node=/amba_pl/myip_controller@42030000, matches=c09083f8
[2025年07月20日 15:54:45.758] OF: of_match_node: MISS (no compatible match for node: /amba_pl/myip_controller@42030000)
[2025年07月20日 15:54:45.758] of_match_device: MISS, none of these compatible entries matched for node /amba_pl/myip_controller@42030000:

But also no such entries appear as I do the insmod of this .ko file. Am I assuming correctly that this is due to the fact that the kernel doesn't find an alias in this .ko file, so it doesn't even try to match anything?

Makefile for the module in my Yocto meta layer:

obj-m := myip_controller.o
myip_controller-objs := myip_controller.o fpga_operations.o
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
 $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules
modules_install:
 $(MAKE) -C $(KERNEL_SRC) M=$(PWD) INSTALL_MOD_PATH=$(INSTALL_MOD_PATH) modules_install
clean:
 $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

And this is the important part of my *.bb file:

SRC_URI = "file://Makefile \
 file://myip_controller.h \
 file://myip_controller.c \
 file://fpga_operations.h \
 file://fpga_operations.c"
S = "${WORKDIR}"
inherit module
KERNEL_MODULE_AUTOLOAD = "myip_controller"
COMPATIBLE_MACHINE = ".*"
EXTRA_CFLAGS += "-g -O0"
EXTRA_OEMAKE += "KERNEL_SRC=${STAGING_KERNEL_DIR} KERNEL_VERSION=${KERNEL_VERSION} INSTALL_MOD_PATH=${D}"
do_compile() {
 oe_runmake
}
do_install() {
 oe_runmake modules_install
}

I used the hello_mod module example from yocto/poky/meta-skeleton/recipes-kernel/hello-mod, changed it hello.c to the following and the alias appears in the ko file :)

#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/device.h>
static int hello_probe(struct platform_device *pdev)
{
 pr_info("hello_probe: found device %s\n", dev_name(&pdev->dev));
 return 0;
}
static int hello_remove(struct platform_device *pdev)
{
 pr_info("hello_remove: removed device %s\n", dev_name(&pdev->dev));
 return 0;
}
static const struct of_device_id hello_of_match[] = {
 { .compatible = "xlnx,myip-controller-1.022", },
 {},
};
MODULE_DEVICE_TABLE(of, hello_of_match);
static struct platform_driver hello_driver = {
 .probe = hello_probe,
 .remove = hello_remove,
 .driver = {
 .name = "hello",
 .of_match_table = hello_of_match,
 },
};
module_platform_driver(hello_driver);
MODULE_LICENSE("GPL");

When I did insmod hello.ko, it showed me the messages from the kernel from the of_match_node function, i.e., as I assumed, the kernel saw that there was an alias it started to assign it.

OF: of_match_node: node=/amba_pl/axi_quad_spi@44010000, matches=bf008024
OF: of_match_node: MISS (no compatible match for node: /amba_pl/axi_quad_spi@44010000)
OF: of_match_node: node=/amba_pl/myip_controller@42030000, matches=bf008024
OF: of_match_node: HIT compatible = 'xlnx,myip-controller-1.022'
hello_probe: found device 42030000.myip_controller
OF: of_match_node: node=/amba_pl/gpio@42000000, matches=bf008024
OF: of_match_node: MISS (no compatible match for node: /amba_pl/gpio@42000000)
OF: of_match_node: node=/amba_pl/gpio@42010000, matches=bf008024
OF: of_match_node: MISS (no compatible match for node: /amba_pl/gpio@42010000)
OF: of_match_node: node=/amba_pl/gpio@42020000, matches=bf008024

So it works! I have to find why my module behaves in different way...

I found what makes the difference, but I don't know how to do it correctly.

The thing is that I am trying to build a module from several source files. When I add them in the Makefile this alias disappears in the resulting .ko file. When I built this hello_mod example from a single file then the alias was included in the .ko file.

I prepared a minimalist representation of my problem in a way that reflects my module. I have the following module files:

my_module/
├── Makefile
├── hello.c # Main C file
├── hello.h # Header for the main file
├── hw_access.c # Hardware access functions
├── hw_access.h # Header for the additional file

Makefile:

obj-m := hello.o
hello-objs := hello.o hw_access.o
SRC := $(shell pwd)
all:
 $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
modules_install:
 $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
clean:
 rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
 rm -f Module.markers Module.symvers modules.order
 rm -rf .tmp_versions Modules.symvers

hello.c:

#include "hello.h"
static int hello_probe(struct platform_device *pdev)
{
 pr_info("hello_probe: found device %s\n", dev_name(&pdev->dev));
 return 0;
}
static int hello_remove(struct platform_device *pdev)
{
 pr_info("hello_remove: removed device %s\n", dev_name(&pdev->dev));
 return 0;
}
static const struct of_device_id hello_of_match[] = {
 { .compatible = "xlnx,myip-controller-1.022", },
 {},
};
MODULE_DEVICE_TABLE(of, hello_of_match);
static struct platform_driver hello_driver = {
 .probe = hello_probe,
 .remove = hello_remove,
 .driver = {
 .name = "hello",
 .of_match_table = hello_of_match,
 },
};
module_platform_driver(hello_driver);
MODULE_LICENSE("GPL");

hello.h

#ifndef HELLO_H
#define HELLO_H
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#define SOME_VALUE 14
struct hello_context {
 int some_parameter;
};
#endif /* HELLO_H */

hw_access.c

#include "hello.h"
#include "hw_access.h"
void set_parameter(struct hello_context *hc)
{
 hc->some_parameter = SOME_VALUE;
 pr_info("HELLO: Parameter context value = %d\n", hc->some_parameter);
}
void get_parameter(struct hello_context *hc)
{
 int parA = hc->some_parameter;
 pr_info("HELLO: Another parameter value = %d\n", parA);
}

hw_access.h

#ifndef HW_ACCESS_H
#define HW_ACCESS_H
#include "hello.h"
void set_parameter(struct hello_context *hc);
void get_parameter(struct hello_context *hc);
#endif // HW_ACCESS_H

So for the above files, it will generate a .ko file without an alias. But as in the Makefile, I will comment this line out:

# hello-objs := hello.o hw_access.o

, it generates a .ko file with an alias.

How can I do it correctly for a multi-source build?

Peter Mortensen
31.4k22 gold badges110 silver badges134 bronze badges
asked Jul 20 at 15:36
6
  • 2
    You need to provide the Linux kernel with a Device Tree that describes your board. But you neglect to show us anything regarding the DT other than some data structures from your driver. Hint: see stackoverflow.com/questions/26840267/… Commented Jul 20 at 18:33
  • 1
    If there is no modalias for this module it may only mean that you built it with CONFIG_MODULE=n. I don't know how you have achieved this. Commented Jul 21 at 6:32
  • 1
    Can you build and run hello.ko from the example yocto module? What happens if you build the whole image and then insert the module already present in the image? If that's not possible, which of the produced ko files in the work directory do you use? How do you tell myip_probe does not run? Commented Jul 21 at 10:39
  • 1
    I am trying to load via insmod the module generated in: yocto/builds/build3/tmp-glibc/sysroots-components/z7000board_revb/myip-controller/lib/modules/<kernel_name>/extra/myip_controller.ko At the beginning of the probe I have: pr_info("IP DEBUG: Initialization 30"); and I don't see it in the terminal. Subsequent steps are not running either. Commented Jul 21 at 11:11
  • 2
    It seems like a file naming issue. Do not use hello.c with other .c files to build hello.ko. Rename hello.c. See this answer Commented Jul 22 at 16:26

1 Answer 1

-1

I can't have the name of the main C file like the module name. When they differ, it works fine!

Peter Mortensen
31.4k22 gold badges110 silver badges134 bronze badges
answered Jul 22 at 16:38
Sign up to request clarification or add additional context in comments.

1 Comment

Okay, this needs to be closed as a dup. I remember there is an old question with the similar issue and problem was exactly as you described

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.