If I have only one PCIe EP and only one function, Do I need “interrupt-map” function in device tree (DTS)? - linux

I’m using legacy PCIe Interrupt mechanism(Virtual INTx), As per my PCIe controller user guide, In legacy Interrupt mechanism Assert or Deassert Virtual INTx messages will be received from the EP device and according to that PCIe Core it will generate or clear interrupt signal respectively.
If I have only one EP and only one function, Do I need “interrupt-map” function in device tree (DTS)?
As per my understanding,
PCIe EP will send Assert_INTA message
PCIe RP decode this message and send Interrupt to Interrupt generating pin INTA_OUT
In design INTA_OUT is directly connected to Interrupt controller Input pin
In Linux kernel this IRQ will invoke PCIe RP ISR and also Endpoint functions ISR
Am I correct in my understanding ?
pci#0xfb000000 {
interrupts = <1 1>; //PCIe RP INTA  IRQ1, Only this info is enough ??
interrupt-parent = <&pic>;
/*Do we need follow info also ??? */
#interrupt-cells = <0x1>;
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
interrupt-map = < 0x0 0x0 0x0 0x1 &pcie_intc 0x1
0x0 0x0 0x0 0x2 &pcie_intc 0x2
0x0 0x0 0x0 0x3 &pcie_intc 0x3
0x0 0x0 0x0 0x4 &pcie_intc 0x4 >;
}

Related

Find port of RFID reader

