Use GPIO as chip select for SPI ACPI overlay - linux-device-driver

I want to use a GPIO pin as a new chip select for SPI on an Up Squared board. The Up squared uses an Intel Pentium N4200, so it's a x86 machine. I have managed to this on a Raspberry Pi by using Device Tree Overlays but as this is an x86 machine I may have to use ACPI overlays.
The Up squared has two spi available and they propose here to use ACPI overlays, this repo, which actually works very well. Below one of the asl files they use
/*
* This ASL can be used to declare a spidev device on SPI0 CS0
*/
DefinitionBlock ("", "SSDT", 5, "INTEL", "SPIDEV0", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (TP0) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI test device connected to CS0")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 10 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
I compiled this file using
$ sudo iasl spidev1.0.asl > /dev/null
$ sudo mv spidev1.0.asl /lib/firmware/acpi-upgrades
$ sudo update-initramfs -u -k all
Then I reboot an I can see a device and communicate through it.
up#up:~$ ls /dev/spi*
/dev/spidev1.0
Thus, I decided to write my own overlay based on themeta-acpi samples from intel and I wrote this:
/*
* This ASL can be used to declare a spidev device on SPI0 CS2
*/
DefinitionBlock ("", "SSDT", 5, "INTEL", "SPIDEV2", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
External (_SB_.PCI0.GIP0.GPO, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.PCI0.GIP0.GPO", 0) {
22 // pin 22 is BCM25 or 402 in linux
}
})
Name (_DSD, Package() {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () { "compatible", "spidev" }, // not sure if this is needed
Package () {
"cs-gpios", Package () {
0,
0,
^SPI1, 0, 0, 0, // index 0 in _CRS -> pin 22
}
},
}
})
Device (TP2) {
Name (_HID, "SPT0001")
Name (_DDN, "SPI test device connected to CS2")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
2, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 10 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
But I cannot see the new device. What am I missing?
Edit:
I have modified the code with a code which actually worked. I can see now a device on /dev/spidev1.2.
However, the CS on pin 22 is low all the time which shouldn't be the case. is the number of the pin correct? I'm using pin numbering from here
Edit 2:
Here is the output of my kernel version
Linux up 5.4.65-rt38+ #1 SMP PREEMPT_RT Mon Feb 28 13:42:31 CET 2022 x86_64 x86_64 x86_64 GNU/Linux
I compiled this up linux repository with the RT patch for the right kernel version.
I also installed the upboard-extras package and I'm actually able to communicate through spi for devices /dev/spidev1.0 and /dev/spidev1.1. So I think I have configured the up squared correctly.
There is nongpio file under /sys/class/gpio
up#up:~/aru$ ls /sys/class/gpio
export gpiochip0 gpiochip267 gpiochip310 gpiochip357 gpiochip434 unexport
I can set the GPIO to 1 or 0 and I can see the output on a multimeter, so I think I have right permissions for GPIO.
Edit 3:
Please find in this link the .dat result from acpidump -o up2-tables.dat

I assume that you are using this board. To be able to use I/O pins(i2c, spi etc.), you need to enable them firstly. Easy way to check you already enabled them or not is that typing in terminal:
uname -a
Output of this will be look like:
Linux upxtreme-UP-WHL01 5.4.0-1-generic #2~upboard2-Ubuntu SMP Thu Jul 25 13:35:27 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
In here #2~upboard2-Ubuntu part can be changed accordingto your board type. However if you don't see a similar result, then you didn't configure your board yet. Otherway to check it, go to folder: /sys/class/gpio and check the ngpio file. Inside it, there should be written 28.
To use any I/O pins(i2c, spi etc.), you don't need to change anything on BIOS side, because its coming to you defaultly enabled.
Please check the up-wiki page, and update your board kernel after linux installation. Then your I/O configurations will be enabled. Up-wiki main page.

Related

STM32 code not working, while loop, delay problems

Currently, I'm facing a weird problem with the STM32. I just generated code with the STM32Cube IDE for the chosen MCU (STM32L031G6). I nearly didn't change anything, except configuring one GPIO as output and trying to let a connected LED blink.
Now the problem:
If I run the code, nothing happens, no blink at all.
Stepping through the code, I can enable the LED once when the WritePin is called. Afterwards, just one step further, the LED is off again, although there is no further WritePin call executed. The LED never gets back on again.
What can be the problem with this code? There is nothing special about it? Did I miss something which is required for generated STM32 code?
For the following code I removed any unused line and comment.
#include "main.h"
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while(1) {
//HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
HAL_Delay(1000);
}
}
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
Error_Handler();
}
}
static void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
}
void Error_Handler(void) {
__disable_irq();
while (1) {}
}
Update 1:
As seen in the comments the HAL_Delay is not working properly. But how to fix it? And why the code does not let the led flicker when the HAL_Delay is removed?
Update 2:
It is also not possible to use the loop the following way, but the led is not turned on in any way.
while (1) {
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
See the following images for the configuration.
Update 3:
When executing the code on the STM32L031G6, the debugger stops pretty soon. Stepping through the code works (sometimes). Here is the debug log when clicking "Run" in the STM32Cube IDE.
SEGGER J-Link GDB Server V7.58 Command Line Version
JLinkARM.dll V7.58 (DLL compiled Nov 4 2021 16:23:13)
Command line: -port 2331 -s -device STM32L031G6 -endian little -speed 4000 -if swd -vd
-----GDB Server start settings-----
GDBInit file: none
GDB Server Listening port: 2331
SWO raw output listening port: 2332
Terminal I/O port: 2333
Accept remote connection: localhost only
Generate logfile: off
Verify download: on
Init regs on start: off
Silent mode: off
Single run mode: on
Target connection timeout: 0 ms
------J-Link related settings------
J-Link Host interface: USB
J-Link script: none
J-Link settings file: none
------Target related settings------
Target device: STM32L031G6
Target interface: SWD
Target interface speed: 4000kHz
Target endian: little
Connecting to J-Link...
J-Link is connected.
Firmware: J-Link V11 compiled Dec 9 2021 14:14:49
Hardware: V11.00
S/N: 261014681
OEM: SEGGER-EDU
Feature(s): FlashBP, GDB
Checking target voltage...
Target voltage: 3.34 V
Listening on TCP/IP port 2331
Connecting to target...
Connected to target
Waiting for GDB connection...Connected to 127.0.0.1
GDB closed TCP/IP connection (Socket 1132)
Connected to 127.0.0.1
Reading all registers
Read 4 bytes # address 0x1FF000FC (Data = 0x89B8D002)
Read 2 bytes # address 0x1FF000FC (Data = 0xD002)
Received monitor command: WriteDP 0x2 0xF0
O.K.
Received monitor command: ReadAP 0x2
O.K.:0xF0000003
Read 4 bytes # address 0x1FF000E4 (Data = 0x05408A28)
Read 2 bytes # address 0x1FF000E4 (Data = 0x8A28)
Read 4 bytes # address 0x1FF000E4 (Data = 0x05408A28)
Read 2 bytes # address 0x1FF000E4 (Data = 0x8A28)
Reading 32 bytes # address 0xF0000FD0
Connected to 127.0.0.1
Reading all registers
Read 4 bytes # address 0x1FF000FC (Data = 0x89B8D002)
Read 2 bytes # address 0x1FF000FC (Data = 0xD002)
Received monitor command: reset
Resetting target
Downloading 192 bytes # address 0x08000000 - Verified OK
Downloading 6072 bytes # address 0x080000C0 - Verified OK
Downloading 28 bytes # address 0x08001878 - Verified OK
Downloading 8 bytes # address 0x08001894 - Verified OK
Downloading 4 bytes # address 0x0800189C - Verified OK
Downloading 4 bytes # address 0x080018A0 - Verified OK
Downloading 12 bytes # address 0x080018A4 - Verified OK
Writing register (PC = 0x 80006d0)
Starting target CPU...
GDB closed TCP/IP connection (Socket 1128)
Debugger requested to halt target...
...Target halted (PC = 0x1FF000E4)
Reading all registers
Read 4 bytes # address 0x1FF000E4 (Data = 0x05408A28)
Read 2 bytes # address 0x1FF000E4 (Data = 0x8A28)
GDB closed TCP/IP connection (Socket 1152)
Restoring target state and closing J-Link connection...
Shutting down...
On the other hand, the same code works on a STM32L031K6 of the nucleo board with the ST link disconnected.
*Update 4:
Since I'm using a custom board, there may be a flaw in the schematics. I don't see any issues with the circuit, but maybe, you see some. There is no crystal since it shouldn't be required regarding the datasheet. There are internal oszillators available.
The TOUCH net is just a circuit which connects GND to the pin if a button is pressed.
This is the circuit of the STM32L031G6U6.
This is the circuit of the LEDs that should be controlled. In the previous code I just try to control the LED with the net label STATUS_LED. Since I got the LED to blink while stepping through the code, the Mosfet circuit should work.
I'm currently very confused why I got so many problems. I tried a second and third PCB of the same circuit, but the problems are the same.
I figured out, that I cannot use any clock configurations although they are offered by the STM32Cube IDE. Using the MSI just doesn't work for some frequencies. The code will stall in the SystemClock_Config setting the oscillator or the clock.
Why the HAL_Delay sometimes doesn't work and sometimes it does?
Why the system doesn't start at all when trying to run the code (even with everything disconnected and just the power supply reconnecting)?
Why stepping through the code does work but running the code does not?
Problem solved. The Altium package I downloaded was for the wrong package of the STM32L031. It ia for the STM32L031G6U6S and not the STM32L031G6U6.

Problem with midi setup on Raspberry Pi with midi board for RPi

I bought this one from osa electronics:
https://www.osaelectronics.com/product/midi-board-for-raspberry-pi/
I followed the instructions here on how to set it up:
https://www.osaelectronics.com/learn/setting-up-raspberry-pi-for-midi/
After following the setup and running this in command line:
python
import mido
mido.get_output_names()
It outputs this which seems to be correct:
['Midi Through:Midi Through Port-0 14:0', 'f_midi:f_midi 24:0']
as well as when I run this from command line:
amidi -l
outputs this:
Dir Device Name
IO hw:2,0 f_midi
However when I run some test applications from their webapge I get no input or output.
like this one:
import mido
from mido import MidiFile
from mido import MetaMessage
port = mido.open_output('f_midi')
mid = MidiFile('mymidifile.mid')
while True:
for msg in MidiFile('mymidifile.mid').play():
port.send(msg)
or from this one (I tried to print the msg but it wont print it even. So doesnt seem to step into the while loop but no errormessages)
import mido
import pigpio
from numpy import interp
pi1 = pigpio.pi()
port = mido.open_input('f_midi') # open USB port
while True:
try: # This filters out all non-note data
for msg in port.iter_pending(): # if there is a message pending
print(msg)
if(msg.type == 'note_on'): # if it is Note On message
out = interp(msg.velocity, [0, 127], [0, 255])
#scale velocity from 0-127 to 0-255
# filter the data by note number
if(msg.note == 53):
pi1.set_PWM_dutycycle(2, out)
elif(msg.note == 55):
pi1.set_PWM_dutycycle(3, out)
elif(msg.note == 57):
pi1.set_PWM_dutycycle(4, out)
else: # if the message is not Note On (e.g. Note Off)
if(msg.note == 53):
pi1.set_PWM_dutycycle(2, 0)
elif(msg.note == 55):
pi1.set_PWM_dutycycle(3, 0)
elif(msg.note == 57):
pi1.set_PWM_dutycycle(4, 0)
except AttributeError as error:
print("Error excepted")
pass
I noticed there is some problems with pigpio daemon
After I have been downloading and installed from this page:
http://abyz.me.uk/rpi/pigpio/download.html
And then try to start the daemon with:
sudo pigpiod
I get this errormessage:
bind to port 8888 failed (Address already in use) Can't initialise
pigpio library
However I have also been running through with this in command line:
aplaymidi -p f_midi myMidiTune.mid
No errormessage but no midioutput to my digital piano ...
How can I debug this?

Maxim MAX14830 in Linux x86 / ACPI

I am receiving a fatal error when attempting to load the Maxim MAX14830 SPI-to-QuadUART chip in a CentOS8 (x86_64) environment. The SPI controller in use is the Intel E3900 Atom, from which I am able to successfully mount and interact with using SPIDEV.
After reviewing several examples from the ARM world, I believe the issue lies in that I am not passing the "clocks" parameter to the max310x driver, but I have been unable to find a suitable example for describing a "phandle to the IC source clock" in ACPI.
The chip's clock input (Pin 45, XIN) is driven by a standard clock oscillator running at 7.3728 MHz.
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-names", "osc"},
Package () {"clock-frequency", 7372800},
Package () {"reg", 0},
}
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "E3900-SPI1-CS1")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
1, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
The relevant output from dmesg is:
[ 1.974203] max310x spi-PRP0001:03: Cannot get clock
[ 1.975951] max310x: probe of spi-PRP0001:03 failed with error -22
The datasheet for the part can be found here: https://datasheets.maximintegrated.com/en/ds/MAX14830.pdf
Any guidance or relevant example link would be appreciated. Thanks!
EDIT: I found an example for how to reference another object at https://www.kernel.org/doc/html/latest/firmware-guide/acpi/dsd/leds.html; the following AML complied correctly, but resulted in a kernel panic. This discussion (https://lore.kernel.org/lkml/914341e7-ca94-054d-6127-522b745006b4#arm.com/T/) leads me to believe that use of the common clock framework is not supported in ACPI, so any drivers that make use of it cannot be used with a ACPI + _DSD configuration.
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPIDEV", 1)
{
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (CLK1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim Clock Object")
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "fixed-clock"},
Package () {"clock-cells", 0},
Package () {"clock-frequency", 7372800},
}
})
}
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
100000, // 100 kHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-names", "osc"},
Package () {"clocks", ^CLK1},
Package () {"reg", 0},
}
})
}
Device (TP11) {
Name (_HID, "SPT0001")
Name (_DDN, "E3900-SPI1-CS1")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
1, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // Don't care
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0 // Must be 0
)
})
}
}
}
With the driver updates provided by 0andriy (https://lore.kernel.org/linux-serial/20201007084635.594991-1-andy.shevchenko#gmail.com/T/#u), I was able to get the /dev/ttyMAX devices to appear, although I needed to perform further modifications to force oscillator clocking; the driver was still dropping to the "Cannot get clock" error.
I modeled my AML after this example (https://github.com/westeri/meta-acpi/blob/master/recipes-bsp/acpi-tables/samples/edison/sc16is7xx.asl), which resulted in the following:
DefinitionBlock ("e3900-spi.aml", "SSDT", 5, "INTEL", "SPI", 1)
{
External (_SB_.PCI0.XHC_.RHUB.HS06.GPIO, DeviceObj)
External (_SB_.PCI0.SPI1, DeviceObj)
Scope (\_SB.PCI0.SPI1)
{
Device (MAX1) {
Name (_HID, "PRP0001")
Name (_DDN, "Maxim MAX14380 Quad UART")
Name (_CRS, ResourceTemplate () {
SpiSerialBus (
0, // Chip select
PolarityLow, // Chip select is active low
FourWireMode, // Full duplex
8, // Bits per word is 8 (byte)
ControllerInitiated, // slave mode
1000000, // 1 MHz
ClockPolarityLow, // SPI mode 0
ClockPhaseFirst, // SPI mode 0
"\\_SB.PCI0.SPI1", // SPI host controller
0, // Must be 0
ResourceConsumer // Slave device
)
GpioInt (Level, ActiveLow, Exclusive, PullDefault, 0x0000,
"\\_SB.PCI0.XHC.RHUB.HS06.GPIO", 0x00, ResourceConsumer, , ) { 18 }
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", "maxim,max14830"},
Package () {"clock-frequency", 7372800},
}
})
}
}
}
However, the driver was still failing in the devm_request_threaded_irq function:
[ 15.951778] max310x spi-PRP0001:00: MAX14830 ID: 0xb4
[ 15.965699] max310x spi-PRP0001:00: Reference clock set to 7372800 Hz
[ 15.968883] spi-PRP0001:00: ttyMAX0 at I/O 0x0 (irq = -517, base_baud = 460800) is a MAX14830
[ 15.972907] spi-PRP0001:00: ttyMAX1 at I/O 0x20 (irq = -517, base_baud = 460800) is a MAX14830
[ 15.985941] spi-PRP0001:00: ttyMAX2 at I/O 0x40 (irq = -517, base_baud = 460800) is a MAX14830
[ 15.990046] spi-PRP0001:00: ttyMAX3 at I/O 0x60 (irq = -517, base_baud = 460800) is a MAX14830
[ 16.009260] max310x spi-PRP0001:00: Unable to reguest IRQ -517
[ 16.021810] max310x: probe of spi-PRP0001:00 failed with error -22
Being a novice at C code, I wasn't able to find a way to correct the issue and ended up just commenting it out so that the mounts were not automatically torn down.
At this point, I am able to successfully query them with the setserial utility and access the devices with minicom.
[root#hwtest ~]# setserial -g /dev/ttyMAX*
/dev/ttyMAX0, UART: undefined, Port: 0x0000, IRQ: -517, Flags: low_latency
/dev/ttyMAX1, UART: undefined, Port: 0x0020, IRQ: -517, Flags: low_latency
/dev/ttyMAX2, UART: undefined, Port: 0x0040, IRQ: -517, Flags: low_latency
/dev/ttyMAX3, UART: undefined, Port: 0x0060, IRQ: -517, Flags: low_latency
I am handing the PCB back to the EE to verify the serial ports are actually working (it does not have easy test points exposed), and I will update this answer if it doesn't.
EDIT: We are able to send data while configured in this manner, but the receive path is not working, likely due to the IRQ issue. I will retest with a 5.11 kernel and report back. The current status is with LTS kernel version 5.4.70, with manual patching of the max310x driver.

Setting device permission from driver code fails

I want to access I2C device driver nodes from user space in a linux kernel 3.10.14.
I added i2c-dev in the kernel configuration and got the /dev/i2c-* device nodes. However they have permission
$ ls -l /dev/i2c-*
crw------- root root 89, 1 2014-08-21 20:00 i2c-1
In drivers/i2c/i2c-dev.c I added the callback
static char *i2c_dev_devnode(struct device *dev, umode_t *mode)
{
if (!mode)
return NULL;
if (MAJOR(dev->devt) == I2C_MAJOR)
*mode = 0666;
return NULL;
}
and in the same file I added the callback to the device class struct:
static int __init i2c_dev_init(void)
{
...
i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
...
/* set access rights */
i2c_dev_class->devnode = i2c_dev_devnode;
...
}
However the access rights of the device node remain
crw------- root root 89, 1 2014-08-21 20:00 i2c-1
There is no /lib/udev/rules.d or /etc/udev/rules.d
I would appreciate any suggestions what might go wrong here.
I am also interested in ideas how to test this issue.
You might try the following. This works at least with kernel 4.9.56.
static int my_uevent(struct device *dev, struct kobj_uevent_env *env)
{
add_uevent_var(env, "DEVMODE=%#o", 0666);
return 0;
}
static int __init i2c_dev_init(void)
{
...
i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");
...
/* set access rights */
i2c_dev_class->dev_uevent = my_uevent;
...
}
I understand the return value of devnode callback function shall not be "NULL" but device node name.
So,
Change your functions return value from "NULL" to devname. Refer the code:
----------------------patch--------------------
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 6f638bb..35a42c6 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
## -614,6 +614,14 ## static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
.notifier_call = i2cdev_notifier_call,
};
+static char *i2c_dev_devnode(struct device *dev, umode_t *mode)
+{
+ printk("\n\n****%s: %d\n\n",__func__,__LINE__);
+ if (mode != NULL)
+ *mode = 0666;
+ return kasprintf(GFP_KERNEL, "i2cr/%s", dev_name(dev));;
+}
+
/* ------------------------------------------------------------------------- */
/*
## -636,7 +644,12 ## static int __init i2c_dev_init(void)
goto out_unreg_chrdev;
}
i2c_dev_class->dev_groups = i2c_groups;
+ /* set access rights */
+ printk(KERN_INFO "i2c setting devnode\n");
+ i2c_dev_class->devnode = i2c_dev_devnode;
+
+
/* Keep track of adapters which will be added or removed later */
res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
if (res)
Results:
Without applying this patch:
root#x86-generic-64:~# ls -l /dev/i2c-*
crw------- 1 root root 89, 0 Nov 1 13:47 /dev/i2c-0
crw------- 1 root root 89, 1 Nov 1 13:47 /dev/i2c-1
With patch:
root#x86-generic-64:~# ls -l /dev/i2cr/*
crw-rw-rw- 1 root root 89, 0 Nov 1 13:38 /dev/i2cr/i2c-0
crw-rw-rw- 1 root root 89, 1 Nov 1 13:38 /dev/i2cr/i2c-1
Setting up device node is responsibility of udev. So we need to use correct udev rule. Further init.rc approach will fail if driver is loaded after boot time for example in case it is a loadable module. Your distribution might be using another way of supporting hotplug so we need to consult documentation about that distro.

How to define platform_data in a Linux 3.8 device tree structure (DTS) file

I'm trying to get the at86rf230 kernel driver running on a BeagleBone Black to communicate with my radio. I have confirmed that I am able to interact with the device using some userspace SPI code. Here's the fragment of the DTS file I'm working with:
fragment#0 {
target = <&am33xx_pinmux>;
__overlay__ {
spi1_pins_s0: spi1_pins_s0 {
pinctrl-single,pins = <
0x040 0x37 /* DIG2 GPIO_9.15 I_PULLUP | MODE7-GPIO1_16 */
0x044 0x17 /* SLPTR GPIO_9.23 O_PULLUP | MODE7-GPIO1_17 */
0x1AC 0x17 /* RSTN GPIO_9.25 O_PULLUP | MODE7-GPIO3_21 */
0x1A4 0x37 /* IRQ GPIO_9.26 I_PULLUP | MODE7-GPIO3_19 */
0x190 0x33 /* SCLK mcasp0_aclkx.spi1_sclk, INPUT_PULLUP | MODE3 */
0x194 0x33 /* MISO mcasp0_fsx.spi1_d0, INPUT_PULLUP | MODE3 */
0x198 0x13 /* MOSI mcasp0_axr0.spi1_d1, OUTPUT_PULLUP | MODE3 */
0x19c 0x13 /* SCS0 mcasp0_ahclkr.spi1_cs0, OUTPUT_PULLUP | MODE3 */
>;
};
};
};
fragment#3 {
target = <&spi1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins_s0>;
at86rf230#0 {
spi-max-frequency = <1000000>;
reg = <0>;
compatible = "at86rf230";
interrupts = <19>;
interrupt-parent = <&gpio3>;
};
};
};
On loading the module I get the following error in dmesg:
[ 352.668833] at86rf230 spi1.0: no platform_data
[ 352.668945] at86rf230: probe of spi1.0 failed with error -22
I am trying to work out the right way to attach platform_data to the SPI overlay. Here's what I'd like to attach:
platform_data {
rstn = <&gpio3 21 0>;
slp_tr = <&gpio1 17 0>;
dig2 = <&gpio1 16 0>;
};
Unfortunately, just sticking it in as-is doesn't work so well when I use dtc to compile the DTS. I get the following error:
syntax error: properties must precede subnodes
FATAL ERROR: Unable to parse input tree
I feel that I'm ridiculously close to solving this, and I just need a little shove in the right direction ;)
First of all, the GPIO names in your excerpt are wrong. Accordingly to the latest code in linux-next there are
pdata->rstn = of_get_named_gpio(spi->dev.of_node, "reset-gpio", 0);
pdata->slp_tr = of_get_named_gpio(spi->dev.of_node, "sleep-gpio", 0);
There are only two of them.
Second, you have to adjust the DTS for your exact board. The entire DTS has to be considered as a platform data for all devices found on the board (some supported, some might be not). The section for the specific device should be described as device node.
So, the good start point is to check what is in upstream already exists, namely in arch/arm/boot/dts/am335x-boneblack.dts, don't forget to check included files as well.
And the example for this specific driver is in Documentation/devicetree/bindings/net/ieee802154/at86rf230.txt.