打印

海思 GPIO驱动程序

[复制链接]
205|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#include <asm/io.h>  

#include <mach/irqs.h>  

#include <mach/hardware.h>  

  

  

  

#define GPIO_DIR     0x400  

#define GPIO_IS      0x404  

#define GPIO_IBE     0x408  

#define GPIO_IEV     0x40C  

#define GPIO_IE      0x410  

#define GPIO_RIS     0x414  

#define GPIO_MIS     0x418  

#define GPIO_IC      0x41C  

  

  

  

  

/************************************************************************/  

/*                         gpio interface                               */  

/************************************************************************/  

  

  

  

  

/**

* _set_gpio_direction - set gpio direction

*

* @port:

* @offset:

* @dir: 0 -- input, 1 -- output

*/  

static void _set_gpio_direction(struct hisi_gpio_port *port, unsigned offset, int dir)  

{  

    u32 l;  

    unsigned long flags;  

  

  

    spin_lock_irqsave(&port->lock, flags);  

    l = __raw_readl(port->base + GPIO_DIR);  

    if (dir)  

        l |= (1 << offset);  

    else  

        l &= ~(1 << offset);  

    __raw_writel(l, port->base + GPIO_DIR);  

    spin_unlock_irqrestore(&port->lock, flags);  

}  

  

  

/**

* hisi_gpio_set - get gpio data

*

*/  

static void hisi_gpio_set(struct hisi_gpio_port *port, unsigned offset, int value)  

{  

    void __iomem *reg = port->base + (1 << (offset + 2));  

    u32 l;  

    unsigned long flags;  

  

  

    spin_lock_irqsave(&port->lock, flags);  

    l = (__raw_readl(reg) & (~(1 << offset))) | (!!value << offset);  

    __raw_writel(l, reg);  

    spin_unlock_irqrestore(&port->lock, flags);  

}  

  

  

/**

* hisi_gpio_get - get gpio value

*

*/  

static int hisi_gpio_get(struct hisi_gpio_port *port, unsigned offset)  

{  

    void __iomem *reg = port->base + (1 << (offset + 2));  

    u32 gpio_direction;  

  

  

    gpio_direction = __raw_readl(port->base + GPIO_DIR);  

    if (((gpio_direction >> offset) & 1))  /* output mode */  

        return (__raw_readl(reg) >> offset) & 1;  

    else /* input mode */  

        return 0;  

}  

  

  

/**

* hisi_gpio_direction_input - gpio direction input

*

*/  

static int hisi_gpio_direction_input(struct hisi_gpio_port *port, unsigned offset)  

{  

    _set_gpio_direction(port, offset, 0);  

    return 0;  

}  

  

  

/**

* hisi_gpio_direction_output - gpio direction output

*

*/  

static int hisi_gpio_direction_output(struct hisi_gpio_port *port, unsigned offset, int value)  

{  

    hisi_gpio_set(port, offset, value);  

    _set_gpio_direction(port, offset, 1);  

    return 0;  

}  

  

  

  

  

/**

* hisi_gpio_init - gpio init functions

*

* @ int_trigger_type: 0~4, ref GT911 datasheet

*

* Must be called by goodix_ts_probe functions only once.

*/  

static int hisi_gpio_init(struct hisi_gpio_port *port, int int_trigger_type)  

{  

    int i, j;  

    u32 l;  

    unsigned offset;  

    const uint8_t irq_table[] = GTP_IRQ_TAB;  

    static bool initialed;  

  

  

    if (initialed)  

        return 0;  

  

  

    printk(KERN_INFO "HISI GPIO hardware\n");  

  

  

    /*1. ioremap */  

    port->base = ioremap_nocache(GTP_BASE_ADDRESS, GTP_RANGE_SIZE);  

    if (!port->base) {  

        dev_err(&ts->client->dev,  

            "Can't remap gpio address: 0x%x, size:0x%dx\n", GTP_BASE_ADDRESS, GTP_RANGE_SIZE);  

        return -1;  

    }  

  

  

    /*2. IOMUX */  

    /*

    writel(reg, IOCONFIG_BASE + 0x178);

    writel(reg, IOCONFIG_BASE + 0x17C);

    */  

  

  

  

  

    /*3. config rest */  

    offset = 7;  

    hisi_gpio_direction_output(port, offset);  // output mode  

  

  

  

  

    /*4. config int */  

    offset = 6;  

    hisi_gpio_direction_input(port, offset);  // input mode  

  

  

    //  

    switch (irq_table[int_trigger_type])  

    {  

    case IRQ_TYPE_EDGE_RISING:  

    {  

                                 /* */  

                                 l = __raw_readl(port->base + GPIO_IS) & (~(1 << offset));  

                                 __raw_writel(l, port->base + GPIO_IS);  

  

                                 /* */  

                                 l = __raw_readl(port->base + GPIO_IEV) | (1 << offset);  

                                 __raw_writel(l, port->base + GPIO_IEV);  

  

  

                                 /**/  

                                 l = __raw_readl(port->base + GPIO_IBE) & (~(1 << offset));  

                                 __raw_writel(l, port->base + GPIO_IBE);  

    }  

        break;  

    case IRQ_TYPE_EDGE_FALLING:  

    {  

                                  /* */  

                                  l = __raw_readl(port->base + GPIO_IS) & (~(1 << offset));  

                                  __raw_writel(l, port->base + GPIO_IS);  

  

  

                                  /* */  

                                  l = __raw_readl(port->base + GPIO_IEV) & (~(1 << offset));  

                                  __raw_writel(l, port->base + GPIO_IEV);  

  

  

                                  /**/  

                                  l = __raw_readl(port->base + GPIO_IBE) & (~(1 << offset));  

                                  __raw_writel(l, port->base + GPIO_IBE);  

    }  

        break;  

    case IRQ_TYPE_LEVEL_LOW:  

    {  

                               /* */  

                               l = __raw_readl(port->base + GPIO_IS) | (1 << offset);  

                               __raw_writel(l, port->base + GPIO_IS);  

  

  

                               /* */  

                               l = __raw_readl(port->base + GPIO_IEV) & (~(1 << offset));  

                               __raw_writel(l, port->base + GPIO_IEV);  

  

  

    }  

        break;  

    case IRQ_TYPE_LEVEL_HIGH:  

    {  

                                /* */  

                                l = __raw_readl(port->base + GPIO_IS) | (1 << offset);  

                                __raw_writel(l, port->base + GPIO_IS);  

  

  

                                /* */  

                                l = __raw_readl(port->base + GPIO_IEV) | (1 << offset);  

                                __raw_writel(l, port->base + GPIO_IEV);  

  

  

    }  

        break;  

    default:  

        break;  

    }  

  

  

    /* disable the interrupt and clear the status */  

    __raw_writel(~0, port->base + GPIO_IC);  

    __raw_writel(~0, port->base + GPIO_IE);  

  

    spin_lock_init(&port->lock);  



    initialed = true;  

    return 0;  

}  

  

  

/**

* hisi_gpio_deinit - DeInit functions

*

*/  

static void hisi_gpio_deinit(struct hisi_gpio_port *port)  

{  

    if (!port)  

        return;  

  

    __raw_writel(~0, port->base + GPIO_IC);  

    __raw_writel(0, port->base + GPIO_IE);  

  

    if (port->base)  

    {  

        iounmap(port->base);  

    }  

}  复制代码

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

376

主题

377

帖子

0

粉丝