This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

GPIO Driver inserting problem in the Kernel

Other Parts Discussed in Thread: TMS320DM355

Dear sir,

                    I am using TMS320DM355 processor based IPNC camera and also i am having montavista 4.0.1 tool chain with dvsdk 1.20 i tried to write a gpio driver and i taken from the ti forum i tried to compiled it.It is running but after generation of  .ko file it is not inserting in the board kernel.It showing some error.

The error is

unknown symbol

1.gpio_free
2.gpio_direction_output
3.gpio_direction_input
4.gpio_get_value
5.gpio_set_value
6.gpio_request

And the driver code is

/******************************************************************************
 * This files declares the ioctl's that can be used to read/write GPIO pins
 * from the user application.  
 *
 * Original Author: Brijesh Singh, Texas Instruments Inc
 ******************************************************************************/
 
/* Include linux kernel header files */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <asm/arch/hardware.h>
#include <asm/gpio.h>
 
/* Include local header file */
#include "user_gpio.h"
 
MODULE_LICENSE("GPL");  
 
/* declare location variables */
static dev_t dev;   
static struct cdev *user_gpio_cdev;
 
/* declare local functions */
static int user_gpio_open (struct inode *inode, struct file *filp);
static int user_gpio_release (struct inode *inode, struct file *filp);
static int user_gpio_ioctl (struct inode *inode, struct file *flip,  
    unsigned int cmd, unsigned long args);
static int user_gpio_get_value(int num);
static int user_gpio_set_value(int num, int val);
int user_gpio_init_module(void);
void user_gpio_cleanup_module(void);
 
/* declare file operation structure */
static struct file_operations user_gpio_fops = {
    .owner = THIS_MODULE,
    .open  = user_gpio_open,
    .ioctl = user_gpio_ioctl,
    .release = user_gpio_release,
};
 
/******************************************************************************
 * user_gpio_get_value - This function returns the value of gpio pin number.
 *****************************************************************************/
static int user_gpio_get_value (int num)  
{
    int status, val;
 
    /* first request the gpio pin */
    status = gpio_request(num, "user_gpio");
    if (status < 0) {
        printk(KERN_DEBUG "Failed to request GPIO%d\n", num);
        return -1;
    }
 
    /* set the direction as input */
    gpio_direction_input(num);
 
    /* get the value */
    val = gpio_get_value(num);
 
    /* free gpio resources */
    gpio_free(num);
 
    return val;
}
 
/******************************************************************************
 * user_gpio_set_value - This function sets the value of gpio pin number.
 *****************************************************************************/
static int user_gpio_set_value (int num, int val)
{
    int status;
 
    /* first request the gpio pin */
    status = gpio_request(num, "user_gpio");
    if (status < 0) {
        printk(KERN_DEBUG "Failed to request GPIO%d\n", num);
        return -1;
    }
 
    /* set the direction as output */
    gpio_direction_output(num, 1);
 
    /* set the value */
    gpio_set_value(num, val);
 
    /* free the resources */
    gpio_free(num);
 
    return 0;
}
 
/******************************************************************************
 * user_gpio_ioctl - function to implement the GPIO ioctl's
 *****************************************************************************/
static int user_gpio_ioctl (struct inode *inode, struct file *filp,  
    unsigned int cmd, unsigned long args)
{
    void __user *argp = (void __user *) args;
    struct user_gpio gpio;
 
    if (_IOC_TYPE(cmd) != USER_GPIO_MAGIC)  {
        return -ENOTTY;
    }
    if (_IOC_NR(cmd) > USER_GPIO_MAXNR) {
        return -ENOTTY;
    }
 
    switch (cmd) {
        case USER_GPIO_READ:
            if (copy_from_user(&gpio, argp, sizeof(struct user_gpio)))
                return -EFAULT;
            gpio.value = user_gpio_get_value(gpio.num);
            if (copy_to_user(argp, &gpio, sizeof(struct user_gpio)))
                return -EFAULT;
              
            break;
         
        case USER_GPIO_WRITE:
            if (copy_from_user(&gpio, argp, sizeof(struct user_gpio)))
                return -EFAULT;
            user_gpio_set_value(gpio.num, gpio.value);
            break;
 
        default:
            return -ENOTTY;
            break;
    }
 
    return 0;
}
 
/******************************************************************************
 * user_gpio_open - do nothing  
 *****************************************************************************/
static int user_gpio_open (struct inode *inode, struct file *filp)
{
    return 0;
}     
 
