On my board (x86_64, Android Lollipop, kernel: 3.14), "pci bus" goes in D3 sleep state and when I'm trying to wake it up by setting it D0 state it's failing with message:
Error log:
Refused to change power state, currently in D3.
After going through pci architecture, I came to know that we cannot bring up pci from D3hot to D0 initialized, we need to follow something like:
D3hot -> D0Uninitialized -> D0Initialized
But I'm unable to figure out how to do that, please help me to find out appropriate solution
After debugging further, I figured out that, power state transition for pci device (i.e. D3 to D0) is working fine when it's requested within pci driver (i.e. pcieport) but as I'm trying to wake up pci device through iwlwifi driver facing above mentioned problem, as it's not able to write wake request to pci chip.
Any help or any clue will be much appreciated.
After a lot of research I found that, If any device wants to use acpi features to communicate to OS, should be registered in ACPI table.
In my case my wifi chip was not registered with ACPI table, because of it was unable to use ACPI features.
Related
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.
I am working working on linux PCIe and NVMe driver. I came across a function in pci driver, pci_reset_bus(), which does pci reset via slot or bus. I understand that reset via bus is "PCIe hot reset" which is defined in PCIe spec. But I am not sure what is pci slot reset (which is implemented by __pci_reset_slot()).
Could anyone help me understanding this? and Also can I use this exported symbol i.e. pci_reset_bus(), for pci hot reset? I want to use this in my custom NVMe driver.
I found a good tool("NVMeCraft") to handle some NVMe SSD. You can directly confirm your question with that tool, and can found the tool with googling.
I have an AOSP tree compiled on my board. I bought a wireless keyboard and connected it to my board via usb port. I expect when the board is in the suspend state, it will wakeup by pressing a key on keyboard. But it is not so.
I tried several ways in my bootloader (uboot), kernel, etc. But no effect. Additionally I made an experiment and found out that in the sleep state, my usb port (which has a dongle in it) has just 1-5 mA. But it should be higher for the dongle to work!
Has anyone experienced this? How to enable remote wakeup for usb in android?
Thanks
More info:
The uboot supports usb host controller interface. I tweaked kernel build options. but these two actions has no effect.
EDIT : I work on p212 reference board of amlogic. Its SoC is Amlogic S905X.
EDIT 2 : I tested the board (which is a tv box actually) using my phone and its charger and I found that when the box goes to sleep, the charging is stopped!! So I can deduce that the dongle has not enough power to stay alive! (yet to send wake signal to SoC !)
Then I carried out a second experiment: I connected the phone using a USB charger which only has two pin instead of four. (Just voltage supply; differential pins (signal pins) are disconnected). The result: my phone is charging now!! It seems when the SoC is suspending, it sends a signal to USB peripherals telling them to not draw power. Am I correct? How can I configure my AOSP tree and Linux kernel and uboot bootloader to avoid happening this?
Please guide me how to fix it in kernel or other parts of stack!
EDIT 3 :
I have pasted my kernel config here. I configured these options to y but has no effect:
CONFIG_PM_RUNTIME=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_DEBUG=y
CONFIG_USB_OTG_WAKELOCK=y
CONFIG_USB_DEBUG=y
CONFIG_USB_OTG=y
Also this link is my device tree files. (in kernel. NOT uboot)
So if I understand things correctly, cat /proc/iomem lists the memory addresses that are mapped to this and that device register and similarily for ioports. If you pick up some book on Linux device drivers, it will state something about iomem being populated by the driver calling request_region() or something like that.
But how does the device driver know where the hardware register is located at from the get-go? For example, rtc0 seems to occupy 0070:0071 for most people - how does Linux/the device driver know that the transistors and wires of my system are hooked up so that flipping exactly those bits corresponds to reading a signal from the RTC?
If you pick up some book on Linux device drivers, it will state something about iomem being populated by the driver calling request_region() or something like that.
The information in /proc/iomem comes from drivers calling request_mem_region().
See Content of /proc/iomem.
how does the device driver know where the hardware register is located
The address of a device register is typically specified by either the board (for an external peripheral) or SoC designer (for an integrated peripheral), and then conveyed in the board or SoC documentation. Some boards (e.g. PC ISA adapter boards) may allow address specification by some DIP switches.
The writer of the device driver then can
(a) hardcode the device address in the driver itself or a board file, or
(b) retrieve the device address using some bus configuration method (e.g. PCI configuration space), or
(c) retrieve the device address using a (handwritten) configuration list (e.g. Device Tree, FEX, ATAGs), or
(d) try to probe the device at runtime.
Note that conveying the system configuration and device addresses to device drivers is a longstanding issue.
The IBM PC's method of assigned addresses that were then hardcoded eventually led to the plug and play initiative for x86 PCs.
Issues with unique Linux kernel builds for each and every ARM board led to the adoption of Device Tree (from PowerPC) for that architecture.
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.