multiple devices, single driver - linux-kernel

I have developped a linux device driver for a PCI-e fpga card, and it's working.
Now, let's suppose that I would like to install two (equal) of these pci-e card on the same pc.
how does it work? I tried to insmod the driver, I expected a "double probing" callback but it wasn't. So, how can i manage this situation? by the minor number? could someone help me?
ps
the pci card are fpga development board, so they are actually "the same" card, maybe I have to differentiate something in the hw?

The situation will be different in case your driver is built-in instead of a kernel module to load. Try to compile it as a built-in driver and make sure that your cards are both powered ON. In that way, both of your cards will be enumerated, then probed by the same driver.
The fact that you insmod the driver, in that case, it relies on the code itself and the way you wrote your driver. If you can share the driver, I would be helpful.

Related

How to tell linux retrain and scan PCIe bus?

We have an embedded board that has an iMX8M-Plus Processor and Linux v5.4.161. This board has one PCIe bus and that one is connected to an FPGA. When we power up the board, the FPGA is not yet configured, so it acts as if it was not on the PCIe bus.
Once the Linux is fully booted, we configure the FPGA and only after that it starts acting as a PCIe endpoint (device).
At this point, when I run lspci -> it returns nothing.
When I first execute echo "1" > /sys/bus/pci/rescan as suggested here and here and then lspci, I still get nothing.
But if I reboot the linux without reseting the FPGA, it starts being visible in the lspci list. Rebooting the linux is not an option for us. Somehow I need to tell the linux that whatever it's doing at the boot time, please do it again at runtime. But I couldn't find a solution for this so far.
According to the Texas Instrument support forum, they said if the PCIe link is not trained at the boot time, rescan command never works.
At the boot time, while linux loads a pci driver, it tries to establish a PCIe link, I can see that with an oscilloscope, PERST pin is asserted and PCIE_CLK generated for a while and then stops if it can not detect any device. But the rescan command never does that.
Also in the system there is no pcie device to executeecho 1 > $pcidevice/remove in order to make rescan functional. Or there is no device or bus to set power off and on back like echo 0 > /sys/bus/pci/slots/.../power
I also learned that there was a method in old linux times (v2.6) called adding a Fake PCIe Device which physically doesn't exist to solve this problem. For that I took the fakephp.c driver from an old linux repo and ported it to ours. After solving a couple of deprecated function problems, it is compiled for Linux Kernel v5.4. modprobe fakephp worked and driver loaded but somehow I didn't get this fake device in my device list. Here it is mentioned that the fakephp driver was removed from mainstream linux since PCI core has similar functionality, but he never mentioned how.
Short of the story is that, I am stuck here, I need my FPGA to be visible in the lspci list without restarting the linux.
I recommend configuring the FPGA in u-boot to get away from these kinds of problems. Connect up SPI pins to FPGA's config pins & run it in Slave configuration mode.

Detect spi device from another driver

I have a Freescale imx.6q (arm) based board.
Hardware is configured with devicetree.
It had a change major incompatible change to timings and voltage for an onboard fpga, but these changes are invisible to the kernel.
The EE's tell us we shouldn't load the old fpga firmware for fear of damaging it. I would like to support both hardware from the same code (It is already causing confusion)
The solution I have thought of is this:
There are several new spi temperature sensors on the board. If I can read from one of those devices, I can infer that I need the new firmware.
How can I (in one driver) grab an spi device and then release it?
I suspect that I might be able to do something like this with device tree,
But I don't want to make the device unavailable.
Any ideas or examples of something like this being done?
After reading question i think your concern is how to add software support for more than one hardware.
If that is the case i think we can write two drivers supporting both hardware's with different configuration such as irq, voltage, register set etc.
So i will enable both drivers in Makefile and config file.
So at the time of boot when probe of drivers gets called we can check the hardware id by using spi_read command from driver.
If hardware id matches then driver probe gets successful and driver can be used to interact with hardware.
If spi_read fails then driver probe itself will fail.
I think this will do the trick.
EDIT (answer the question)
To detect use an SPI device from another driver use a reference to the device in the devicetree structure.
Short answer: add a reference to the spi device in your devices dts entry.
Slightly longer answer:
When adding spi to another device driver, you are effectively adding a subdevice, which may want its own driver. I have an FPGA which loads its firmware over (something close enough to be considered) SPI. I started with the idea of just treating the spi device as part of the larger driver, but the more work went into it, the more obvious it was that it is its own device, with a purpose and function that is distinct from the rest of the driver. I separated that code into its own driver.
Now instead of a reference to an SPI device, my driver just has a reference to an FPGA Manager device.
See line 98, 370 of https://github.com/d4ddi0/linux/blob/v4.12evi/arch/arm/boot/dts/imx6q-evi.dts
and
make sure the spi driver is loaded before your driver completes loading
My original answer to my question (for historical purposes):
What I ended up doing was using different devicetree files. The difference is know at initial install time (based on the serial number). The bootloader knows which dts filename to load.
There are multiple FPGA firmware versions and the right one is chosen based on the description in the dts.
This way, I can still update the driver and/or dts without breakage.
This works well in practice even though it does not detect anything at runtime.
One problem still exists, if I take an SD card from a new revision, and put it into an old one, the incorrect firmware will be loaded. To really solve this last problem, we've talked about adding an EEPROM to uniquely identify the hardware revision on future boards.