/******************************************************************************
 * user_gpio_release - do nothing  
 *****************************************************************************/
static int user_gpio_release (struct inode *inode, struct file *filp)
{
    return 0;
}  
 
/*****************************************************************************
 * user_gpio_init_module - initialise user gpio module
 ****************************************************************************/
int user_gpio_init_module ()
{
    if (alloc_chrdev_region(&dev, 0, 1, "user_gpio") < 0) {
        printk(KERN_DEBUG "Failed to register the device\n");
        return 1;
    }
 
    user_gpio_cdev = cdev_alloc();
    if (user_gpio_cdev == NULL) {
        printk(KERN_DEBUG "Failed to allocate cdev\n");
        return 1;
    }
 
    cdev_init(user_gpio_cdev, &user_gpio_fops);
    if (cdev_add(user_gpio_cdev, dev, 1) < 0) {
        printk(KERN_DEBUG "Failed to add cdev\n");
        return 1;
    }
 
    return 0;
}
 
/*****************************************************************************
 * user_gpio_init_cleanup - cleanup user gpio module
 ****************************************************************************/
void user_gpio_cleanup_module ()
{
    cdev_del(user_gpio_cdev);
    unregister_chrdev_region(dev, 1);
 
}
 
/* Register driver to the kernel */
module_init(user_gpio_init_module);
module_exit(user_gpio_cleanup_module);

If any one helps to solve this problem it will be very useful for me.

