Linux I2C kernel driver binding - linux

I am learning about how to develop a Linux I2C kernel driver, and I learn from websites below.
How to instantiate I2C devices
I2C Driver for Linux Based Embedded System
...
Next, I found a sample that shows how to implement a I2C touchpad driver, but it really confused me.
linux/drivers/input/mouse/synaptics_i2c.c
My question is, how Linux kernel bind this driver to correctly device? This driver don't provide 'detect' callback, no specify the I2C slave address via i2c_driver.address_list, and there is seems no anyone to call i2c_board_info to register the address info (I grep a whole Linux codebase).
I thought the driver MUST be specify the slave address or provide the 'detect' callback, just like
drivers/hwmon/adc128d818.c
or
linux/drivers/rtc/rtc-ds1307.c (it will be register by i2c_board_info)
Please let me know what I missed, thanks.

The i2c device declaration is start from device tree.
Declare the i2c devices in device tree.
Example:
i2c1: i2c#400a0000 {
/* ... master properties skipped ... */
clock-frequency = <100000>;
flash#50 {
compatible = "atmel,24c256";
reg = <0x50>;
};
pca9532: gpio#60 {
compatible = "nxp,pca9532";
gpio-controller;
#gpio-cells = <2>;
reg = <0x60>;
};
};
Where,
1) 400a000 is a i2c bus address
2) pca9532 and flash are driver names
3) #50 and #60 are slave address
4) the attribute “compatible” to find and map device with the driver
5) other attribute which is inside cell of each entries are specific to the driver which will be used for device initialization during the probe
https://www.kernel.org/doc/Documentation/i2c/instantiating-devices

I finally figured out my question.
Refer to http://www.embedded-bits.co.uk/2009/i2c-in-the-2632-linux-kernel/
There is need to register my I2C device with i2c_new_probed_device() or i2c_new_device on Kernel to let it have a mapping table about slave address and device name.

Related

Why does the device tree have to list interrupts for a UART device?

On the device file tree listed here we can see an UART device:
uarta: serial#70006000 {
compatible = "nvidia,tegra210-uart", "nvidia,tegra20-uart";
reg = <0x0 0x70006000 0x0 0x40>;
reg-shift = <2>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA210_CLK_UARTA>;
clock-names = "serial";
resets = <&tegra_car 6>;
reset-names = "serial";
dmas = <&apbdma 8>, <&apbdma 8>;
dma-names = "rx", "tx";
status = "disabled";
};
The tegra210-uart driver is declared here
Why does uarta needs the interrupts section? Does it produce or receive interrupts? My guess is that it produces software interrupts: when it writes something to the serial, it triggers an interrupt. But why must this interrupt be listed in the device tree? And where is the code for this interrupt?
The second line of the above code block (reg = <0x0 0x70006000 0x0 0x40>) refers to an uart address. What is this address exactly? If I understand correctly, this is the address for a 8250_UART device but I'd like to know which pieces of this address do what, and how the kernel talks with this chip.
Driver documentation is available at https://www.kernel.org/doc/Documentation/devicetree/bindings/serial/nvidia%2Ctegra20-hsuart.txt
According to this forum https://forums.developer.nvidia.com/t/enabling-interrupts-for-uart-xavier-agx/166269
interrupts are used to prevent regular polling on UART.
Registering handler on this interrupt allows to only run code when effective data are received and available in DMA buffer, or when the complete outgoing message provided in DMA has been sent. Such a DMA usage example is available at: UART Tx mode with DMA enabled
Memory address 0x70006000 is the base location for UARTA controller registers (there are 4 UART [A,B,C,D] in Tegra 2) where to write commands or read status. These documents may help to understand:
https://docs.freebsd.org/en/articles/serial-uart/index.html
https://www.lammertbies.nl/comm/info/serial-uart
For instance, the Scratch Register (SCR +0x07) can be used to write and read back any byte as a way to test UART is present and controller operates as expected.
I recommend you to download reference documentation, chapter 22 for UART, available from https://developer.nvidia.com/embedded/tegra-2-reference

Handling pin modes from devicetree to module

