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

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.

Related

Is there a way to programmatically detect type, manufacturer, name and/or description of i2c device on raspberry pi

I have a raspberry pi connected with multiple i2c devices and want to be able to programmatically work out the type, manufacturer name, device name and/or description for each device on the i2c bus.
Is there any way to do this? Can it be done in python?
I can already get the ID numbers with python code the does essentially the same as i2cdetect, but it doesn't give any information that tells what each device is.
That means I have to manually dig through data sheets and then still have to disassemble the hardware and test with each individual device as the only one connected, to identify which device is at which ID, since some devices can be customized by altering their factory ID.
Putting it together in the first place was a huge job that I don't want to repeat, so I would rather have a way to identify each device programmatically.
Does anyone know how or if this can be done? Does i2c protocol lend any support for that?
Could it be done indirectly, ie. is it possible to power down or otherwise temporarily mute or disable an i2c compatible HAT while the Raspberry Pi is running and then rescan the i2c bus and identify which ID no longer shows up?
No, the I2C bus is not designed for this.
The only way to do something like this is to have the knowledge of the possible addresses for each type of device stored somewhere, together with a way of detecting whether it's really that particular device. Some devices (such as the BMP/BME sensor family) have a ID register that can be used for this, but others don't have that. There are even devices (such as displays) that don't even support reading any data from them.

How does the Linux Operating System understand the underlying hardware?

I want to learn how Linux OS understands the underlying hardware.Can anyone suggest me where to start for getting this understanding,As of now i just know the '/dev' sub-directory plays a vital role in that.
It has the device special files which are like a portal to the device driver which then takes it to the physical device.
I read somewhere that Udev daemon listens to the netlink socket to collect this information and Udev device manager detects addition and removal of devices as they occur.
But with these i am just not satisfied with the thought of how Linux reads the hardware.
Please let me know where to start to understand this, i am so thankful to anyone trying to help.
I think at first you need to find out how the memory mapping works. What is the address space and how it relates to physical memory. Then you could read about how the hardware is mapped in address space and how to access it. It is a big amount of docs to read.
Some of those information are in Linux Documentation Project.
Additionally some knowledge about electronic would be helpful.
In general - Linux for communication with devices needs some "channel" of communication. This channel may be for example ISA, PCI, USB, etc bus. For example PCI devices are memory mapped devices and Linux kernel communicates with them via memory accesses. So first Linux needs to see given device in some memory area and then it is able to configure this device and do some communication with it.
In case of USB devices it is a little bit complicated because USB devices are not memory mapped. You need to configure USB host first to be able to communicate with USB devices. Every communication with USB device is achieved via USB host.
There are also devices which are not connected via ISA, PCI or USB. They are connected directly to the processor and visible under some memory address. This solution is usually implemented in embedded devices. For example ARM processors use this approach.
Regarding udev - it is user-space application which listens for events from Linux kernel and helps other applications with recognizing device addition and configuration.

difference between device file and device driver

I am currently reading the Linux Module Programming Guide and I have stumbled onto two terms that have confused a bit - device files and device driver. Upon goggling these terms I have come across the following-
A device driver is a piece of software that operates or controls a particular type of device.
A device file is an interface for a device driver that appears in a file system as if it were an ordinary file. In Unix-like operating systems, these are usually found under the /dev directory and are also called device nodes.
What I would like to know is -
1) Are device files an interface between user space programs and the device driver?
2) Does the program access the driver in the kernel via the appropriate device special file?
eg, when using say spidev char dev file, does that allow my userspace program to interact with spi.c and omap2_mcspi.c etc using simple read, write and ioctl calls?
One of the primary abstractions in Unix is the file (source):
Programs, services, texts, images, and so forth, are all files. Input and output devices, and generally all devices, are considered to be files, according to the system.
This lets users treat a variety of entities with a uniform set of operations, even through the implementation of those operations may be wildly different.
As you were getting at with your question, device files are the user facing side of the abstraction. This is what the user sees; a file that they can write to, read from, open, close, etc. The device drivers are the implementation of those operations.
So the user will make a call to a file operation such as write, and then the kernel will then use the device driver to carry out the operation.
Device File like /dev/spidevX.Y is a SW abstraction of a SPI device which exposes Linux low level SPI API to the userspace with syscalls (in Linux driver world known as "file operations"):
That is read(), write(), ioctl()...
spidev.c is a special kind of driver which is registered for generic SPI client(chip) devices, and it's main goal is to export Kernel low level SPI API to userspace.
There is a whole Linux SPI layer in between defined in spi.c
Device driver representing real HW SPI controller is where callbacks (hooks) are implemented and registered to the kernel as a part of spi_master (spi_controller)structure.
Here is a callback initialization for SPI message transfer:
master->transfer_one_message = atmel_spi_transfer_one_message;
everything in linux is a file.
device driver is a software used by operating system to communicate with device.
device driver makes use of device files.

Implement SDIO to interface SPI device