Is it possible to override a driver that has been compiled into the kernel?

I have a USB device for which I have an API. This API only works if the USB device doesn't use the ftdi_sio/usbserial drivers.
On my laptop, if I plug the USB device in, these drivers get loaded (as modules) and I have to unload them using modprobe -r after which code using the API can see the device.
I have another device which experiences the same issue although no modules are loaded so I'm guessing these drivers are compiled into the kernel. My question is this - is there any way to stop this device from using these drivers or do I have to recompile the kernel, etc?
Thanks for any help!
You are essentially looking for a way to :
unbind the default driver from your USB device
and
bind a driver of your choice to it.
Take a quick look at this to get you started.
A slightly more detailed description of the same is available in this excellent LWN article of (un)binding device drivers.

Keeping device functionality inside device controller rather than OS kernel. What are consequences?

A friend of mine asked me this question in the class and I could not answer it. He asked:
Since we know kernel controls the physical hardware via device drivers. What if all this functionality is kept inside the device controller itself rather than kernel managing them. What would be the consequences of such scenario? Good or Bad?
I searched online for this question but could not get information about this scenario. May be I'm not googling in the right keyword.
You insight into this will help me getting clearing my concepts.
Please answer.
Thanks.
Your question seems to propose the elimination of the "device driver" by "keeping" "control (of) the physical hardware ... inside the device controller". The premise for this seems to be:
kernel controls the physical hardware via device drivers.
That description of a device driver is something similar to what I've seem for end-user comprehension rather than from a developer's perspective. The end-user is aware of the device, and it is the device driver that takes that abstraction and can control that device down to the specific control bits of each device port.
But a device driver is responsible for mundane housekeeping tasks such as:
maintaining device status and availability;
configuring the device for operation;
managing data flow, setting-up/tearing-down data transfers, copying data between user space and kernel space;
handling interrupts and exceptions.
These tasks are integral to a device driver. These tasks cannot be transferred out of the purview of the kernel driver to a peripheral device.
Sometimes the device driver can only try to manage the device, rather than fully control it, for example, a NIC driver during a packet flood.
There is simply no possibility that you can eliminate a device driver no matter how much of "all this functionality is kept inside the device controller itself". And there would still be control directives/commands issued from the device driver to the peripheral.
The hardware device in question should be a computer peripheral device, not an autonomous robot device. The device should be designed to operate with a computer. Whatever interface there is between processor and device should be suitable for the task. If the peripheral is made more "intelligent", then perhaps the CPU can be unburdened and a high-level command interface can replace low-level sub-operation directives. But only "some" functionality can be transferred to the peripheral, not "all".

How to read from USB without any driver?

We are creating small system which has GPS receiver and PC. We want to test my GPS receiver, We do not want to go for a driver on the first go. First I would like to test my circuit works or nor. GPS IC has been set to output NMEA sentence. We want a program which just reads data from USB port and print it on the screen.
Can we write something like this easily ? Do we have any open source tool which will achieve this purpose ?
Platform : Windows 7
All devices need a driver, so I'm going to interpret your question as "how can I read NMEA data from my GPS using only drivers provided by the OS, so I don't have to write my own?"
If the GPS chip has a USB interface, then you should have gotten a driver with it. But most GPS chips have a UART interface which in your case sounds like it is connected to a separate USB-UART conversion chip. That conversion chip most likely came with a driver as well, but if not, you could jumper the reset pin of the converter chip, disabling it, and then attach a TTL/RS-232 level converter (available off-the-shelf) to the UART traces and then to your computer's serial port.
Unless you suspect that the driver for the USB-UART converter is causing problems, I wouldn't bother.
Anything connected via USB is a device. Devices require a device driver, period.
You might be able to get away with an existing driver built into Windows. This is how USB memory keys work for example - they present a generic device that looks like a removable disk, and Windows already includes the drivers for generic removable disks.
You would need to check the documentation for your device to see if it can emulate a device which already has drivers. Otherwise you must install the company's drivers, or you're out of luck.
Have a look at libusb. You should be able to read the data with that and a little code. (Yes, it's a driver. I take the question to mean "without writing a driver".)
You need a device driver for your device. Unless Windows already have a class driver for the device.
For USB devices on Windows 7 you can write a user-mode driver, see UMDF.

Resources