I am trying to write a linux device driver for a SPI device, using Atmels SAMA5d35 MPU. Linux version is 4.19.30.
I have configured the pins in my device tree and set the status to "okay".
After that the pins changed mode as expected. My question is then, how do I manipulate pinmodes during runtime? My SPI device is not always on, neither is my driver always loaded. When that is the case I want the configured SPI pins to change mode to normal GPIOs (for power-consumption).
Is it the drivers task to do that, or is it something one can define in the device tree, when the driver for example is not loaded?
I have tried to implement a pinctrl-0 for setting the pins to SPI mode, and then a pinctrl-1 for setting the same pins to normal GPIOs. My idea was to switch between these pin configuration in the device driver, but unfortunately the device tree complaints about using the same pins for both pinctrl-0 and pinctrl-1 (compiles fine, but system wont boot). Although this was just my logical thoughts. I am sure there is a more correct way to do the things I stated above.
spi0: spi#f0004000 {
status = "okay";
ext_adc: ads1258#1 {
compatible = "ti,ads1258";
pinctrl-names = "default", "sleep";
pinctrl-0 = <&pinctrl_spi0_default>;
pinctrl-1 = <&pinctrl_spi0_sleep>;
reg = <1>; /* Hardware chipselect SPI0_NPCS1 */
spi-max-frequency = <16000000>; /* According to datasheet */
start-gpios = <&pioD 5 GPIO_ACTIVE_HIGH>;
drdy-gpios = <&pioD 22 GPIO_ACTIVE_LOW>;
enaadc-gpios = <&pioA 26 GPIO_ACTIVE_HIGH>;
};
};
My question is then, how do I manipulate pinmodes during runtime?
That's called "Runtime pinmuxing", which is described in Documentation/pinctrl.txt.
But you may not have to do that.
When that is the case I want the configured SPI pins to change mode to normal GPIOs (for power-consumption).
Is it the drivers task to do that, or is it something one can define in the device tree, when the driver for example is not loaded?
The default mode for a pin (of Atmel/Microchip SoCs) is to be unassigned to any peripheral mode, and be available for use as a GPIO.
All pins that are not assigned to a peripheral or acquired by a driver as a GPIO, end up in the pool of available GPIOs.
So when your SPI driver is not successfully installed, those pins it would use will be in the pool of available GPIOs.
I have tried to implement a pinctrl-0 for setting the pins to SPI mode, and then a pinctrl-1 for setting the same pins to normal GPIOs.
Assigning pins for use by the SPI controller is proper, but there is no mechanism AFAIK for assigning a pin to be an available GPIO.
You can only define properties in the DT for what a device, such as the SPI controller, requires.
There is no mechanism for an "alternate" assignment.
I am sure there is a more correct way to do the things I stated above.
If your driver does not install, then its resources such as its pins should not be allocated. The pins that the SPI would have used will remain unused, and end up in the pool of available GPIOs (unless something else claims/requests one of those pins).
So your DT needs to simply define what your device uses, and leave it at that.
If you still want your driver to modify the state of its pin, then study the section titled "Pin control requests from drivers" in Documentation/pinctrl.txt.

vbus regulator device tree

can someone explain the device tree settings? What they will do on i.MX6 Processor?
Thanks!
vbus1_regulator: regulator#1 {
compatible = "regulator-fixed";
regulator-name = "vbus1_regulator";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
&usbotg {
vbus-supply = <&vbus1_regulator>;
dr_mode = "host";
status = "okay";
};
The USB protocol defines two roles - host and client. With USB OTG (on-the-go) a device can have both host and client capabilities. See:
http://www.usb.org/developers/onthego/
https://www.maximintegrated.com/en/app-notes/index.mvp/id/1822
In order for the device to work as a host, it needs to provide power for the client device connected to it, as required by the USB standard.
That being said, the &usbotg node is:
Using the _vbus1_regulator_ as USB power supply.
Forcing the USB OTG port to work as host by setting the dr_mode property to host.
Enabling the node by setting the status to okay.
Please see the Linux kernel device-tree bindings documentation for more details:
https://www.kernel.org/doc/Documentation/devicetree/bindings/usb/fsl-usb.txt
And the vbus1_regulator node is:
Using the kernel driver compatible to regulator-fixed: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/regulator/fixed.c?h=v4.19-rc1#n196
Setting the name of the regulator to vbus1_regulator.
Defining the minimum and maximum voltages to the same value of 5000000 micro volts, which as the same as 5 volts. Both are the same due to the nature of a fixed voltage regulator - you have a single fixed output voltage value.
Using a GPIO pin (declared elsewhere) to control the regulator (switch on/off).
Defining that the GPIO level must be high in order to activate the regulator. If this property is omitted, that it is assumed that the regulator is active on logic level low.
Please see the Linux kernel device-tree bindings documentaiton for more details:
https://www.kernel.org/doc/Documentation/devicetree/bindings/regulator/fixed-regulator.txt