People,
I have always seen references about how to use a SPI interface to operate a SD memory card.
This is not what I want. I need to do exactly the opposite.
I want to be able to use the SDIO controller (through SD slot) in my "host" (any PC having a SD-card interface) to talk to my devices (basically microcontrollers) that can only "speak" SPI.
If my understanding is not too wrong, I cannot simply tell my SD controller to talk in a raw SPI mode but I can teach my microcontrollers to behave as a SDIO device that can be controlled by my host.
This way I still have two challenges left:
Correctly implement a generic SDIO device in my microcontroller.
Implement/configure the correct drivers in the host to be able to interact with my devices.
Implement the SDIO device seems to be a matter of following the spec.
The host-side driver, though, is something I hope I can accomplish with a user-space driver in Linux using some already existing kernel-space driver to SDIO.
That's the point that I come to ask for help.
Can anyone please point me any samples, documents or any kind of resources that can help me in my task?
On the PC side, this is all you need: http://sourceforge.net/projects/sdio-linux/
This may be useful for reference: http://www.varsanofiev.com/inside/WritingLinuxSDIODrivers.htm (although, I don't think you would be writing a driver)
On the microcontroller side, use "bit-banging" to implement the SDIO spec.
However, first consider why do this. SDIO and SPI are just serial protocols, so is USB; wouldn't you rather make an SPI-to-USB bridge? USB is much more user-friendly on the host side, as well as being more standard/more common. And if you do want a SPI-to-USB bridge, turns out it already exists, the SPI Shortcut (probably other options, this is just the first one that comes to mind)
EDIT Or, you could bit-bang I2C on the micro, if the host supports I2C (many do). Actually, go through every serial protocol the host supports, and see if you can support it easily from the micro side (by bit banging, since the micro is likely to not have a slave mode for that protocol built-in). RS232 (with level shifter), I2C, and SPI are likely to be the preferred choices. SDIO is pretty much the last choice, I think.
SDIO is very tightly specified. Unless your microcontroller has an SDIO block that is designed to act as a device rather than host, I don't think this will be possible. I know of a few special purpose communications controllers that implement an SDIO device, but I haven't come across any general purpose microcontrollers.
You would need a fairly fast microcontroller to be able to bit-bang SDIO initialization at up to 400 kHz. If running an STM32F4 at 180 MHz, this gives you only microcontroller cycles between SDIO clock cycles. If the host turns up the clock speed to the maximum of 25 MHz after initialization, then you're down to 7 cycles between SDIO clocks.
For perspective on the SDIO spec, the one you linked is a simplified spec that doesn't cover the signalling and timing of the bus. The full spec is many times larger.
As Alex I mentioned, there may be better alternatives for what you need. If your SDIO host supports SPI mode, most microcontrollers do have SPI peripherals that can act as slaves rather than hosts, so this may be an avenue without a peripheral. If your data rates are low enough, a simple UART may suffice (you can reasonably hit 1 Mbit over short distances).

Which h/w knoledge needed to have to become a Device driver programmer?

I am very interested in device driver programming .I have started reading the LDD3 ,there author said
"to become a device driver programmer you have to understand your specific device well"
can any one tell me what is the meaning of the "understand your specific device" .what are the thing I should know before writing a device driver.
Thanks
That's a basic list with software and hardware combined.
The Operating System driver API
The processor architecture as it relates to hardware interfacing
The 'bus' structure that interfaces the device hardware to the processor
Interrupt Handling
Dma Control
Processor Caching
Processor MMU control
OS Semaphores and scheduling
Data/Byte Alignment
Assembly language when needed
Control of Instruction Execution Order and Optimization
Consideration of performance issues
What's IO and memory mapped hardware ?
http://www.cs.nmsu.edu/~pfeiffer/classes/473/notes/io.html
This link talks about generic hardware access in Linux device drivers.
http://www.linuxforu.com/2011/06/generic-hardware-access-in-linux/
This is specifically about USB hardware
http://www.beyondlogic.org/usbnutshell/usb2.shtml
Check lwn.net it never disappoints a device driver developer.
https://lwn.net/Archives/
Last, but not least, They have everythig, CPU, Memory, Camera, PCI..
http://www.hardwaresecrets.com/page/memory
-
Hi, I'm very pleased to share what I have learnt with you guys.
Yes, it is the basic need to know your device if you wanna be a device driver programmer. I also want to be a linux device driver programmer, or even more, though I have some device driver experience under other software platforms.
The reason why you wanna contact with it is that you wanna make it do something for you.
Normally, what it can do is the first thing you must know. It's very obvious that you will never send Ethernet frames through UART or SPI, right?
There exist various kinds of devices in the world, such as, storage device, FLASH, SD card, harddisk; communicating devices, network card, wifi; interconnected bus, PCI-express; how many there are.
After that, the next thing you will concern is how you can do to reach your goal.
To access the device, reading, or writing, there is usually a controller embedded in the processor. Here, when I say "processor", it means it is a core integrated with various kinds of controllers, no matter pc desktop or embeded system areas.
The Controller is the interface you will face, to work on the device behind the controller.
Through the controller, you can ask the device to do what you want. In the controller, there are registers, which are the deepest points the software can touch. Beyond that lies the hardware, as you are a device driver programmer, it is very common for you to communicate with hardware engineers to make things done.
If going into details about the register, there are control registers used to tell device what you want it to do, status registers, used to reflect the status of operations underway in devices, if interrupt is supported by that device, there are also some registers for you to deal with interrupts.
Well, I almost forget there are also data registers, whicha are used to store the data to be sent or written, or to be read by user. According to the specific implementation, registers used to store data from upper users to be sent or written and registes used to hold data from outside that will be read by users may be the same, or may be not.
In a normal way, if you wanna let someone do something for you, you should provide something to him first. Whoever wants to do anything, there must be some inputs to him, right?
in a summary,
action(read,write,or others) + data(you give, or you ask for) + status(what progress it is)
what it can do
how it does that, how to assemble the command cell, time sequence?
what you must provide it to reach your goal
genarally, two kinds of things you should provide:
if you ask for, where to store what you ask for;
if you give, where are what you give
how it reflects the progress of operations, polling or interrupts
Well, that is all I want to share with you.
Thanks.

Resources