Preferred Linux driver architecture for a multi-function PMU device - linux

I have a bespoke/complex Power Management Unit which exposes its functionality as an I2C slave with 16-bit registers and an interrupt (out) signal.
This PMU also has GPIO functionality.
(The interrupt tells the Linux kernel (I2C master) to read registers because a GPIO input has changed state).
Currently, I've structured the (working) driver(s) as:
./include/linux/mfd/mypmu.h
./drivers/gpio/gpio-mypmu.c
./drivers/mfd/mypmu-core.c
./drivers/mfd/mypmu-regmap.c
./drivers/mfd/mypmu-i2c.c
I have three MODULE_DESCRIPTION() macro invocations:
./drivers/gpio/gpio-mypmu.c:MODULE_DESCRIPTION("GPIO interface for MYPMU");
./drivers/mfd/mypmu-core.c:MODULE_DESCRIPTION("MYMU device");
./drivers/mfd/mypmu-i2c.c:MODULE_DESCRIPTION("MYPMU_I2C");
The reason that it's split into three separate modules is that I use different ways of registering each module, according to the kernel subsystem of which they are a part.
./drivers/gpio/gpio-mypmu.c:platform_driver_register(&mypmu_gpio_driver);
./drivers/mfd/mypmu-core.c:platform_set_drvdata(*pdev, mypmu);
./drivers/mfd/mypmu-i2c.c:i2c_add_driver(&mypmu_i2c_driver);
(This is largely cargo-cult programming, caused by aping other (single-function) drivers' code.)
Is using three modules in one device driver normal? Or is there a way to register one driver in multiple Linux subsystems, such as GPIO and I2C?
Can a driver appear in /sys/class/gpio without a module living in the drivers/gpio tree?
Is there a better way of structuring an MFD driver?

Related

Non-blocking i2c read from userspace

I'm trying to read and write data off i2c in slave mode and have found several examples to do this in userspace including this most relevant one from NXP (I'm using the iMX8MQ):
https://source.codeaurora.org/external/imx/imx-test/tree/test/mxc_i2c_slave_test/mxc_i2c_slave_test.c?h=imx_4.14.78_1.0.0_ga
However, it looks like if I want to read data, it would be a polling based implementation because it looks like i2c-dev does not provide a way to register userspace callbacks when i2c data is available. Not even sure if any Linux device drivers allow doing this at all. Am I correct in assuming that there is no non-blocking and asynchronous way of doing an i2c read from userspace in slave mode?
I'm not very familiar with writing device drivers so even if I wanted to implement my own, similar to this one:
https://github.com/torvalds/linux/blob/master/drivers/i2c/i2c-slave-eeprom.c
is it a good idea to call a userspace function when data became available (for instance when the driver received an I2C_SLAVE_STOP)?

Gpio Linux conventions and names

How can we find the naming of available gpios in an arbitrary board that runs Linux and then to use the Linux commands echo "gpionumber" >/sys/class/gpio so then we can control this gpio?
Gpio and gpiocontrollers are numbered. Gpiocontrollers may have labels, but they may not be unique.
The linux kernel documentation on gpio sysfs driver can be found here and is a good read.
The linux kernel uses device tree file to know which gpiocontrollers are available to him. A gpiocontroller may have multiple gpios. Each board has it's own unique device tree compiled with the kernel or loaded at boot time.
Gpiocontrollers are identified by the register and register length they refer too, see here. You can specify the label of the gpiocontroller as described in device tree file format and you can query the gpiocontroller label using /sys/class/gpio/gpiochipN/label, they may be not unique and they don't let you identify the gpio. Also, they may change between device tree file versions.
There is no "naming", just numbering. You can query all gpios available on a particular board by just inspecting/adding the /sys/class/gpio/gpiochip*/ngpio Usually a board manufacturer/provider/seller/etc provides documentation with the kernel it ships with the board with explanation, which gpio has which number/address, like for Colibri VF61. For some popular boards it is just a matter of googling to find nice looking images with gpio numbers, like for RaspberryPi3 or

