some questions on linux, RS485, omap_uart, omap8250

I have been trying to get RS485 support working on a BeagleBone Black Rev C equipped with Mikro Elektronika Click Shield and RS485 Click board.

The realities of that configuration mean I have to use GPIO0_22/P8.19 to control the RS485 transceiver that is connected to UART2. It took me a while to work out that the default serial driver didn’t support using GPIO pins as transmit indicators and that I needed to use the omap_uart driver (in the omap-serial module) instead since this driver does support such usage.

My initial attempts to do this were to load the overlay (BB-UART2-RS485 - of my own construction, based on BB-UART2 and BB-UART4-RS485), unbind the default driver that had bound itself to the device (omap8250), then bind the omap_uart driver to the device (I had to build and install a full kernel package with the omap-serial module to make this option available).

[ 225.635280] bone_capemgr bone_capemgr: part_number ‘BB-UART2-RS485’, version ‘N/A’

[ 225.635315] bone_capemgr bone_capemgr: slot #4: override
[ 225.635332] bone_capemgr bone_capemgr: Using override eeprom data at slot 4
[ 225.635348] bone_capemgr bone_capemgr: slot #4: ‘Override Board Name,00A0,Override Manuf,BB-UART2-RS485’
[ 225.650992] 48024000.serial: ttyS2 at MMIO 0x48024000 (irq = 187, base_baud = 3000000) is a 8250
[ 225.651555] bone_capemgr bone_capemgr: slot #4: dtbo ‘BB-UART2-RS485-00A0.dtbo’ loaded; overlay id #0
[ 284.743479] omap_uart 48024000.serial: no wakeirq for uart2
[ 284.744069] 48024000.serial: ttyO2 at MMIO 0x48024000 (irq = 187, base_baud = 3000000) is a OMAP UART2

The problem was, when I tried to do this, I got a stack dump from the kernel when I try to use the device. For example:

cat < /dev/ttyS2 > /dev/null

This happens:

[ 379.326951] Unhandled fault: external abort on non-linefetch (0x1028) at 0xfa024008

[ 379.334662] pgd = db2ac000
[ 379.337379] [fa024008] *pgd=48011452(bad)
[ 379.341423] Internal error: : 1028 [#1] SMP THUMB2
[ 379.346234] Modules linked in: snd_soc_hdmi_codec snd_soc_simple_card omap_aes_driver omap_sham snd_soc_davinci_mcasp snd_soc_edma omap_rng snd_soc_omap rng_core tilcdc snd_soc_core snd_pcm_dmaengine snd_pcm snd_timer snd soundcore evdev tda998x omap_serial uio_pdrv_genirq uio usb_f_ecm g_ether usb_f_rndis u_ether libcomposite
[ 379.375474] CPU: 0 PID: 2348 Comm: cat Not tainted 4.4.26-ti-r59 #1
[ 379.381766] Hardware name: Generic AM33XX (Flattened Device Tree)
[ 379.387883] task: db239a00 ti: db216000 task.ti: db216000
[ 379.393316] PC is at mem_serial_in+0xe/0x18
[ 379.397522] LR is at omap_8250_pm+0x29/0x90
[ 379.401722] pc : [] lr : [] psr: 00030033
sp : db217ef0 ip : 00000000 fp : da917a88
[ 379.413248] r10: 00000002 r9 : da917a80 r8 : dc33d234
[ 379.418492] r7 : dc33d260 r6 : 00000003 r5 : da995200 r4 : c0d23f74
[ 379.425044] r3 : 00000002 r2 : fa024000 r1 : 00000008 r0 : c0d23f74
[ 379.431598] Flags: nzcv IRQs on FIQs on Mode SVC_32 ISA Thumb Segment none
[ 379.438936] Control: 50c5387d Table: 9b2ac019 DAC: 00000051
[ 379.444704] Process cat (pid: 2348, stack limit = 0xdb216218)
[ 379.450472] Stack: (0xdb217ef0 to 0xdb218000)
[ 379.454848] 7ee0: dc33d1d0 da995200 c0d23f74 c0448ffb
[ 379.463063] 7f00: da995200 00000000 da9bf4d8 db505cd0 d90f55d8 c0433d6f 00000400 db254000
[ 379.471279] 7f20: c06e5fcf c01109ff 00000000 00000000 dc371780 da917a80 00000000 da9bf4d8
[ 379.479494] 7f40: db505cd0 d90f55d8 da9bf4d8 00000010 da917a88 c0130395 00000000 00000000
[ 379.487709] 7f60: 000001eb db239e84 c0c649ac db239a00 00000000 c000ea24 db216000 00000000
[ 379.495924] 7f80: 00020000 c0045443 da917a80 db216000 c000ea24 db217fb0 00000006 c00119af
[ 379.504139] 7fa0: b6e3c000 00020000 00000000 c000e8c7 00000000 00022000 00000001 00000001
[ 379.512353] 7fc0: b6e3c000 00020000 00000000 00000006 00000000 00000000 00000000 00020000
[ 379.520567] 7fe0: 00000000 bed0357c 00011aed b6ee8446 40030030 00000000 00000000 00000000
[ 379.528793] [] (mem_serial_in) from [] (omap_8250_pm+0x29/0x90)
[ 379.536488] [] (omap_8250_pm) from [] (uart_close+0xb7/0x1c4)
[ 379.544009] [] (uart_close) from [] (tty_release+0xa7/0x3c0)
[ 379.551445] [] (tty_release) from [] (__fput+0x6d/0x158)
[ 379.558530] [] (__fput) from [] (task_work_run+0x6f/0x94)
[ 379.565711] [] (task_work_run) from [] (do_work_pending+0x7f/0x80)
[ 379.573667] [] (do_work_pending) from [] (slow_work_pending+0x9/0x16)
[ 379.581883] Code: f890 304d 6882 4099 (5c50) b2c0
[ 379.586696] —[ end trace adcd747959f3ed22 ]—

Since I couldn’t work out why the crash was occurring, I decided to rebuild the kernel with omap_uart built in and omap8250 as a module.

I then got the results I expected, and the GPIO pin is driven high, when expected.

  • Was what I was trying to do originally (unbinding one driver I didn’t want and rebinding the one I wanted) unreasonable?

  • If not, is the stack trace above indicative of a bug in the omap8250 driver?

  • Is there a better way to arrange for a particular driver to be bound to a particular device?

  • in particular, Is there a way to prevent omap8250 from automatically binding to the 48024000.serial device when that device is created by the loading of the overlay?

jon.