I am using pyembedded in for a Python program using Ubuntu 22.04.
I am trying to get the ID that the RFID reader should provide when it reads a card. By using pyembedded I need to specify the port of the RFID using this line of code:
rfid = RFID(port='{USB}', baud_rate=9600)
I cannot find the actual USB port that is in use the RFID. Here is the udevadm info:
sudo udevadm info --query=all --name=/dev/input/event16
P: /devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:2518:6022.0003/input/input21/event16
N: input/event16
L: 0
S: input/by-id/usb-NSCCN_wCopy_Smart_Reader-event-if00
S: input/by-path/pci-0000:00:14.0-usb-0:2:1.0-event
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:2518:6022.0003/input/input21/event16
E: DEVNAME=/dev/input/event16
E: MAJOR=13
E: MINOR=80
E: SUBSYSTEM=input
E: USEC_INITIALIZED=1191291401
E: ID_INPUT=1
E: ID_VENDOR=NSCCN
E: ID_VENDOR_ENC=NSCCN
E: ID_VENDOR_ID=2518
E: ID_MODEL=wCopy_Smart_Reader
E: ID_MODEL_ENC=wCopy\x20Smart\x20Reader
E: ID_MODEL_ID=6022
E: ID_REVISION=0103
E: ID_SERIAL=NSCCN_wCopy_Smart_Reader
E: ID_TYPE=hid
E: ID_BUS=usb
E: ID_USB_INTERFACES=:030000:
E: ID_USB_INTERFACE_NUM=00
E: ID_USB_DRIVER=usbhid
E: ID_PATH=pci-0000:00:14.0-usb-0:2:1.0
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_2_1_0
E: LIBINPUT_DEVICE_GROUP=3/2518/6022:usb-0000:00:14.0-2
E: DEVLINKS=/dev/input/by-id/usb-NSCCN_wCopy_Smart_Reader-event-if00 /dev/input/by-path/pci-0000:00:14.0-usb-0:2:1.0-event
Is it specified here somewhere the path of the USB port in use and I cannot see it?
I also tried multiple ways so far, but none of the seemed to be working. I added also an udev rule containing the vendor and product ID of the RFID that looks like this:
SUBSYSTEM=="USB", ATTRS{idVendor}=="2518", ATTRS{idProduct}=="6022", MODE="0660", GROUP="plugdev"
Here is the full device info that I get using usb.core:
DEVICE ID 2518:6022 on Bus 001 Address 007 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x110 USB 1.1
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0x2518
idProduct : 0x6022
bcdDevice : 0x103 Device 1.03
iManufacturer : 0x1 NSCCN
iProduct : 0x2 wCopy Smart Reader
iSerialNumber : 0x3
bNumConfigurations : 0x1
CONFIGURATION 1: 400 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x29 (41 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0xc0 Self Powered
bMaxPower : 0xc8 (400 mA)
INTERFACE 0: Human Interface Device ====================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x2
bInterfaceClass : 0x3 Human Interface Device
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x0
ENDPOINT 0x81: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x1
ENDPOINT 0x2: Interrupt OUT ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x1
Also, when I am running:
rfid = RFID(port='/dev/bus/usb/001/009', baud_rate=9600)
I get:
serial.serialutil.SerialException: Could not configure port: (25, 'Inappropriate ioctl for device')
From where can I get the path of the port in use by this device?
From pyembedded website:
Note: Use port as ‘COM1’, ‘COM2’ etc in case of windows machine. Use port as ‘/dev/ttyUSB0’ in case of linux based devices:
I suppose you are taking /dev/bus/usb/001/009 from the lsusb command output. Check this question(https://askubuntu.com/questions/435861/what-is-the-difference-between-dev-tty-and-dev-bus-usb-001-002) to understand the difference between both paths.
I should use dmesg and connect/disconnect the device to see how Linux is managing the rfid reader. Then if the reader is being mapped to a tty you can use the path to call RFID(port, baud_rate)

u-boot hard fault error after ram initialization

I have ported U-boot on my Waveshare coreH7 stm32h743 board. I have used stm32h743-disco files and device trees as a template for porting. my onboard SDRAM is IS42S16400J that is 8MBytes. I have calculate the parameters of my sdram and I put them in my board device tree file as shown as below:
/*
* Memory configuration from sdram datasheet IS42S32800G-6BLI
* firsct bank is bank#0
* second bank is bank#1
*/
bank2: bank#1 {
st,sdram-control = /bits/ 8 <NO_COL_8
NO_ROW_12
MWIDTH_16
BANKS_4
CAS_3
SDCLK_2
RD_BURST_EN
RD_PIPE_DL_0>;
st,sdram-timing = /bits/ 8 <TMRD_1
TXSR_1
TRAS_1
TRC_6
TRP_2
TWR_1
TRCD_1>;
st,sdram-refcount = <300>;
};
also, I have been configured the rcc values to feed the dram with 100MHz.
but when uboot starts initialization, it goes to hard fault interrupt.
this is the log:
lib/fdtdec.c:fdtdec_setup_mem_size_base_fdt() fdtdec_setup_mem_size_base_fdt: Initial DRAM size 2000000
include/initcall.h:initcall_run_list() initcall: 08008a89
common/board_f.c:setup_dest_addr() Monitor len: 00039F80
common/board_f.c:setup_dest_addr() Ram size: 02000000
common/board_f.c:setup_dest_addr() Ram top: D2000000
include/initcall.h:initcall_run_list() initcall: 08008665
include/initcall.h:initcall_run_list() initcall: 0800117d
arch/arm/lib/cache.c:arm_reserve_mmu() TLB table from d1ff0000 to d1ff4000
include/initcall.h:initcall_run_list() initcall: 080088c3
include/initcall.h:initcall_run_list() initcall: 080088c7
include/initcall.h:initcall_run_list() initcall: 080086b1
common/board_f.c:reserve_uboot() Reserving 231k for U-Boot at: d1fb6000
include/initcall.h:initcall_run_list() initcall: 080088ed
common/board_f.c:reserve_malloc() Reserving 1032k for malloc() at: d1eb4000
include/initcall.h:initcall_run_list() initcall: 08008821
Hard fault
pc : 0800087e lr : 00000000 xPSR : 21000000
r12 : d1eb3ff0 r3 : 00000000 r2 : 00000010
r1 : 00000000 r0 : d1eb3fb0
Resetting CPU ...
what is the problem? is ram initialized unsuccessfully? why? maybe wrong parameters? how Can I know that ram is initialized successfully?
this is normal info log of u-boot:
U-Boot 2020.07-00610-g610e1487c8-dirty (Aug 04 2020 - 00:34:13 +0430)
Model: Waveshare STM32H743i-Coreh7 board
DRAM: Hard fault
pc : 0800087e lr : 00000000 xPSR : 21000000
r12 : d1eb3ff0 r3 : 00000000 r2 : 00000010
r1 : 00000000 r0 : d1eb3fb0
Resetting CPU ...
your ram size is wrong. as you mentioned, the actual ram size is 8MB that is 0x7A1200 in hexadecimal number. but in U-boot log is "Initial DRAM size 2000000". you should change it in the device tree of your board.
memory {
device_type = "memory";
reg = <0xd0000000 0x7A1200>;
};

Read the bar- QR-code with a scanner on windows 10 system

I have connected a bar- / qr-code scanner to my windows 10 pc via usb.
The scanner is registered on the system.
Now I want to write a python app to read bar- and qr-codes with the scanner.
Yet I am not able to read codes, I get an object as a result.
What I have to do, whta is going wrong???
To access the complete parameter from the scanner is possible.
#importing modules
import usb
import usb.core
import usb.util
import usb.backend.libusb1
#device vid / pid
VID = 0x2010
PID = 0x7638
#access the device registry
backend = usb.backend.libusb1.get_backend(find_library=lambda X: "C:\ProgramData\Anaconda3\libusb\amd64")
#some tries to get parameters / informations about the device
usb_error = usb.USBError('USB-Error', error_code='error', errno=None)
dev = usb.core.find(idVendor=VID, idProduct=PID)
dev.set_configuration()
if not dev:
raise ValueError ("USB device not found")
exit(1)
config = dev.configurations
cfg = dev.get_active_configuration()
intf = cfg[(0,0)]
ep = usb.util.find_descriptor(
intf,
custom_match = lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)
ep_adr = ep.bEndpointAddress
dev.backend.open_device
adress = dev.address
manufaktur = dev.manufacturer
conf2 = dev.bNumConfigurations
dev_descriptor = dev.bDescriptorType
ser_num = dev.serial_number
busses = usb.busses()
for bus in busses:
devices = bus.devices
for dev in devices:
print ("Device:", dev.filename)
print (" idVendor: %d (0x%04x)" % (dev.idVendor, dev.idVendor))
print (" idProduct: %d (0x%04x)" % (dev.idProduct, dev.idProduct))
print('cfg: ', str(cfg))
print('Manufacturer: ', str(manufaktur))
print('Serial Number', str(ser_num))
print('EP: ', ep)
print('Descriptor: ', dev_descriptor)
the actual result:
Device:
idVendor: 8208 (0x2010)
idProduct: 30264 (0x7638)
cfg: CONFIGURATION 1: 400 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x22 (34 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0x80 Bus Powered
bMaxPower : 0xc8 (400 mA)
INTERFACE 0: Human Interface Device ====================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x1
bInterfaceClass : 0x3 Human Interface Device
bInterfaceSubClass : 0x1
bInterfaceProtocol : 0x1
iInterface : 0x0
ENDPOINT 0x83: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x83 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x8 (8 bytes)
bInterval : 0x1
Manufacturer: USBKey Chip
Serial Number 202730041341
EP: ENDPOINT 0x83: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x83 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x8 (8 bytes)
bInterval : 0x1
Descriptor: 1
The object you get must be a string with the resulting scan output. Try scanning to a console...
The scanner you have is emulating only a USB keyboard as OUTPUT.
All the SW inside the scanner produces is a string of bytes as a result of the scanned image.
What you are trying to do is use libusb to talk the the USB hw directly, which will only get you an emulated HID keyboard.
If you want to hack down, you need to jtag the scanner board or scan config images to trigger configuration changes on the device.
my Barcode scanner connected via USB is acting like standard input device (like Keyboard) in Windows 10. When barcode is scanned on opened text file in Notepad, the scanned digits appears in text file, like typing on Keyboard.
Hence for reading into Python39 shell or file in Windows 10, used the python code 'input("scan Barcode: ")' and scanned. I got scanned digits from scanner device.
C:\Project\Python39>python
Python 3.9.0 (tags/v3.9.0:9cf6752, Oct 5 2020, 15:34:40) [MSC v.1927 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>>
>>> input("scan Barcode: ")
scan Barcode: 88H-1010UB-0TV
'88H-1010UB-0TV'
>>>
>>> myBarCodeId = input("Scan barCode please ...")
Scan barCode please ...TARNLK002563
>>>
>>> print(myBarCodeId)
TARNLK002563
>>>
>>> mibar=input("scan me please \n")
scan me please
88H-1010UB-0TV
>>>
>>> print(mibar)
88H-1010UB-0TV
>>>

Not able to transfer data through libusb

I am trying to run this program for sending data using libusb. I am not able to find the endpoint of my USB port. This parameter is required in the libusb_bulk_transfer function.
#include <iostream>
#include <libusb.h>
using namespace std;
int main() {
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_device_handle *dev_handle; //a device handle
libusb_context *ctx = NULL; //a libusb session
int r; //for return values
ssize_t cnt; //holding number of devices in list
r = libusb_init(&ctx); //initialize the library for the session we just declared
if(r < 0) {
cout<<"Init Error "<<r<<endl; //there was an error
return 1;
}
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
cout<<"Get Device Error"<<endl; //there was an error
return 1;
}
cout<<cnt<<" Devices in list."<<endl;
dev_handle = libusb_open_device_with_vid_pid(ctx, 5118, 7424); //these are vendorID and productID I found for my usb device
if(dev_handle == NULL)
cout<<"Cannot open device"<<endl;
else
cout<<"Device Opened"<<endl;
libusb_free_device_list(devs, 1); //free the list, unref the devices in it
unsigned char *data = new unsigned char[4]; //data to write
data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values
int actual; //used to find out how many bytes were written
if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached
cout<<"Kernel Driver Active"<<endl;
if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
cout<<"Kernel Driver Detached!"<<endl;
}
r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1)
if(r < 0) {
cout<<"Cannot Claim Interface"<<endl;
return 1;
}
cout<<"Claimed Interface"<<endl;
cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to write : abcd
cout<<"Writing Data..."<<endl;
r = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), data, 4, &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
if(r == 0 && actual == 4) //we wrote the 4 bytes successfully
cout<<"Writing Successful!"<<endl;
else
cout<<"Write Error"<<endl;
r = libusb_release_interface(dev_handle, 0); //release the claimed interface
if(r!=0) {
cout<<"Cannot Release Interface"<<endl;
return 1;
}
cout<<"Released Interface"<<endl;
libusb_close(dev_handle); //close the device we opened
libusb_exit(ctx); //needs to be called to end the
delete[] data; //delete the allocated memory for data
return 0;
}
The following is the program on my host PC to receive the data.
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{
read_port();
//return 0;
}
read_port(void)
{
int fd = open("/dev/ttyACM0", O_RDONLY | O_NOCTTY);
if (fd == -1)
{
/* Could not open the port. */
perror("open_port: Unable to open /dev/ttyACM0) - ");
}
char buffer[32];
for(;;)
{
int n = read(fd, buffer, sizeof(buffer));
if (n < 0)
fputs("read failed!\n", stderr);
printf("\n %d", n);
}
}
Please help.
Thanks in advance.
In answer to your actual question, if you want to find out what actual endpoints are attached the device, lsusb is your friend
If you are unsure what your device's vendor and device ID are, type:
lsusb
and you will get something like this:
Bus 001 Device 005: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse
Bus 001 Device 015: ID 413c:2003 Dell Computer Corp. Keyboard
Bus 001 Device 020: ID 0483:3748 STMicroelectronics ST-LINK/V2
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Let's say we want to know what endpoints are present on the ST-LINK/V2, we use lsusb in verbose mode using the -v option, and specify only the device we're interested in with the -d option with the ID:
lsusb -v -d 0483:3748
We will get a big list of fields from this. The topology is roughly:
device->configuration->interface->endpoints
| interface->endpoints
| interface->endpoints
|
->configuration->interface->endpoints
interface->endpoints
...
So locate the interface you want to use (often 0):
locate the interface descriptor
encapsulated inside this you can see the endpoint descriptors
then look for the term bEndpointAddress to get the actual value
In this case we have a bulk in endpoint with an address of 0x81:
bEndpointAddress 0x81 EP 1 IN
And another a little further down:
bEndpointAddress 0x02 EP 2 OUT
And another in endpoint:
bEndpointAddress 0x83 EP 3 IN
For completeness here is the full dump:
Bus 001 Device 020: ID 0483:3748 STMicroelectronics ST-LINK/V2
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x0483 STMicroelectronics
idProduct 0x3748 ST-LINK/V2
bcdDevice 1.00
iManufacturer 1 STMicroelectronics
iProduct 2 STM32 STLink
iSerial 3 000000000001
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 39
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 4 ST Link
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN *!eg end point address!*
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Device Status: 0x0000
(Bus Powered)

Accessing external bus in kernel space on an ARM based board

I'm trying to write an LCD display driver on an ARM based board.
The LCD controller is plugged on the external memory bus.
So I try to convert the physical address of registers of the controller to the virtual one.
I use the following pieces of code to do that :
#define AT91_VA_BASE_CS2 phys_to_virt(0x50000000)
static inline unsigned char at91_CS2_read(unsigned int reg)
{
void __iomem *CS2_base = (void __iomem *)AT91_VA_BASE_CS2;
return __raw_readb(CS2_base + reg);
}
static inline void at91_CS2_write(unsigned int reg, unsigned char value)
{
void __iomem *CS2_base = (void __iomem *)AT91_VA_BASE_CS2;
__raw_writeb(value, CS2_base + reg);
}
void write_lcd_port (int mode, unsigned char cmd_dat)
{
while ((read_lcd_port() & 0x03) != 0x03) {
/* wait while LCD is busy!!! */
} /* endwhile */
/* Send Command */
if (mode == 1)
{
at91_CS2_write(4, cmd_dat);
}
/* Send Data */
if (mode == 0)
{
at91_CS2_write(0, cmd_dat);
}
}
I get the following message :
Unable to handle kernel paging request at virtual address 4f000004
pgd = c39bc000
[4f000004] *pgd=00000000
Internal error: Oops: 5 [#1]
Modules linked in: module_complet dm9000 at91_wdt vfat fat jffs2 nls_iso8859_1 nls_cp437 nls_base usb_storage sd_mod sg scsie
CPU: 0
PC is at read_lcd_port+0x1c/0x38 [module_complet]
LR is at 0x1
pc : [<bf0a21b8>] lr : [<00000001>] Tainted: P
sp : c380bf1c ip : 60000093 fp : c380bf2c
r10: 0003a804 r9 : c380a000 r8 : c001de64
r7 : 00000000 r6 : fefff000 r5 : 0000009c r4 : 00000001
r3 : 4f000000 r2 : 00000000 r1 : 00001438 r0 : bf0a25cc
Flags: nZCv IRQs on FIQs on Mode SVC_32 Segment user
Control: C000717F Table: 239BC000 DAC: 00000015
Process insmod (pid: 903, stack limit = 0xc380a198)
Stack: (0xc380bf1c to 0xc380c000)
bf00: 00000001
bf20: c380bf44 c380bf30 bf0a21f4 bf0a21ac 00000000 fefa0000 c380bf54 c380bf48
bf40: bf0a2288 bf0a21e4 c380bf64 c380bf58 bf0a246c bf0a2280 c380bf84 c380bf68
bf60: bf0a4058 bf0a2464 40017000 c01c89a0 bf0a2d80 c01c8990 c380bfa4 c380bf88
bf80: c004cd20 bf0a4010 00000003 00000000 0000000c 00000080 00000000 c380bfa8
bfa0: c001dcc0 c004cbc8 00000000 0000000c 00900080 40017000 0000162e 00041050
bfc0: 00000003 00000000 0000000c bea0fde4 bea0fec4 00000002 0003a804 00000000
bfe0: bea0fd10 bea0fd04 0001b290 400d1d20 60000010 00900080 20002031 20002431
Backtrace:
[<bf0a219c>] (read_lcd_port+0x0/0x38 [module_complet]) from [<bf0a21f4>] (write_lcd_port+0x20/0x80 [module_complet])
r4 = 00000001
[<bf0a21d4>] (write_lcd_port+0x0/0x80 [module_complet]) from [<bf0a2288>] (wr_cmd+0x18/0x1c [module_complet])
r5 = FEFA0000 r4 = 00000000
[<bf0a2270>] (wr_cmd+0x0/0x1c [module_complet]) from [<bf0a246c>] (lcd_init+0x18/0x80 [module_complet])
[<bf0a2454>] (lcd_init+0x0/0x80 [module_complet]) from [<bf0a4058>] (mon_module_init+0x58/0xcc [module_complet])
[<bf0a4000>] (mon_module_init+0x0/0xcc [module_complet]) from [<c004cd20>] (sys_init_module+0x168/0x2c8)
r6 = C01C8990 r5 = BF0A2D80 r4 = C01C89A0
[<c004cbb8>] (sys_init_module+0x0/0x2c8) from [<c001dcc0>] (ret_fast_syscall+0x0/0x2c)
r7 = 00000080 r6 = 0000000C r5 = 00000000 r4 = 00000003
Code: e59f001c eb3e43c2 e3a0344f e59f0014 (e5d34004)
Segmentation fault
Note that this method works for internal peripherals (such as timers).
So in some cases, phys_to_virt works.
I think that no page is allocated at the address 0x50000000. How can I allocate a page at this specific address ?
I found functions like kmap but it seems to be very complicated and I don't know how to use it.
The best way to access memory-mapped peripherals is with the kernel's ioremap and friends.
First, declare that you want to use a specific region of memory for your peripheral:
struct resource *res = request_mem_region(0x50000000, region_size, "at91");
When you unload your driver, you will want to free that memory region.
release_mem_region(0x50000000, region_size);
Now, you can remap the I/O region before use.
void *ptr = ioremap(0x50000000, region_size);
If you want to prevent caching of these registers, use ioremap_nocache instead. You can also only remap a subregion of your device's memory space if you're only using that part.
Now that you have the iomapped region, you can do I/O on that memory.
iowrite8(value, (char *)ptr + reg);
unsigned int val = ioread8((char *)ptr + reg);
Once you're done reading from and writing to that region of memory, you can unmap it.
iounmap(ptr);
I hope this helps. I would recommend reading (or at least using as a reference) Linux Device Drivers, 3rd Edition, which can be read online for free.

Resources