海思GPIO


#include 
#include 
#include 



#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);
    }


}


你可能感兴趣的:(海思)