How to Make a Built-In Device Driver in Linux

How to make a built-in device driver in linux

There are two ways to do for your query
1) building your module as statically compiled along with kernel(your source code should reside in kernel tree ),so while building build it static which come as a part of kernel,
so when kernel boots your module will be loaded.
2)Same as above but while building build as dynamic loadable module so that wheneever required you can load it.

to illustrate above concept you can try below link for simple helloworld example.

http://www.agusbj.staff.ugm.ac.id/abjfile/Chap8.pdf

How to write a simple Linux device driver?

First, start by writing a generic kernel module. There are multiple places to look up for information but I found this link to be very useful. After you have gone through all examples specified there you can start writing your own Linux Driver Module.

Please note, that you will not get away with just copy-pasting the example code and hope it will work, no. Kernel API can sometimes change and examples will not work. Examples provided there should be looked at as a guide on how to do something. Depending on the kernel version you are using you have to modify the example in order to work.

Consider using TI platform-provided functions as much as you can, because that can really do a lot of work for you, like requesting and enabling needed clocks, buses, and power supplies. If I recall correctly you can use the functions to acquire memory-mapped address ranges for direct access to registers. I have to mention that I have a bad experience with TI-provided functions because they do not properly release/clean up all acquired resources, so for some resources, I had to call other kernel services to release them during module unload.

Edit 1:

I'm not entirely familiar with Linux SPI implementation but I would start by looking at omap2_mcspi_probe() function in drivers/spi/spi-omap2-mcspi.c file. As you can see there, it registers it's methods to Linux master SPI driver using this API: Linux/include/linux/spi/spi.h. In contrast to char driver, the main functions here are *_transfer() functions. Look up the struct descriptions in spi.h file for further details. Also, have a look at this alternative device driver API, too.

Linux: Compiling a kernel device driver in standalone fashion

Examining your Makefile

#                             
# Makefile for eFuse.
#

obj-$(CONFIG_EFUSE) += efuse_bch_8.o efuse_version.o efuse_hw.o efuse.o

We learn that the code can be built as either a loadable module, or permanently linked into the kernel itself.

Examining odroidc_defconfig from branch odroidc-3.10.y-android mentioned in your instructions we find

#
# EFUSE Support
#
CONFIG_EFUSE=y

With the "y" indicating that the code is to be linked into the driver. Had it instead said "m" it would be built as a module.

It's possible you could change that in the kernel config, but it might also cause problems if there's nothing setup to load the module before it is needed.

Likely simply installing the newly built kernel with the code already linked inside (ie, forgetting about the module idea) will work.

Built-in kernel driver still need device tree?

Built-in kernel driver still need device tree? Yes. Concept of device tree is orthogonal to whether drivers are built-in or compiled as modules. Device tree contains information about the hardware. Platform bus passes that info to relevant drivers.

This is a good brief article about platform bus, and how things used to be before device tree: https://www.codeproject.com/tips/1080177/linux-platform-device-driver. Device tree factors out harware info otherwiese hard-coded in kernel code, making the code more portable.

How to load and unload linux drivers that are built into kernel

It's easy as that. You find a device and driver which you want to unbind. For example, on my Intel Minnownboard (v1) I have PCH UDC controller (a PCI device):

% lspci -nk
...
02:02.4 0c03: 8086:8808 (rev 02)
Subsystem: 1cc8:0001
Kernel driver in use: pch_udc

Now I know necessary bits:

  • bus on which the device is located: PCI
  • device name: 0000:02:02.4 (note that lspci gives reduced PCI address, i.e. without domain or i.o.w. BDF, while driver expects domain:BDF)
  • driver name: pch_udc

Take altogether we can unbind the device:

% echo 0000:02:02.4 > /sys/bus/pci/drivers/pch_udc/unbind
[ 3042.531872] configfs-gadget 0000:02:02.4: unregistering UDC driver [g1]
[ 3042.540979] udc 0000:02:02.4: releasing '0000:02:02.4'

You may bind it again. Simple use bind node in the same folder.

The feature appeared more than 15 years ago and here is the article on LWN that explains it.

How to make existing Linux kernel module driver after modifying the driver source code

You must run make from the top directory of the Linux source (/usr/src/linux/). Be sure that your driver is included in your /usr/src/linux/.config file. So, build the kernel with your driver.
If you don't want to rebuild the entire kernel, read more :)

If you want to re-build all modules inside the directory:

make M=drivers/net/wireless/rtl818x/rtl8187/

If you want to re-build a single module inside the directory:

make M=drivers/net/wireless/rtl818x/ CONFIG_RTL8187=m

The *CONFIG_RTL8187* name can be found in drivers/net/wireless/rtl818x/Kconfig (CONFIG_ + RTL8187)

It should works also this:

make drivers/net/wireless/rtl818x/rtl8187/rtl8187.ko

A simple program on linux device driver

You'd better to read the paragraph at page 24 of the book Linux Device Drivers, 3rd edition (freely available at http://oreilly.com/openbook/linuxdrive3/book/index.html).

The -C option makes it change the directory to the one provided. There, it finds the kernel's top-level Makefile. Then, the M= option causes that Makefile to move back to your module source directory before trying to build the modules target ($PWD is a variable containing the path of your current directory).

obj-m is a variable containing the list of kernel modules to be build (see https://www.kernel.org/doc/Documentation/kbuild/makefiles.txt) .



Related Topics



Leave a reply



Submit