您的位置:首页 > 其它

海思GPIO

2015-10-29 15:19 246 查看
#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);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: