imx uart address in Linux

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

imx uart address in Linux

Jump to solution
2,882 Views
a_r_f_
Contributor II

Hi,

I'm trying to use i.MX6UL with Linux 4.12.4 in a device with RS485 bus handled by serial port UART5. I have a problem that no matter what I try to do, if I leave control to the SERIAL_IMX driver, the RTS signal, which is used as driver enable, gets high on boot and stays like that forever. The correct behaviour would be that this signal stays low on boot and goes high only for transmission.

I've added a number of printk's to drivers/tty/serial/imx.c to track when the driver tries to change the state of the signal, and also what values it tries to write to UCR2 register, and eventually - where does it expect the register to be located.

The observation is, that the struct uart_port type variable describing the port has rs485.flags = 0x3, which looks correct. Also, driver calls functions intended for setting or clearing the signal correctly, and it produces correct value of UCR2, equal to 0x4027 or 0x5027, for setting and clearing the signal, respectively.

But, what I don't understand and I am unable to find any relation to the hardware, is that the driver thinks the serial port is located at address 0xe0964000, while the true physical address of the UART5 peripheral is 0x021f4000. Is this a virtual address of the peripheral? Do peripherals have a virtual address at all? To me it would make no sense.

Please, could someone explain to me why this reported address is correct, if it is, or otherwise help me track where does this come from? I didn't find the place where uart_port.membase gets assigned its value.

Best regards,
Adam

Labels (3)
0 Kudos
Reply
1 Solution
2,225 Views
igorpadykov
NXP Employee
NXP Employee

Hi Adam

yes virtual address is used, for example one can look at

#define MX6Q_IO_ADDRESS(x)              IOMEM(MX6Q_IO_P2V(x))

in linux/arch/arm/mach-imx/mx6.h

mx6.h\mach-imx\arm\arch - linux-imx - i.MX Linux kernel 

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

0 Kudos
Reply
4 Replies
2,226 Views
igorpadykov
NXP Employee
NXP Employee

Hi Adam

yes virtual address is used, for example one can look at

#define MX6Q_IO_ADDRESS(x)              IOMEM(MX6Q_IO_P2V(x))

in linux/arch/arm/mach-imx/mx6.h

mx6.h\mach-imx\arm\arch - linux-imx - i.MX Linux kernel 

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply
2,225 Views
a_r_f_
Contributor II

I've checked that it is possible to toggle CTS_B signal from barebox, by using command mw.

It is sufficient to:

- mux GPIO1_IO09 pin to UART5_CTS_B, by writing 8 to 0x020e0080 (pad ctrl reg. if I'm not messing up the name),

- enable UART5, by writing 1 to 0x021f4080.

Then writing to 0x021f4084 sets the CTS_B signal, eg. 0x5023 clears it, and 0x4023 sets it.

When I've left CTS_B low and booted Linux, the signal kept this state until I've sent something to /dev/ttymxc4, afterwards it remained high.

I've tried to do the same toggling from Linux using devmem2, but it was not possible.

The pad was correctly muxed:

# devmem2 0x020e0080 w
/dev/mem opened.
Memory mapped at address 0xb6f9b000.
Read at address  0x020E0080 (0xb6f9b080): 0x00000008

UCR2 looked like after reset, although it should have been already initialized by system on boot:

# devmem2 0x021f4084 w          
/dev/mem opened.
Memory mapped at address 0xb6fbd000.
Read at address  0x021F4084 (0xb6fbd084): 0x00000001

I've tried to toggle CTS_B, but no success. I've noticed, that the memory has been mapped at different address each time, also different than for reading. Maybe that's due to some temporary assignment? Still, the second write has shown no signs of the previous write access, by displaying read value 1.

# devmem2 0x021f4084 w 0x5023
/dev/mem opened.
Memory mapped at address 0xb6fd7000.
Read at address  0x021F4084 (0xb6fd7084): 0x00000001
Write at address 0x021F4084 (0xb6fd7084): 0x00005023, readback 0x00005023

# devmem2 0x021f4084 w 0x4023
/dev/mem opened.
Memory mapped at address 0xb6f98000.
Read at address  0x021F4084 (0xb6f98084): 0x00000001
Write at address 0x021F4084 (0xb6f98084): 0x00004023, readback 0x00004023

devmem2 has shown 0 in UCR1, so I tried to write 1 to enable UART, but no luck either.

The mapped address displayed by devmem2 was different from what my printk's have shown previously, so I checked what happens for accessing that address. It resulted in a crash:

# devmem2 0xe0964084  w         
/dev/mem opened.[  200.606411] Unable to handle kernel paging request at virtual address bf013be4
[  200.614376] pgd = d95ac000
[  200.617122] [bf013be4] *pgd=00000000
[  200.620766] Internal error: Oops: 80000005 [#1] SMP ARM
[  200.626023] Modules linked in:
[  200.629149] CPU: 0 PID: 207 Comm: devmem2 Not tainted 4.14.39-BSP-Yocto-phyBOARD-Segin-PD17.2.0+ #7
[  200.638234] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[  200.644456] task: db6adcc0 task.stack: da8a0000
[  200.649027] PC is at 0xbf013be4
[  200.652228] LR is at force_sig_info+0xd8/0xf0
[  200.656627] pc : [<bf013be4>]    lr : [<c01325e0>]    psr: 60070193
[  200.662931] sp : da8a1e08  ip : 00000000  fp : da8a1e2c
[  200.668195] r10: bee0cbf8  r9 : b6fb5084  r8 : 00000037
[  200.673461] r7 : da8a1e30  r6 : 0000080d  r5 : 0000000b  r4 : db6adcc0
[  200.680029] r3 : 00000000  r2 : db6a06c0  r1 : 00000000  r0 : 00000000
[  200.686602] Flags: nZCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  200.693866] Control: 10c5387d  Table: 995ac06a  DAC: 00000051
[  200.699653] Process devmem2 (pid: 207, stack limit = 0xda8a0210)
[  200.705698] Stack: (0xda8a1e08 to 0xda8a2000)
[  200.710113] 1e00:                   00000001 e1a01006 0000080d daf8a000 da8a1fb0 b6fb5084
[  200.718351] 1e20: da8a1ec4 da8a1e30 c0115788 c0132514 0000000b 00000000 00000001 e1a01006
[  200.726588] 1e40: 00000000 da885600 0161d02d 00000025 da8a0000 00000025 da8a1e7c da8a1e68
[  200.734824] 1e60: c015b674 c015b5b0 00000004 00000000 da8a1e94 da8a1e80 da8a1e94 da8a1e88
[  200.743062] 1e80: c0481e54 c048429c da8a1edc da8a1e98 c047a4fc c0481e48 da9a5200 c047e004
[  200.751299] 1ea0: da8fe0c0 00000051 da87b400 00000025 b6fb5000 da8a1fb0 da8a1eec da8a1ec8
[  200.759535] 1ec0: c0115ca4 c0115744 00000001 da8a1fb0 c0e091d4 0000080d c0115cc0 e1a01006
[  200.767772] 1ee0: da8a1efc da8a1ef0 c0115cd0 c0115c3c da8a1fac da8a1f00 c0101328 c0115ccc
[  200.776006] 1f00: 00000002 da9a0780 00000000 00000000 00000000 00000000 da8a1f74 da8a1f28
[  200.784242] 1f20: c01d8718 00000025 da8fe0c0 00000002 00000000 db6d2030 da8fe0c8 00000000
[  200.792479] 1f40: da8a1f7c da8a1f50 c020b204 c024b36c 00000000 00000000 da8fe0c0 da8fe0c0
[  200.800717] 1f60: 0161d008 00000025 c0108044 da8a0000 da8a1fa4 da8a1f80 c020b360 c020b0d0
[  200.808955] 1f80: 00000000 00000000 00000025 00010400 60070010 ffffffff 10c5387d 10c5387d
[  200.817191] 1fa0: 00000000 da8a1fb0 c010d408 c01012f8 b6f85d60 00010c94 00000008 e1a01006
[  200.825430] 1fc0: 00020e7c b6fb5000 b6f75758 5108a9ae 00000003 b6fb5084 bee0cbf8 bee0cdf4
[  200.833667] 1fe0: 00020600 bee0cbe8 00010608 00010400 60070010 ffffffff 00000000 00000000
[  200.841871] Backtrace:
[  200.844405] [<c0132508>] (force_sig_info) from [<c0115788>] (__do_user_fault+0x50/0x58)
[  200.852481]  r9:b6fb5084 r8:da8a1fb0 r7:daf8a000 r6:0000080d r5:e1a01006 r4:00000001
[  200.860291] [<c0115738>] (__do_user_fault) from [<c0115ca4>] (do_bad_area+0x74/0x90)
[  200.868072]  r4:da8a1fb0
[  200.870663] [<c0115c30>] (do_bad_area) from [<c0115cd0>] (do_sect_fault+0x10/0x18)
[  200.878285]  r7:e1a01006 r6:c0115cc0 r5:0000080d r4:c0e091d4
[  200.884007] [<c0115cc0>] (do_sect_fault) from [<c0101328>] (do_DataAbort+0x3c/0xbc)
[  200.891729] [<c01012ec>] (do_DataAbort) from [<c010d408>] (__dabt_usr+0x48/0x60)
[  200.899163] Exception stack(0xda8a1fb0 to 0xda8a1ff8)
[  200.904263] 1fa0:                                     b6f85d60 00010c94 00000008 e1a01006
[  200.912499] 1fc0: 00020e7c b6fb5000 b6f75758 5108a9ae 00000003 b6fb5084 bee0cbf8 bee0cdf4
[  200.920730] 1fe0: 00020600 bee0cbe8 00010608 00010400 60070010 ffffffff
[  200.927400]  r8:10c5387d r7:10c5387d r6:ffffffff r5:60070010 r4:00010400
[  200.934143] Code: bad PC value
[  200.937246] ---[ end trace e0ede72db580c3d2 ]---

I would appreciate any hint on what is going on here.

Best regards,
Adam

0 Kudos
Reply
2,225 Views
a_r_f_
Contributor II

I've found the spot where the remapped base address is assigned. Looking into the source I would guess that the address will start with 0xf4 but this one starting with 0xe0 just has to be correct, because there is some activity on TX line of the port when sending something from the system. Still, CTS bit of UCR2 seems to be useless.

Best regards,
Adam

0 Kudos
Reply
2,225 Views
a_r_f_
Contributor II

After some more debugging, it seems to me that, at least with kernel 4.14.39, CTS bit from UCR2 is ignored when not transmitting, because UART gets disabled (by setting UCR1 to 0).

0 Kudos
Reply