On 01/13/2012 08:15 PM, Manfred wrote:
> (In reply to Wolfgangs Respond)
>
> Thank you for the explanations.
> So I managed to recompile the kernel module with a lot of "printk"
>
> commands. And I could track the problem to the following:
> it fails in:[1]
> int __init rt_16550_init(void)
>
> When calling these lines:
> rt_16550_reg_out(mode, base, IER, 0);
> DEBUGPRINT("after reg_out IER \n");
> rt_16550_reg_in(mode, base, IIR);
> DEBUGPRINT("after reg_in IIR \n");
>
> So it seems to fail the first time when it tries to call:
> rt_16550_reg_in(mode, base, IIR);
> where
> mode=1
> rt_16550_reg_in is defined in:
> 16550A_io.h:161:
> static RT_16550_IO_INLINE u8
> rt_16550_reg_in(io_mode_t io_mode, unsigned long base, int off)
> {
> switch (io_mode) {
> case MODE_PIO:
> return inb(base + off);
> default: /* MODE_MMIO */
> return readb((void *)base + off);
> }
> }
>
> --> where is MODE_PIO defined?: is it 1 or 0?
> (could not find it in any .c or .h file)
Well, it's in :
http://www.rts.uni-hannover.de/xenomai/lxr/source/ksrc/drivers/serial/16550A_io.h
and depends on some Kconfig options. Also another prinkt can give you
the required information.
> So anyway, it either fails in inb(base+off)
> or (more probably:) in read(void*)base+off
Yes, most likely it's an unaligned access.
> -->
> Is this consistent with your assumption that we need a regshift?
Yes. I was suggesting to put some printks in the Linux serial device
setup code first to see how the registers are accessed.
> If yes, which function calls need to be fixed?
> -->
> I tried to look in 8250.c [2]:
> regshift seems to be mostly used when using map_8250_in_reg and
> map_8250_out_reg:
> offset = map_8250_in_reg(p, offset) << p->regshift;
> offset = map_8250_in_reg(p, offset) << p->regshift;
> but also elsewhere:
> 2498 static unsigned int serial8250_port_size(struct uart_8250_port *pt)
> 2499 {
> 2500 if (pt->port.iotype == UPIO_AU)
> 2501 return 0x1000;
> 2502 #ifdef CONFIG_ARCH_OMAP
> 2503 if (is_omap_port(pt))
> 2504 return 0x16 << pt->port.regshift;
> 2505 #endif
> 2506 return 8 << pt->port.regshift;
> 2507 }
> or:
> 2600 static void serial8250_release_rsa_resource(struct uart_8250_port *up)
> 2601 {
> 2602 unsigned long offset = UART_RSA_BASE << up->port.regshift;
> 2603 unsigned int size = 8 << up->port.regshift;
> 2604
> 2605 switch (up->port.iotype) {
> 2606 case UPIO_HUB6:
> 2607 case UPIO_PORT:
> 2608 release_region(up->port.iobase + offset, size);
> 2609 break;
> 2610 }
> 2611 }
This is the driver. The devices are setup and configured in
http://lxr.linux.no/#linux+v3.2.1/arch/arm/mach-omap2/serial.c
IIRC. Check what regshift is used for your hardware (by putting further
printk's).
> -->
> So can I just change the function in 16550A.c like this?:
> rt_16550_reg_in(io_mode_t io_mode, unsigned long base, int off, int
> regshift)
> {
> switch (io_mode) {
> case MODE_PIO:
> return inb(base + off);
> default: /* MODE_MMIO */
> /* ADD REGSHIFT for MMIO Mode: */
> unsigned long paddr=((void*)base+off)<< regshift;
> return readb((void *)base + off);
You need to shift just the *offset* at the beginning of the function:
off <<= regshift;
You also need to adjust the region for request_region() or ioremap().
> }
>
> Thanks for the help.
> Please note, this is really my first try on kernel modules and drivers,
> So sorry, in case I got it all wrong.
No problem, you are welcome.
Wolfgang.
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help