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
Xenomai-help@gna.org
https://mail.gna.org/listinfo/xenomai-help

Reply via email to