Linux - Is it necessary to register (instantiate) i2c devices before using them?

I'm confused on how userspace programs using Linux's i2c dev interface is able to register (instantiate?) i2c devices.
From my understanding by reading this: https://www.kernel.org/doc/Documentation/i2c/instantiating-devices, it seems we need to either:
Define a i2c_board_info struct with name and address of the i2c
device, do a i2c_register_board_info()
Have a devicetree entry such as this:
i2c1: i2c#400a0000 {
/* ... master properties skipped ... */
clock-frequency = <100000>;
flash#50 {
compatible = "atmel,24c256";
reg = <0x50>;
};
pca9532: gpio#60 {
compatible = "nxp,pca9532";
gpio-controller;
#gpio-cells = <2>;
reg = <0x60>;
};
};
Instantiate devies explicitly by defining a i2c_board_info struct, then call i2c_new_device() in the init of the i2c device driver
But how is this done for user space programs using the i2c-dev interface described here https://www.kernel.org/doc/Documentation/i2c/dev-interface?
I don't have a devicetree entry, and when I grep the code for i2c_board_info, i2c_register_board_info(), or i2c_new_device() I don't find anything. But the code below still works, how?
#include <linux/i2c-dev.h>
void read_from_device(uint8_t *read_data)
{
int result;
file_desc = open("/dev/i2c-2", O_RDWR);
ioctl(file_desc, I2C_SLAVE, device_address);
i2c_smbus_write_byte_data(file_desc, DEVICE_PAGE_ADDRESS, page_number);
result = i2c_smbus_read_byte_data(file_desc, device_register_address);
*read_data = result;
close(file_desc);
}
Does this mean we don't necessarily have to register (instantiate) i2c devices in order to use them? Does that apply to both i2c drivers as well as userspace programs using i2c-dev interface?
The i2c-dev driver binds to the bus (i2c_adapter), not a specific i2c device (i2c_client). So you only need to create the bus device to use i2c-dev and adding devices for the clients isn't necessary. In fact, you'll find i2c-dev will not let you use an I2C address bound to another driver unless you use the I2C_SLAVE_FORCE ioctl.
This is the opposite to the spidev driver, which binds to a specific spi slave device and not the bus as a whole. I2C predates the modern Linux device model and some things are different than is done in other places.
If you want a kernel driver to control the I2C device then there needs to be a device for the driver to bind to. The exception would be so-called "old style" I2C drivers which probe a set of addresses and bind to devices if any are found that appear to be the correct kind.

Named GPIOs in DeviceTree

I am trying to create a device tree for an embedded system, and would like to expose a few GPIOs to userspace. These are not and should not be used by kernel drivers. For instance, there is a USB device soldered to the board that is controlled by a user-space driver. It has a GPIO reset line, which the userspace library needs to access.
I would like these to be exposed by name in sysfs somewhere so that userspace can access /sys/class/gpio/usbreset instead of needing to know the magic gpio number and needing to specifically "export" it. I have tried setting it up as a GPIO hog, which initializes the GPIO, but its name does not appear in sysfs, and the gpio cannot be exported when it is hogged. I know that I can pick another kernel driver type such as LED, but it is not an LED, and this does not seem very clean to me.
What is the right way to export a named GPIO in sysfs?
You can use the "gpio-leds" type in the devtree. Make sure you have CONFIG_LEDS_GPIO in your kernel. Set up your devtree as described in Documentation/devicetree/bindings/leds/leds-gpio.txt. I know, it says "LED", but the driver just wiggles the GPIO, and doesn't care what's hooked up to it.
Example devtree entry (copied from the docs):
run-control {
compatible = "gpio-leds";
red {
gpios = <&mpc8572 6 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
green {
gpios = <&mpc8572 7 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
};
Those entries will be accessible by name in sysfs, and you can manipulate them from userspace there.
I propose writing a simple kernel module to ask for the GPIO and then exporting a link, the link can be named and hence suitable for your request.
https://www.kernel.org/doc/Documentation/gpio/sysfs.txt
from the link above:
After the GPIO has been exported, gpiod_export_link() allows creating
symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can
use this to provide the interface under their own device in sysfs with
a descriptive name

Resources