Thanks

  • Looks like the kernel has been built without the GPIO library. Check you kernel config to see that the GPIO driver is included. I am surprised it isn't. Which version of the kernel are you using? The later kernels have an "official" GPIO interface via /sys/class/gpio/ rather than the /dev system.

  • Yes sir you are absolutely right i build the kernel with GPIO library now it is including and am able to insert the .ko file in the kernel and via application i can able to toggle the pin.I am using the kernel 2.6.10_mvl401_IPNC_1.1.0.

    Now gpio driver and application is working sir.With this existing driver i can able to access the interrupt pin with the register change for appropriate register for interrupt in application.

    If u have any driver and application for interrupt please give sir, it will be very very help full for us.

    Thank you very much

  • Linux 2.6.10 is very old. It does not have the "official" GPIO inferface, I think the GPIO interface was introduced somewhere around 2.6.26 or so. Interrupt ability was added in 2.6.33 or 2.6.37. Can't quite remember. Interrupt handling can be complicated. The "official" GPIO handles this by implementing a linux poll() interface. It also implements a blocking read. From what I can see in your example code, the GPIO level is queried via ioctl(). A work-around would be to poll for level changes. Otherwise you'll have to get deeply involved in the Linux device driver writing.

    I'd suggest looking the current kernel version for ideas. Note that the new kernel code will probably not back-port to an older kernel. Or look around your 2.6.10 version for simple drivers that handle interrupts. Most simple drivers will use the structure "file_operations". Search for that structure. Or better move up to the newer kernel if you can. Also, you can try searching around this forum for other people who have tried to write their own GPIO driver libraries. I tried the search term "Linux GPIO file_operations". Be aware, there won't be many examples for such a old kernel.

  • Dear sir,

                     Yes sir you are write it very old kernel but we have the ipnc camera which is having this kernel only inside            

     Now i am attaching a gpio diver and one application that is working sir.My question is with that existing driver can i edit in the application for changing the i/o pins which is used for interrupt and enable the register which used for interrupt means it will work.Or i have to search for separate driver and application.

    In application there are some register is there

    example DIR0,INDATA0

    Instead of this i can set the register like SET_RIS_TRIG01 ,CLR_RIS_TRIG01 means it will work

    i Attach the gipo application

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    //#include "hardware.h"

    #define DAVINCI_SYSTEM_MODULE_BASE        (0x01C40000)
    #define PINMUX0            (DAVINCI_SYSTEM_MODULE_BASE + 0x00)
    #define PINMUX1            (DAVINCI_SYSTEM_MODULE_BASE + 0x04)
    /* dm355 only */
    #define PINMUX2            (DAVINCI_SYSTEM_MODULE_BASE + 0x08)
    #define PINMUX3            (DAVINCI_SYSTEM_MODULE_BASE + 0x0c)
    #define PINMUX4            (DAVINCI_SYSTEM_MODULE_BASE + 0x10)

    #define DAVINCI_GPIO_BASE    (0x01C67000)
    #define DIR01            (DAVINCI_GPIO_BASE + 0x10)
    #define OUT_DATA01        (DAVINCI_GPIO_BASE + 0x14)
    #define SET_DATA01        (DAVINCI_GPIO_BASE + 0x18)
    #define CLR_DATA01        (DAVINCI_GPIO_BASE + 0x1C)
    #define IN_DATA01        (DAVINCI_GPIO_BASE + 0x20)


    int main()
    {
        int fdg,fdp,fdgd,val;
     
        fdg=open("/dev/gpiocustom",O_RDWR);
        if(fdg==-1)
        {
        printf("Failed to open the driver\n");
        return 0;
        }

        fdgd=open("/dev/gpiocustomdir",O_RDWR);
        if(fdgd==-1)
        {
        printf("Failed to open the driver\n");
        return 0;
        }

        fdp=open("/dev/pinmuxcustom",O_RDWR);
        if(fdp==-1)
        {
        printf("Failed to open the driver\n");
        return 0;
        }

        /* Set the PINMUX */    
        val=read(fdp,PINMUX3,0);
        printf("PinMux3 = 0x%X\n",val);
        val=val & 0xFFF9FFFF; //Set pin 16 & pin 17 to GPIO
        write(fdp,PINMUX3,val);    
        val=read(fdp,PINMUX3,0);
        printf("PinMux3 = 0x%X\n",val);

        /* Set the Direction */    
        write(fdgd,17,0);
        val=read(fdgd,17,0);    
        printf("DIR01-17 = 0x%X\n",val);
    /* Different method
        val=read(fdgd,DIR01,0);
        printf("DIR01 = 0x%X\n",val);
        val=val & 0xFFF0FFFF; //Set pin 17 to Output
        printf("val = 0x%X\n",val);
        write(fdgd,DIR01,val);    */
        val=read(fdgd,DIR01,0);
        printf("DIR01 = 0x%X\n",val);

        while(1){
        write(fdg,17,0);
        val = read(fdg,16,0);
        printf ("val 16 = 0x%X\n",val);
        val= read(fdp,IN_DATA01,0);
        printf ("IN_DATA01 = 0x%X\n",val);
        usleep(500000);
        write(fdg,17,1);
        val = read(fdg,16,0);
        printf ("val 16 = 0x%X\n",val);
        val= read(fdp,IN_DATA01,0);
        printf ("IN_DATA01 = 0x%X\n",val);
        usleep(500000);
        }

    }

    Thank you

  • The driver in your first post and the app above don't seem to match. I don't see any other driver code. The app uses the read() and write() interface which are not defined in the driver that you posted.

    Actually the drivers misuse those interfaces. For example, read() is prototyped as ssize_t read(int fd, void *buf, size_t count) where buf is the app memory array to read into and count is the number of bytes to read. Here, the buf parameter is used a physical memory location with pinmuxcustom. With gpiocustom and gpiocustomdir it is uses buf as a number with values like 16 and 17. The count parameters appears to be unused and set to 0.

    Your pinmuxcustom driver appears to read and write from physical memory locations specified by the app. Assuming the pinmuxcustom driver does not do anything else like modifying other registers, I guess you could pass in a different address like SET_RIS_TRIG01 or CLR_RIS_TRIG01.

    To get more people to look at your problem, I would suggest that you unverify my post or start as new thread,. Generally posts with the green verify icon tend to get overlooked.

  • Yes sir the application not suitable to that driver now i am sending the driver and application sir.Here there drivers are there one is

    PINMUX DRIVER -for initialise as gpio

    gpio_custom_dir_driver- for initalise as input or output

    gpio_custom_driver.

    SO three drivers are there and one application sir.

    gpio_cutom_driver.c

    #include <linux/module.h>

    #include <linux/version.h>

    #include <linux/delay.h>

    #include <linux/fs.h>

    #include <asm/arch/hardware.h>



    //#define DAVINCI_GPIO_BASE    (0x01C67000)

    #define GPIO_CUSTOM_MAJOR     202

    #define GPIO_CUSTOM_NAME      "GPIO_CUSTOM_DRIVER"



    static int gpio_custom_read(int file_handle, unsigned int reg_num, unsigned int io_value)

    {

        unsigned int x = 1;

        

        if ( 0 <= reg_num <= 31  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x20);

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }

        if ( 32 <= reg_num <= 63  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x48);

        reg_num = reg_num - 32;

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }

        if ( 64 <= reg_num <= 95  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x70);

        reg_num = reg_num - 64;

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }

        if ( 96 <= reg_num <= 103  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x98);

        reg_num = reg_num - 96;

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }

        if ( (reg_num ==  DAVINCI_GPIO_BASE+0x20) || (reg_num ==  DAVINCI_GPIO_BASE+0x48) ||

             (reg_num ==  DAVINCI_GPIO_BASE+0x70) || (reg_num ==  DAVINCI_GPIO_BASE+0x98) )

        {

        return davinci_readl(reg_num);

        }

        return -1;

    }

    static int gpio_custom_write(int file_handle, unsigned int reg_num, unsigned int reg_val)

    {

        unsigned int x=1, io_value;

    //add check if reg_val is GT 1    

        if ( 0 <= reg_num <= 31  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x14);

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value,DAVINCI_GPIO_BASE+0x14);

        }

        if ( 32 <= reg_num <= 63  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x3C);

        reg_num = reg_num - 32;

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value,DAVINCI_GPIO_BASE+0x3C);

        }

        if ( 64 <= reg_num <= 95  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x64);

        reg_num = reg_num - 64;

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value,DAVINCI_GPIO_BASE+0x64);

        }

        if ( 96 <= reg_num <= 103  )

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x8C);

        reg_num = reg_num - 96;

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value,DAVINCI_GPIO_BASE+0x8C);

        }

        if ( (reg_num ==  DAVINCI_GPIO_BASE+0x14) || (reg_num ==  DAVINCI_GPIO_BASE+0x3C) ||

             (reg_num ==  DAVINCI_GPIO_BASE+0x64) || (reg_num ==  DAVINCI_GPIO_BASE+0x8C) )

        {

        return davinci_writel(reg_val,reg_num);

        }

        

        return -1;

    }



    static int gpio_custom_open(struct inode *inode, struct file *file)

    {

    return 0;

    }

    struct file_operations gpio_custom_file_ops = {

        .owner        = THIS_MODULE,

        .llseek        = NULL,

        .read        = gpio_custom_read,

        .write        = gpio_custom_write,

        .readdir    = NULL,

        .poll        = NULL,

        .ioctl        = NULL,

        .mmap        = NULL,

        .open        = gpio_custom_open,

        .flush        = NULL,

        .release    = NULL,

        .fsync        = NULL,

        .fasync        = NULL,

        .lock        = NULL,

        .readv        = NULL,

        .writev        = NULL,    

    };
    int __init init_module (void) /* Loads a module in the kernel */

    {

        int status;

        printk("Initializing the GPIO driver \n");

        printk("This driver is for DM devices on LSP1.20 \n");



        status = register_chrdev(GPIO_CUSTOM_MAJOR, GPIO_CUSTOM_NAME, &gpio_custom_file_ops);      

        return status;

    }

    void cleanup_module(void) /* Removes module from kernel */

    {

        printk("Cleaning up GPIO driver \n");

        unregister_chrdev(GPIO_CUSTOM_MAJOR, GPIO_CUSTOM_NAME);

    }

    MODULE_AUTHOR("Frangline Jose");

    MODULE_DESCRIPTION("GPIO driver for TMS320DM devices");

    MODULE_LICENSE("GPL");

    gpio_custom_dir_driver.c

    #include <linux/module.h>

    #include <linux/version.h>

    #include <linux/delay.h>

    #include <linux/fs.h>

    #include <asm/arch/hardware.h>


    #define GPIO_CUSTOM_DIR_MAJOR     203

    #define GPIO_CUSTOM_DIR_NAME      "GPIO_CUSTOM_DIR_DRIVER"


    static int gpio_custom_dir_read(int file_handle, unsigned int reg_num, unsigned int io_value)

    {

        unsigned int x = 1;



        if ((reg_num >=0) && (reg_num <= 31))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x10);

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }



        if ((reg_num >=32) && (reg_num <= 63))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x38);

        reg_num = reg_num - 32;

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }



        if ((reg_num >=64) && (reg_num <= 95))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x60);

        reg_num = reg_num - 64;

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }



        if ((reg_num >=96) && (reg_num <= 103))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x88);

        reg_num = reg_num - 96;

        x = x << (reg_num);

        io_value = io_value & x;

        return (io_value >> (reg_num));

        }



        if ( (reg_num ==  DAVINCI_GPIO_BASE+0x10) || (reg_num ==  DAVINCI_GPIO_BASE+0x38) ||

             (reg_num ==  DAVINCI_GPIO_BASE+0x60) || (reg_num ==  DAVINCI_GPIO_BASE+0x88) )

        {

        return davinci_readl(reg_num);

        }

        return -1;

    }


    static int gpio_custom_dir_write(int file_handle, unsigned int reg_num, unsigned int reg_val)

    {

        unsigned int x=1;

        unsigned int io_value;



        if ((reg_num >=0) && (reg_num <= 31))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x10);

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value, DAVINCI_GPIO_BASE+0x10);

        }



        if ((reg_num >=32) && (reg_num <= 63))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x38);

        reg_num = reg_num - 32;

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value,DAVINCI_GPIO_BASE+0x38);

        }



        if ((reg_num >=64) && (reg_num <= 95))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x60);

        reg_num = reg_num - 64;

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value,(DAVINCI_GPIO_BASE+0x60));

        }



        if ((reg_num >=96) && (reg_num <= 103))

        {

        io_value = davinci_readl(DAVINCI_GPIO_BASE+0x88);

        reg_num = reg_num - 96;

        if (reg_val) io_value = io_value | (x << (reg_num));

        else io_value = io_value & (~(x << reg_num));

        return davinci_writel(io_value,(DAVINCI_GPIO_BASE+0x88));

        }



        if ( (reg_num ==  DAVINCI_GPIO_BASE+0x10) || (reg_num ==  DAVINCI_GPIO_BASE+0x38) ||

             (reg_num ==  DAVINCI_GPIO_BASE+0x60) || (reg_num ==  DAVINCI_GPIO_BASE+0x88) )

        {

        return davinci_writel(reg_val,reg_num);

        }

        

        return -1;

    }
    static int gpio_custom_dir_open(struct inode *inode, struct file *file)

    {

    return 0;

    }
    struct file_operations gpio_custom_dir_file_ops = {

        .owner        = THIS_MODULE,

        .llseek        = NULL,

        .read        = gpio_custom_dir_read,

        .write        = gpio_custom_dir_write,

        .readdir    = NULL,

        .poll        = NULL,

        .ioctl        = NULL,

        .mmap        = NULL,

        .open        = gpio_custom_dir_open,

        .flush        = NULL,

        .release    = NULL,

        .fsync        = NULL,

        .fasync        = NULL,

        .lock        = NULL,

        .readv        = NULL,

        .writev        = NULL,    

    };

    int __init init_module (void) /* Loads a module in the kernel */

    {

        int status;

        printk("Initializing the GPIO Direction driver \n");

        printk("This driver is for DM devices on LSP1.20 \n");

        status = register_chrdev(GPIO_CUSTOM_DIR_MAJOR, GPIO_CUSTOM_DIR_NAME,

             &gpio_custom_dir_file_ops);      

        return status;

    }


    void cleanup_module(void) /* Removes module from kernel */

    {

        printk("Cleaning up GPIO Direction driver \n");

        unregister_chrdev(GPIO_CUSTOM_DIR_MAJOR, GPIO_CUSTOM_DIR_NAME);

    }

    MODULE_AUTHOR("Frangline Jose");

    MODULE_DESCRIPTION("GPIO direction driver for TMS320DM devices");

    MODULE_LICENSE("GPL");

    pinmux_custom_driver.c


    #include <linux/module.h>

    #include <linux/version.h>

    #include <linux/delay.h>

    #include <linux/fs.h>

    #include <asm/arch/hardware.h>

    #include <asm/gpio.h>


    #define PINMUX_CUSTOM_MAJOR 204

    #define PINMUX_CUSTOM_NAME  "PINMUX_CUSTOM_DRIVER"


    static int pinmux_custom_read(int file_handle, unsigned int reg_num, int io_value)

    {

        io_value = davinci_readl(reg_num);

        return io_value;

    }


    static int pinmux_custom_write(int file_handle, unsigned int reg_num, unsigned int reg_val)

    {

        printk("REG=0x%X, Val=0x%X\n",reg_num,reg_val);

        davinci_writel(reg_val, reg_num);

        return 0;

    }



    static int pinmux_custom_open(struct inode *inode, struct file *file)

    {

    return 0;

    }



    struct file_operations pinmux_custom_file_ops = {

        .owner        = THIS_MODULE,

        .llseek        = NULL,

        .read        = pinmux_custom_read,

        .write        = pinmux_custom_write,

        .readdir    = NULL,

        .poll        = NULL,

        .ioctl        = NULL,

        .mmap        = NULL,

        .open        = pinmux_custom_open,

        .flush        = NULL,

        .release    = NULL,

        .fsync        = NULL,

        .fasync        = NULL,

        .lock        = NULL,

        .readv        = NULL,

        .writev        = NULL,    

    };



    int __init init_module (void) /* Loads a module in the kernel */

    {

        int status;

        printk("Initializing the PINMUX driver \n");

        printk("This driver is for DM devices on LSP1.20 \n");



        status = register_chrdev(PINMUX_CUSTOM_MAJOR, PINMUX_CUSTOM_NAME,

                 &pinmux_custom_file_ops);      

        return status;

    }


    void cleanup_module(void) /* Removes module from kernel */

    {

        printk("Cleaning up PINMUX driver \n");

        unregister_chrdev(PINMUX_CUSTOM_MAJOR, PINMUX_CUSTOM_NAME);

    }

    MODULE_AUTHOR("Frangline Jose");

    MODULE_DESCRIPTION("PINMUX driver for TMS320DM devices");

    MODULE_LICENSE("GPL");

    application.c

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    //#include "hardware.h"

    #define DAVINCI_SYSTEM_MODULE_BASE        (0x01C40000)
    #define PINMUX0            (DAVINCI_SYSTEM_MODULE_BASE + 0x00)
    #define PINMUX1            (DAVINCI_SYSTEM_MODULE_BASE + 0x04)
    /* dm355 only */
    #define PINMUX2            (DAVINCI_SYSTEM_MODULE_BASE + 0x08)
    #define PINMUX3            (DAVINCI_SYSTEM_MODULE_BASE + 0x0c)
    #define PINMUX4            (DAVINCI_SYSTEM_MODULE_BASE + 0x10)

    #define DAVINCI_GPIO_BASE    (0x01C67000)
    #define DIR01            (DAVINCI_GPIO_BASE + 0x10)
    #define OUT_DATA01        (DAVINCI_GPIO_BASE + 0x14)
    #define SET_DATA01        (DAVINCI_GPIO_BASE + 0x18)
    #define CLR_DATA01        (DAVINCI_GPIO_BASE + 0x1C)
    #define IN_DATA01        (DAVINCI_GPIO_BASE + 0x20)


    int main()
    {
        int fdg,fdp,fdgd,val;
     
        fdg=open("/dev/gpio_custom_driver",O_RDWR);
        if(fdg==-1)
        {
        printf("Failed to open the driver\n");
        return 0;
        }

        fdgd=open("/dev/gpio_custom_dir_driver",O_RDWR);
        if(fdgd==-1)
        {
        printf("Failed to open the driver\n");
        return 0;
        }

        fdp=open("/dev/pinmux_custom_driver",O_RDWR);
        if(fdp==-1)
        {
        printf("Failed to open the driver\n");
        return 0;
        }

        /* Set the PINMUX */    
        val=read(fdp,PINMUX3,0);
        printf("PinMux3 = 0x%X\n",val);
        val=val & 0xFFF9FFFF; //Set pin 16 & pin 17 to GPIO
        write(fdp,PINMUX3,val);    
        val=read(fdp,PINMUX3,0);
        printf("PinMux3 = 0x%X\n",val);

        /* Set the Direction */    
        write(fdgd,17,0);
        val=read(fdgd,17,0);    
        printf("DIR01-17 = 0x%X\n",val);
    /* Different method
        val=read(fdgd,DIR01,0);
        printf("DIR01 = 0x%X\n",val);
        val=val & 0xFFF0FFFF; //Set pin 17 to Output
        printf("val = 0x%X\n",val);
        write(fdgd,DIR01,val);    */
        val=read(fdgd,DIR01,0);
        printf("DIR01 = 0x%X\n",val);

        while(1){
        write(fdg,17,0);
        val = read(fdg,16,0);
        printf ("val 16 = 0x%X\n",val);
        val= read(fdp,IN_DATA01,0);
        printf ("IN_DATA01 = 0x%X\n",val);
        usleep(50000000);
        write(fdg,17,1);
        val = read(fdg,16,0);
        printf ("val 16 = 0x%X\n",val);
        val= read(fdp,IN_DATA01,0);
        printf ("IN_DATA01 = 0x%X\n",val);
        usleep(50000000);
          
        }

    }

    These are application and drivers i used for toggling the pin.

    Now i am trying to do with the same existing driver if change in the application like i included the register which used for interrupt.But i dont know how to write interrupt subroutine in the application.If i get the answer it will be very helpful for me.

    Thank you very much





  • Dear sir,

                   Can any one guide me how to use the below interrupt function in the above gpio driver and applications.

    request_irq(IRQ_DM355_GPIOBNK6, isr, SA_INTERRUPT, "slave",NULL);

    It will be very use full for me.

    Thank you very much