What can be removed from the Linux i2c-dev driver to serve as a base for a new driver meant for only one device? - linux

I'm trying to write a Linux character device driver for a device that just happens to communicate over I2C. The device is an Atmel microcontroller with code that provides an I2C address. It already works using the typical i2c-dev method on the Linux-side.
So now I want to replicate i2c-dev as a new driver that works specifically with this particular device, so that I can add some of my own device-specific abstraction code on top. But I'd like to trim out all the unnecessary code from i2c-dev that currently makes it generic. What can be removed in this situation?

What can be removed in this situation?
You're actually asking an XY question.
You would be better off looking at and adapting an existing I2C device driver that is already similar in required functionality, rather than hacking a special case driver for userspace access.
So now I want to replicate i2c-dev as a new driver that works specifically with this particular device, so that I can add some of my own device-specific abstraction code on top
So then you actually need to write a "Client driver" as described below (from Linux Documentation/i2c/summary):
When we talk about I2C, we use the following terms:
Bus -> Algorithm
Adapter
Device -> Driver
Client
An Algorithm driver contains general code that can be used for a whole class
of I2C adapters. Each specific adapter driver either depends on one algorithm
driver, or includes its own implementation.
A Driver driver (yes, this sounds ridiculous, sorry) contains the general
code to access some type of device. Each detected device gets its own
data in the Client structure. Usually, Driver and Client are more closely
integrated than Algorithm and Adapter.
Details are in Documentation/i2c/writing-clients.
To find a driver of similar functionality, scan the list of I2C client drivers. Note that these I2C drivers are located in the Linux source tree by their functionality (e.g. drivers/rtc/ or drivers/hwmon/) and not their interface (i.e. I2C).

Related

How do I write a network device driver using SPI?

I have implemented a device driver for the NRF24L01+ transceiver in userspace using rust. The userspace driver makes use of the kernel spi interface driver. Writing the driver as kernel module seems incredibly hard, as the documentation for linux/netdevice.h as found in linux device drivers seems outdated (or I'm just not smart enough to understand the intricate details).
A new project from the TU Munich proposes the use of vfio. From my understanding this type of driver implementation uses the iommu to manage isolation to protected memory areas for the devices. "Project Ixy" uses the network device as block device, hence it can be mapped. SPI is different as insofar it is a streaming protocol.
My question is, if it is possible to integrate the user space spi network device driver into the linux network stack, e.g. having all protocols etc handled by the network stack. Is it possible to use a similar approach as Project Ixy, like having a small component in kernel space, which is isolated for security, that builds a "bridge" to userland?
I think it is possible in two ways:
using TAP interface
writing your own "bridging" interface like TAP between user space and kernel space
If ethernet-like interface is enough for you - then use TAP. I mean TAP provides functionality where physical layer is moved to user space. In your case it could work like this: data received by SPI can be pushed to TAP interface to linux network stack. The data received from TAP interface (from Linux network stack) you can push via SPI. Is that what you wanted?
If ethernet-like interace (as TAP is) is not enough for you - you can write your own interface in kernel space basing on TAP sources.

Linux device driver with optional multiple platform driver interfaces

Suppose I have a chip that has multiple options for interfacing with it, for example, the chip may have an I2C interface and a SPI interface and I can choose one of these interfaces and wire the device accordingly. How would I write a linux device driver for such device?
A chip with this behavior is ssd1307, which already has a driver implementation in the mainline linux kernel (https://github.com/torvalds/linux/blob/master/drivers/video/fbdev/ssd1307fb.c), implemented only for its I2C interface (the chip also has a 3/4 Wire SPI Interface). As you can see in the code, the probe function relies heavily on the fact that it is an I2C interface, so in order to use the SPI interface I would need to write an entirely new driver, repeating a lot of common code, or insert a lot of #ifdefs, which don't seem to be good approaches to me.
For chips providing several interface types, standard practice is to provide core driver and interface-specific frontends for it.
Several examples could be found e.g. in sound/soc/codecs/: pcm179x.c / pcm179x-i2c.c / pcm179x-spi.c and others.
This is not (yet?) done for ssd1307.

How do 'clients' fit in with 'platform devices' and 'platform drivers'

Reading about the driver-model platform, my understanding is that a platform driver is a static piece of kernel code that controls a platform device, which is a device which generally is always present in the system, as opposed to a driver composed of a kernel module, which can be loaded or removed at will and controls devices which might not always be connected. This answer seems to support that statement.
If all this is true, I expect it's what I'm looking for. I am trying to write a kernel module which, among other things, needs to communicate with an external device over I2C. While the external device isn't always part of the system, the I2C bus IS, so it ought to be controlled by a platform driver. So rather than writing code in my module to directly control the I2C, I ought to be using the platform driver. I found what I believe to be the proper platform driver for the I2C bus on my platform here, and it does use < linux/platform_device.h >, so that seems to be consistent.
However, in addition to this, when looking up I2C in general, I have seen reference to an I2C "client". From the name alone, this sounds like what I am trying to write now, a kernel module that uses the platform driver to communicate over I2C. However, in the documentation for the driver-model platform, nothing about a "client" is mentioned, so I don't know if this is correct or if it is some completely separate different model.
So how does a "client" kernel module fit into the driver-platform model for interfacing with hardware in Linux? Is my module supposed to instantiate a struct of the i2c_driver, or is that something done by the platform driver, and the module is supposed to create an interface to that?

Simple SPI device driver

I have written a simple driver for a character device in Non Blocking mode using epoll.
Now I would like to use that driver for SPI interface.
What should be the device name or how will I map the actual device with the kernel ?
How will I use the interrupt?
Also who is the Master and Slave?Suppose I am connecting a SPI compatible device to the panda board.Will that device becomes a slave and the development board becomes Master?
I am a newbie.I am using a panda board.
In what way should I go through the Technical Reference manual?
I would really appreciate if anybody would explain and clarify my doubts.
You probably want to connect your driver to a SPI bus driver. This requires a slight reworking of your driver. See drivers/spi/spi.c
You'll be using the commands for the bus (master, the CPU side) to read and write the commands to the unit.
I don't know what a Panda board is, but if it connects via SPI, it might be a master, but it is probably a slave.
Go through the basics of spi here

How should I structure a linux driver that uses several chips in one device?

I have a hardware device that consists of 3 separate chips on an I2C bus. I would like to group them together and expose them to userland as one logical device. The user would see the logical device represented by a single directory somewhere in /sys as well as the nodes you'd expect from the I2C chips under /sys/class/i2c-adapter/i2c-?/*.
One of the chips is an MCP23017 which as far as I can tell already has a driver (drivers/gpio/gpio-mcp23s08.c) and I'd like to reuse it. Another of the chips is a PCA9685 and I would like to contribute a driver for this chip that uses the PWM system in include/linux/pwm.h. The third chip is an MCU running custom firmware.
How should I structure the set of drivers? One idea I had is to register a platform driver to present the logical device, and use I2C drivers from within that. Is this a good way to go? Are there better ways?
The logical device is a motor driver board and IR receiver. I have a simple diagram of its structure.
I'm looking to create two interfaces. The first similar to /sys/class/gpio where motors can be 'exported' and then accessed via reading and writing attributes. This would be useful for shell script access and quick debugging of the mechanical parts of the system attached to the motors. The second a character device node in /dev where data can be read or written in binary format, more useful for application control.
it seems not usual design, are you sure you have access to I2C bus of all chips ?
I think you should be able to talk only to MCU, and MCU should manage other devices.
Otherwise, why MCU is there ?
However, I cannot see your diagram, perhaps link is wrong.

Resources