difference between core.c and pci.c in Linux nvme driver

I want to learn how nvme driver works in Linux,
So I look into nvme driver source code here
what confuses me is that there are two source file containing "module_init()"
core.c
module_init(nvme_core_init);
and
pci.c
module_init(nvme_init);
I know the module_init() function is the entry of the driver
but how come there are two entry in nvme driver ?
module_init() is the entry point of a module, and with abstraction we layer the modules to logically separate functionality, improve code reuse, etc...
pci.c provides the PCI / PCIe interface/abstraction layer for using NVMe devices over a PCI bus - it has much more to do with managing tangible devices:
nvme_id_table
nvme_probe()
nvme_irq()
core.c provides the core driver for generically dealing with an NVMe devices connected to the system (it doesn't care how). This module cares more about providing the standardised block device access, etc...
nvme_fops
nvme_submit_io()
This is a common idiom throughout the kernel, and is done so that if an NVMe device became accessible via another bus, then core.c would be reused with no / minimal changes, and new_bus.c would be written to interface between the two.
If you're using NVMe over PCIe, then the following chain will hopefully help things make sense:
pci.c implements nvme_pci_reg_read32()
pci.c registers nvme_pci_reg_read32() in the nvme_ctrl_ops structure, named nvme_pci_ctrl_ops
core.c implements nvme_init_ctrl(), which is called with a pointer to one of these structures
core.c keeps a reference to the structure
core.c implements nvme_init_identify(), which needs assistance of the lower-level - pci.c
core.c calls pci.c's nvme_pci_reg_read32() via the reference retained above
If we were to develop a new bus that could support an NVMe device, then we could swap out pci.c for new_bus.c with no changes to core.c (as mentioned above).
It's also worth checking out the Kconfig files as they can hint at things like this - though there is a certain amount of mental gymnastics to tie the source files to the menu options via the Makefiles.

How a device driver recognise the peripheral mapping in embedded unix

In most example project for embedded system there is a system file in which we can find structures for different peripheral as well as the memory mapping of the peripheral register, in addition there is also a module per peripheral that contains basic function to manipulate the periheral like: periph_enable, periph_write, periph_read; this is the architecture i have in mind when i tackle a new project.
Actually i started to work with a BF609 but now with an embedded linux in it, my task consist in writing a communication driver with another device via UART, as usual i tried to look for the files i used to use but in vain, i can't find the mapping of the different peripheral.
I started to read this book, i undrestand that the kernel see each device like a file and that a driver is mainly the implementation of the open, close, read and writefunctions in these file but i still don't undrestand how these functions communicate with peripheral registers.
My questions:
1) How device drivers recognise the mapping of the peripheral is there sth i missed, is there any example that explain how to implement simple read and write functions via UART for example
2) Where can i find the mapping of the peripheral in the buildroot directory
Thanks in advance

Transfer data from linux to fpga and inversely?

I have booted a ubuntu on a ZedBoard. I want to transfer data between fpga and linux. For example, I want to write or read a register from linux. What is best way for doing it? I have not any idea.
Thanx.
First of all, you need to specifically say what you want to do, for example. if you want to access the IO signals on the FPGA, you need to first add the GPIO module to your system, synthesize and implement it.
Then you use the Linux GPIO Driver to access the port as it is explained in this page:
Linux GPIO Driver
The GPIO driver fits in the Linux GPIO framework which is not a char
mode driver. Yet it does provide access to the GPIO by user space
through the sysfs filesystem. This allows each GPIO signal to be read
and written in similar manner to a char mode device. The interface is
somewhat documented in the kernel tree at Documentation/gpio.txt. The
following text is aimed to augment, not replace the existing
documentation.
For other, more complex interfaces you need to create your own driver or use one of the drivers that are available and modify it to fit your needs.

Resources