i have connected a hardware to an embedded linux board on i2c lines.
I can see the device at /dev/i2c-1
filename = "/dev/i2c-1"
filehandle = open(filename,O_RDWR);
write(filehandle, <buffer to be written>, <number of Bytes>)
(similiarly for read = read(filehandle, <buffer to be read in an array>, <number of Bytes>)
Now my question here is am I using the Linux's i2c-drivers ( read/write) when I am invoking write system calls (and read like above using filehandle).
Also is this implementation independent of i2c module?I verified only after I do modprobe i2c_dev I can see my code running.
Is modprobe i2c_dev loading the i2c module and forming the /dev/i2c-1 in the /dev directory since I have connected the i2c device to it.
User-space interface to I2C
User-space interface to I2C subsystem is provided via /dev/i2c-* files and documented at Documentation/i2c/dev-interface. There are two ways to send I2C message:
send plain buffer via write(); you need to include linux/i2c-dev.h for this
send i2c_msg structure via ioctl() with I2C_RDWR request; you need to include linux/i2c.h for this
See this question for examples.
How /dev/i2c-1 is associated with I2C subsystem
/dev/i2c-1 file is just an interface to I2C subsystem. You can send I2C message, receive I2C message and configure I2C using correspondingly write(), read() and ioctl() syscalls. Once you perform one of these operations over /dev/i2c-1 file, it's being passed through Virtual file system to I2C layer, where those operations are implemented. Actual callbacks for those operations are implemented in drivers/i2c/i2c-dev.c file, more specifically -- in i2cdev_fops structure.
For example, when you perform open() syscall on /dev/i2c-1 file, the i2cdev_open() function is called in kernel, which creates i2c_client structure for further send/receive operations, and that structure is being assigned to file's private data field:
/* This creates an anonymous i2c_client, which may later be
* pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
*
* This client is ** NEVER REGISTERED ** with the driver model
* or I2C core code!! It just holds private copies of addressing
* information and maybe a PEC flag.
*/
client = kzalloc(sizeof(*client), GFP_KERNEL);
...
file->private_data = client;
When you perform some operations on that /dev/i2c-1 file next, i2c_client structure will be extracted from file->private_data field, and corresponding function will be called for that structure.
For write() syscall the i2cdev_write() function will be called, which leads to i2c_master_send() function call:
struct i2c_client *client = file->private_data;
...
ret = i2c_master_send(client, tmp, count);
The same way read() leads to i2cdev_read(), which leads to i2c_master_recv(). And ioctl() leads to i2cdev_ioctl(), which just assigns corresponding flags to i2c_client structure.
How /dev/i2c-1 is associated with hardware I2C driver
Operations performed on /dev/i2c-* file lead eventually to execution of I2C hardware driver functions. Let's see one example of it. When we are doing write() syscall, the whole chain will be:
write() -> i2cdev_write() -> i2c_master_send() -> i2c_transfer() -> __i2c_transfer() -> adap->algo->master_xfer(), where adap is i2c_adapter structure, which stores hardware specific data about I2C controller, such as callbacks of I2C hardware driver. That .master_xfer callback is implemented in I2C hardware driver. For example, for OMAP platforms it's implemented in drivers/i2c/busses/i2c-omap.c file, see omap_i2c_xfer() function.
Related
I'm trying to develop a simple Linux kernel module that manages a bunch of sensors/actuators pinned on the GPIO of a Raspberry Pi.
The GPIO functionalities I need are quite simple: get/set pin values, receive IRQs, ...
In my code, I have a misc_device which implements the usual open, read, write and open operations. In my read operation, for instance, I'd like to get the value (high/low) of a specific GPIO pin.
Luckily, the kernel provides an interface for such GPIO operations. Actually, there are two interfaces, according to the official GPIO doc: the legacy one, which is extremely simple yet deprecated, and the new descriptor-based one.
I'd like to use the latter for my project, and I understand how to implement all I need except for one thing: the device tree stuff.
With reference to board.txt, before I can call gpiod_get_index() and later gpiod_get_value(), first I need to setup the device tree somehow like this:
foo_device {
compatible = "acme,foo";
...
led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
};
However, I've absolutely no clue where to put that chunk of code, nor if I really need it. Mind that I have a misc device which looks like this, where aaa_fops contains the read operation:
static struct miscdevice aaa = {
MISC_DYNAMIC_MINOR, "aaa", &aaa_fops
};
Using the old deprecated interface, my problem would be solved because it doesn't require to mess with the device tree, but I'd still like to use the new one if not too complex.
I've read a bunch of documentation, both official and unofficial, but couldn't find a straight and simple answer to my issue. I tried to find an answer in the kernel source code, especially in the drivers section, but only got lost in a valley of complex and messy stuff.
The lack of working, minimal examples (WME) about kernel is significantly slowing down my learning process, just my opinion about it.
Could you please give me a WME of a simple device (preferably a misc) whose read() operation gets the value of a pin, using the new GPIO interface?
If you need more details about my code, just ask. Thanks in advance!
Note 1: I'm aware that most of my work could be done in userspace rather than kernelspace; my project is for educational purposes only, to learn the kernel.
Note 2: I choose a misc device because it's simple, but I can switch to a char device if needed.
... first I need to setup the device tree somehow like this:
...
However, I've absolutely no clue where to put that chunk of code
Device Tree nodes and properties should not be called "code".
Most devices are connected to a peripheral bus, so device nodes typically are child nodes of the peripheral bus node.
Could you please give me a WME of a simple device
You can find numerous examples of descriptor-based GPIO usage in the kernel source.
Since the documentation specifies the GPIO descriptor as a property named
<function>-gpios, a grep of the directory arch/arm/boot/dts for the string "\-gpios" reports many possible examples.
In particular there's
./bcm2835-rpi-b.dts: hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
This hpd-gpios property belongs to the hdmi base-node defined in bcm283x.dtsi, and is used by the gpu/drm/vc4/vc4_hdmi.c driver.
/* General HDMI hardware state. */
struct vc4_hdmi {
...
int hpd_gpio;
...
};
static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
{
...
/* Only use the GPIO HPD pin if present in the DT, otherwise
* we'll use the HDMI core's register.
*/
if (of_find_property(dev->of_node, "hpd-gpios", &value)) {
...
hdmi->hpd_gpio = of_get_named_gpio_flags(dev->of_node,
"hpd-gpios", 0,
&hpd_gpio_flags);
if (hdmi->hpd_gpio < 0) {
ret = hdmi->hpd_gpio;
goto err_unprepare_hsm;
}
...
}
If the hpd-gpios property is defined/found and successfully retrieved from the board's DeviceTree, then the driver's structure member hpd_gpio holds the GPIO pin number.
Since this driver does not call devm_gpio_request(), the framework apparently allocates the GPIO pin for the driver.
The driver can then access the GPIO pin.
static enum drm_connector_status
vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
...
if (vc4->hdmi->hpd_gpio) {
if (gpio_get_value_cansleep(vc4->hdmi->hpd_gpio) ^
vc4->hdmi->hpd_active_low)
return connector_status_connected;
else
return connector_status_disconnected;
}
I'm working in an USB ACM driver, "where i need to send notification from kernel space to user space application for invoking a call back function". I'm not much aware of using kernel to user interfaces in code. how well can sysfs help for this scenario. Please send some sample code to use sysfs so that I'll get an idea to implement in my code. I could not find it anywhere. Also pls tell anyother easy way to achieve kernel to user space notification. Thanks in advance.
My suggestion would be to create a sysfs interface to your kernel driver that userspace can access. Each sysfs attribute if created with the correct properties can be read like a file from userspace. You can then use the poll function from userspace to poll for an action on that file. To trigger this action from Kernel space, you can use the sysfs_notify function on your attribute and it will cause your userspace code to wake up. Here is how I would do it
Kernel
1. Create Kobject or attach an attribute to a previous kobject
2. When you want to signal userspace call sysfs_notify on the kobject and attribute
Userspace
Create a new thread that will block while waiting for the sysfs_notify
Open the sysfs attribute from this thread
poll the attribute, once sysfs_notify from the kernel is called it will unblock your poll
call your event handling function
Another alternative would be to use eventfd. You create eventfd, pass the integer file descriptor to kernel space (e.g. through sysfs, or ioctl), then convert the file descriptor you got from user space to eventfd_ctx in kernel space. This is it - you have your notification channel.
User space
#include <sys/eventfd.h>
int efd = eventfd(0, 0);
// pass 'efd' to kernel space
Kernel space
#include <linux/eventfd.h>
// Set up
int efd = /* get from user space - sysfs/ioctl/write/... */;
struct eventfd_ctx* efd_ctx = eventfd_ctx_fdget(efd);
// Signal user space
eventfd_signal(efd_ctx, 1);
// Tear down
eventfd_ctx_put(efd_ctx);
I have developed a SPI platform driver for a single SPI device.Which SPI device we are using,that configuration can be given in Device Tree.probe() function of SPI platform driver is called when name matching happens with name give in driver and the same present in DT.
In SPI platform driver module_init() method, we register SPI device structure (struct spi_driver spidev_spi_driver) with function call: spi_register_driver().
Please refer to the (static struct spi_driver spidev_spi_driver) in below link for example.
Link: http://lxr.free-electrons.com/source/drivers/spi/spidev.c#L664
Here Probe() is one important method registered in this call.
When probe function is called, kernel passes pointer of SPI device (e.g struct spi_device *spi) in probe() function which is further utilized in read and write operation with SPI device.
All the above procedure happens only once for a single SPI device.
Now I have query here that if I want to use more than one SPI device present in my micro controller e.g. imx6 then how I will handle this situation?
How will I receive SPI device pointers in this case?
Is the probe function will be called twice (bcoz here only I get SPI device pointers from kernel)?
Do I need to create entries such as done in spidev_dt_ids:
http://lxr.free-electrons.com/source/drivers/spi/spidev.c#L657
I haven't worked on specifically spi device, but I think I might give you some basic idea. The logic is that probe is called whenever there is matching between device->name and device_driver->name. So 2 devices can use same driver but 2 drivers should not be there for same device.
For configuring 2 devices to same driver, the 2 device will be registered on same name and hence same probe will be called. But then in probe you can differentiate. You will have access to the device struct of spi which you can use to set one parameter to distinguish and set the relevant parameters.
One more approach is like using core framework used by i2c in which general functionality functions are made and used by client driver whenever needed.
I hope this helps.
What does ioctl do in the structure struct tty_driver?
I know the ioctl() function provides the means to control the hardware (Keyboard, Mouse, Print) but for example a driver to control the leds on the keyboard I think that the ioctl is more than enough to do this task...
So why I need a tty_driver? I know tty_driver is a struct
P.D I've never tried to program a Device Driver. I've only read a bit of code in some books.
When developing a new driver, the struct tty_driver structure is used to register a tty_driver (using tty_register_driver() 1). This code creates a new device file and set the file operations to some tty specific functions.
The ioctl entry in the newly created file operations is set to tty_ioctl() 2 which after handling some of the basic commands will call the .ioctl function set in the struct tty_operations 3 referenced in the struct tty_driver.
By defining ioctl (note that it is checked if it is not NULL in 3) the developer can implement ioctl commands specific to its device or simply be notified of some other standard commands.
I would like to copy data to user space from kernel module which receives data from serial port and transfers it to DMA, which in turn forwards the data to tty layer and finally to user space.
the current flow is
serial driver FIFO--> DMA-->TTY layer -->User space (the data to tty layer is emptied from DMA upon expiration of timer)
What I want to achieve is
serial driver FIFO-->DMA-->user space. (I am OK with using timer to send the data to user space, if there is a better way let me know)
Also the kernel module handling the serialFIFO->DMA is not a character device.
I would like to bypass tty layer completely. what is the best way to achieve so?
Any pointers/code snippet would be appreciated.
In >=3.10.5 the "serial FIFO" that you refer to is called a uart_port. These are defined in drivers/tty/serial.
I assume that what you want to do is to copy the driver for your UART to a new file, then instead of using uart_insert_char to insert characters from the UART RX FIFO, you want to insert the characters into a buffer that you can access from user space.
The way to do this is to create a second driver, a misc class device driver that has file operations, including mmap, and that allocates kernel memory that the driver's mmap file operation function associates with the userspace mapped memory. There is a good example of code for this written by Maxime Ripard. This example was written for a FIQ handled device, but you can use just the probe routine's dma_zalloc_coherent call and the mmap routine, with it's call to remap_pfn_range, to do the trick, that is, to associate a user space mmap on the misc device file with the alloc'ed memory.
You need to connect the memory that you allocated in your misc driver to the buffer that you write to in your UART driver using either a global void pointer, or else by using an exported symbol, if your misc driver is a module. Initialize the pointer to a known invalid value in the UART driver and test it to make sure the misc driver has assigned it before you try to insert characters to the address to which it points.
Note that you can't add an mmap function to the UART driver directly because the UART driver class does not support an mmap file operation. It only supports the operations defined in the include/linux/serial_core.h struct uart_ops.
Admittedly this is a cumbersome solution - two device drivers, but the alternative is to write a new device class, a UART device that has an mmap operation, and that would be a lot of work compared with the above solution although it would be elegant. No one has done this to date because as Jonathan Corbet say's "...not every device lends itself to the mmap abstraction; it makes no sense, for instance, for serial ports and other stream-oriented devices", though this is exactly what you are asking for.
I implemented this solution for a polling mode UART driver based on the mxs-auart.c code and Maxime's example. It was non-trivial effort but mostly because I am using a FIQ handler for the polling timer. You should allow two to three weeks to get the whole thing up and running.
The DMA aspect of your question depends on whether the UART supports DMA transfer mode. If so, then you should be able to set it using the serial flags. The i.MX28's PrimeCell auarts support DMA transfer but for my application there was no advantage over simply reading bytes directly from the UART RX FIFO.