Re: startup/request_port functions not being called

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 05/05/2016 12:30 PM, Greg KH wrote:
> On Thu, May 05, 2016 at 06:23:12PM +0000, Andy Falanga (afalanga) wrote:
>> I'm writing my first serial driver for a UART (AXI UART Lite from
>> Xilinx).  Yes, I know there's one in the kernel but the hardware in this
>> case isn't embedded.
>>
>> Using the documentation in <kernel_src>/Documentation/serial/driver and
>> the existing code for references, I've implemented my driver.  However,
>> I cannot validate the my startup or request_port functions are being
>> called.
>>
>> I'm calling uart_register_driver() and then uart_register_port() and I'm
>> sure these functions are passing.  I'm seeing my device handles show in
>> /dev.  The documentation states that the startup() function, "... will
>> only be called when the port is initially opened."  Yet, I'm not seeing
>> pr_info() messages that I should be.  What should I look for in order to
>> determine why the setup functions aren't being called?
> Are you sure that some other driver isn't being called instead of yours?
>
> Without seeing the code, it's impossible to debug, please just send a
> patch.
>
>
Hi Greg,

I had to jump through some hoops in order to send the code.  Here's what 
I've got for driver registration/initialization.

     #define MAX_SUPPORTED_UARTS 1
     #define DRIVER_MAJOR_NUM  243  /* local/experimental */
     #define DRIVER_MINOR_NUM  0

     static int request_port(struct uart_port *);
     static void release_port(struct uart_port *);
     static int startup(struct uart_port *);
     static void shutdown(struct uart_port *);

     static struct uart_ops axilite_ops = {
         .release_port = release_port,
         .request_port = request_port,
         .startup = startup,
         .shutdown = shutdown,
     };

     static struct uart_port axilite_ports[MAX_SUPPORTED_UARTS] = {
         {
             .mapbase = 0, /* determined during discovery */
             .membase = 0, /* calcuated after learning mapbase */
             .iotype = UPIO_MEM, /* from serial_core.c */
             .irq = 0,  /* currently, device doesn't use an IRQ, just 
polling */
             .fifosize = 16,  /* directly Xilinx documentation */
             .ops = &axilite_ops,
             .flags = UPF_FIXED_TYPE | UPF_FIXED_PORT | UPF_SPD_VHI,
             .mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR, /* from 
uartlite.c in kernel tree */
         },
     };

     static struct uart_driver axilite_driver = {
         .owner = THIS_MODULE,
         .driver_name = "axilite",
         .dev_name = "ttyAUL",
         .major = DRIVER_MAJOR_NUM,
         .minor = DRIVER_MINOR_NUM,
         .nr = MAX_SUPPORTED_UARTS,
     };

     static int startup(struct uart_port *pup)
     {
         void __iomem* pmem = pup->membase;
         uint32_t ctlreg = 0;
         pr_info("%s:%d entry point\n", __func__, __LINE__);

         ctlreg = ioread32(CTL_REG_ADDR(pmem));
         pr_info("DEBUG: %s:%d CTL Reg is 0x%08x\n",
                 __func__, __LINE__, ctlreg);
         /* clear the FIFO's */
         ctlreg |= CTL_REG_RST_TX | CTL_REG_RST_RX;
         iowrite32(ctlreg, CTL_REG_ADDR(pmem));

         return 0;
     }

     static void shutdown(struct uart_port *pup)
     {
         void __iomem* pmem = pup->membase;

         pr_info("%s:%d entry point\n", __func__, __LINE__);

         /* Using a queue from the axilite driver in the kernel */
         iowrite32(0, CTL_REG_ADDR(pmem));
     }

     static void release_port(struct uart_port *pup)
     {
         pr_info("%s:%d entry point\n", __func__, __LINE__);

         if (pup->membase)
             iounmap(pup->membase);

         pup->membase = NULL;
     }

     static int request_port(struct uart_port *pup)
     {
         int result = 0;
         uint32_t bus_addr = pup->mapbase;
         void __iomem* pmem = NULL;

         pr_info("%s:%d mapping bus addr to virtual space\n",
                 __func__, __LINE__);
         pmem = ioremap_nocache(bus_addr, UART_REGISTER_REGION);
         if (IS_ERR_OR_NULL(pmem)) {
             pr_err("%s:%d ioremap_nocache failed\n",
                     __func__, __LINE__);
             result = PTR_ERR(pmem);
             goto startup_exit;
         }

         pup->membase = pmem;
         pr_info("%s:%d busaddr 0x%08x mapped to %p\n",
                 __func__, __LINE__, bus_addr, pmem);

     startup_exit:
         return result;
     }

     static int add_uart_ports(void)
     {
         int result = 0;
         uint32_t i = 0, baseaddr = 0;

         pr_info("%s:%d adding %d port(s) to the system\n",
                 __func__, __LINE__, uart_count);

         /* calls into code which learns the base address,
          * verified that it works
          */
         baseaddr = get_uart_base(i);

         if ((int)baseaddr == -EINVAL) {
             pr_err("%s:%d Invalid index used\n", __func__, __LINE__);
             result = (int)baseaddr;
             goto add_ports_exit;
         }
         else if (0 == baseaddr) {
             pr_err("%s:%d Invalid bus address encountered, port add 
stopped\n",
                     __func__, __LINE__);
             result = -ENODEV;
             goto add_ports_exit;
         }
         else
             axilite_port[i].mapbase = baseaddr;

         result = uart_add_one_port(&axilite_driver, &axilite_port[i]);
         if (result) {
             pr_err("%s:%d uart_add_one_port failed for port %d\n",
                     __func__, __LINE__, i);
             goto add_ports_exit;
         }

         /* TODO think of a better way to track whether the port
          * is registered.  this will work for now.
          */
         axilite_port[i].private_data = &uart_count;

         init_stage |= UART_PORT_REGISTERED;

     add_ports_exit:

         return result;
     }

     static int add_uart_driver(void)
     {
         int result = 0;
         pr_info("%s:%d adding the driver\n", __func__, __LINE__);

         uart_count = get_uart_count();
         axilite_driver.nr = (int)uart_count;

         result = uart_register_driver(&axilite_driver);
         if (result) {
             pr_err("%s:%d uart_register_driver failed\n",
                     __func__, __LINE__);
             goto add_driver_exit;
         }

         init_stage |= DRIVER_REGISTERED;

     add_driver_exit:
         return result;
     }
--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux