-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 137535 b: refs/heads/master c: 1df621a h: refs/heads/master i: 137533: 1b5b5c9 137531: 9ddacb9 137527: e4b462b 137519: 38476fc 137503: b9fedce 137471: 2e32a79 v: v3
- Loading branch information
Paulius Zaleckas
committed
Mar 26, 2009
1 parent
8e35c73
commit 491e6bd
Showing
7 changed files
with
266 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 881a95f976e687307b41ba3c767561f533485c7e | ||
refs/heads/master: 1df621ae2f3b03d557d962a7afec2b1d04558986 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ | |
|
||
# Object file lists. | ||
|
||
obj-y := irq.o mm.o time.o devices.o | ||
obj-y := irq.o mm.o time.o devices.o gpio.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
/* | ||
* Gemini gpiochip and interrupt routines | ||
* | ||
* Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
* | ||
* Based on plat-mxc/gpio.c: | ||
* MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de> | ||
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/init.h> | ||
#include <linux/io.h> | ||
#include <linux/irq.h> | ||
#include <linux/gpio.h> | ||
|
||
#include <mach/hardware.h> | ||
#include <mach/irqs.h> | ||
|
||
#define GPIO_BASE(x) IO_ADDRESS(GEMINI_GPIO_BASE(x)) | ||
|
||
/* GPIO registers definition */ | ||
#define GPIO_DATA_OUT 0x0 | ||
#define GPIO_DATA_IN 0x4 | ||
#define GPIO_DIR 0x8 | ||
#define GPIO_DATA_SET 0x10 | ||
#define GPIO_DATA_CLR 0x14 | ||
#define GPIO_PULL_EN 0x18 | ||
#define GPIO_PULL_TYPE 0x1C | ||
#define GPIO_INT_EN 0x20 | ||
#define GPIO_INT_STAT 0x24 | ||
#define GPIO_INT_MASK 0x2C | ||
#define GPIO_INT_CLR 0x30 | ||
#define GPIO_INT_TYPE 0x34 | ||
#define GPIO_INT_BOTH_EDGE 0x38 | ||
#define GPIO_INT_LEVEL 0x3C | ||
#define GPIO_DEBOUNCE_EN 0x40 | ||
#define GPIO_DEBOUNCE_PRESCALE 0x44 | ||
|
||
#define GPIO_PORT_NUM 3 | ||
|
||
static void _set_gpio_irqenable(unsigned int base, unsigned int index, | ||
int enable) | ||
{ | ||
unsigned int reg; | ||
|
||
reg = __raw_readl(base + GPIO_INT_EN); | ||
reg = (reg & (~(1 << index))) | (!!enable << index); | ||
__raw_writel(reg, base + GPIO_INT_EN); | ||
} | ||
|
||
static void gpio_ack_irq(unsigned int irq) | ||
{ | ||
unsigned int gpio = irq_to_gpio(irq); | ||
unsigned int base = GPIO_BASE(gpio / 32); | ||
|
||
__raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR); | ||
} | ||
|
||
static void gpio_mask_irq(unsigned int irq) | ||
{ | ||
unsigned int gpio = irq_to_gpio(irq); | ||
unsigned int base = GPIO_BASE(gpio / 32); | ||
|
||
_set_gpio_irqenable(base, gpio % 32, 0); | ||
} | ||
|
||
static void gpio_unmask_irq(unsigned int irq) | ||
{ | ||
unsigned int gpio = irq_to_gpio(irq); | ||
unsigned int base = GPIO_BASE(gpio / 32); | ||
|
||
_set_gpio_irqenable(base, gpio % 32, 1); | ||
} | ||
|
||
static int gpio_set_irq_type(unsigned int irq, unsigned int type) | ||
{ | ||
unsigned int gpio = irq_to_gpio(irq); | ||
unsigned int gpio_mask = 1 << (gpio % 32); | ||
unsigned int base = GPIO_BASE(gpio / 32); | ||
unsigned int reg_both, reg_level, reg_type; | ||
|
||
reg_type = __raw_readl(base + GPIO_INT_TYPE); | ||
reg_level = __raw_readl(base + GPIO_INT_BOTH_EDGE); | ||
reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE); | ||
|
||
switch (type) { | ||
case IRQ_TYPE_EDGE_BOTH: | ||
reg_type &= ~gpio_mask; | ||
reg_both |= gpio_mask; | ||
break; | ||
case IRQ_TYPE_EDGE_RISING: | ||
reg_type &= ~gpio_mask; | ||
reg_both &= ~gpio_mask; | ||
reg_level &= ~gpio_mask; | ||
break; | ||
case IRQ_TYPE_EDGE_FALLING: | ||
reg_type &= ~gpio_mask; | ||
reg_both &= ~gpio_mask; | ||
reg_level |= gpio_mask; | ||
break; | ||
case IRQ_TYPE_LEVEL_HIGH: | ||
reg_type |= gpio_mask; | ||
reg_level &= ~gpio_mask; | ||
break; | ||
case IRQ_TYPE_LEVEL_LOW: | ||
reg_type |= gpio_mask; | ||
reg_level |= gpio_mask; | ||
break; | ||
default: | ||
return -EINVAL; | ||
} | ||
|
||
__raw_writel(reg_type, base + GPIO_INT_TYPE); | ||
__raw_writel(reg_level, base + GPIO_INT_BOTH_EDGE); | ||
__raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE); | ||
|
||
gpio_ack_irq(irq); | ||
|
||
return 0; | ||
} | ||
|
||
static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
{ | ||
unsigned int gpio_irq_no, irq_stat; | ||
unsigned int port = (unsigned int)get_irq_data(irq); | ||
|
||
irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT); | ||
|
||
gpio_irq_no = GPIO_IRQ_BASE + port * 32; | ||
for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) { | ||
|
||
if ((irq_stat & 1) == 0) | ||
continue; | ||
|
||
BUG_ON(!(irq_desc[gpio_irq_no].handle_irq)); | ||
irq_desc[gpio_irq_no].handle_irq(gpio_irq_no, | ||
&irq_desc[gpio_irq_no]); | ||
} | ||
} | ||
|
||
static struct irq_chip gpio_irq_chip = { | ||
.name = "GPIO", | ||
.ack = gpio_ack_irq, | ||
.mask = gpio_mask_irq, | ||
.unmask = gpio_unmask_irq, | ||
.set_type = gpio_set_irq_type, | ||
}; | ||
|
||
static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset, | ||
int dir) | ||
{ | ||
unsigned int base = GPIO_BASE(offset / 32); | ||
unsigned int reg; | ||
|
||
reg = __raw_readl(base + GPIO_DIR); | ||
if (dir) | ||
reg |= 1 << (offset % 32); | ||
else | ||
reg &= ~(1 << (offset % 32)); | ||
__raw_writel(reg, base + GPIO_DIR); | ||
} | ||
|
||
static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
{ | ||
unsigned int base = GPIO_BASE(offset / 32); | ||
|
||
if (value) | ||
__raw_writel(1 << (offset % 32), base + GPIO_DATA_SET); | ||
else | ||
__raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR); | ||
} | ||
|
||
static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
{ | ||
unsigned int base = GPIO_BASE(offset / 32); | ||
|
||
return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1; | ||
} | ||
|
||
static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
{ | ||
_set_gpio_direction(chip, offset, 0); | ||
return 0; | ||
} | ||
|
||
static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
int value) | ||
{ | ||
_set_gpio_direction(chip, offset, 1); | ||
gemini_gpio_set(chip, offset, value); | ||
return 0; | ||
} | ||
|
||
static struct gpio_chip gemini_gpio_chip = { | ||
.label = "Gemini", | ||
.direction_input = gemini_gpio_direction_input, | ||
.get = gemini_gpio_get, | ||
.direction_output = gemini_gpio_direction_output, | ||
.set = gemini_gpio_set, | ||
.base = 0, | ||
.ngpio = GPIO_PORT_NUM * 32, | ||
}; | ||
|
||
void __init gemini_gpio_init(void) | ||
{ | ||
int i, j; | ||
|
||
for (i = 0; i < GPIO_PORT_NUM; i++) { | ||
/* disable, unmask and clear all interrupts */ | ||
__raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN); | ||
__raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK); | ||
__raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR); | ||
|
||
for (j = GPIO_IRQ_BASE + i * 32; | ||
j < GPIO_IRQ_BASE + (i + 1) * 32; j++) { | ||
set_irq_chip(j, &gpio_irq_chip); | ||
set_irq_handler(j, handle_edge_irq); | ||
set_irq_flags(j, IRQF_VALID); | ||
} | ||
|
||
set_irq_chained_handler(IRQ_GPIO(i), gpio_irq_handler); | ||
set_irq_data(IRQ_GPIO(i), (void *)i); | ||
} | ||
|
||
BUG_ON(gpiochip_add(&gemini_gpio_chip)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Gemini gpiolib specific defines | ||
* | ||
* Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
*/ | ||
|
||
#ifndef __MACH_GPIO_H__ | ||
#define __MACH_GPIO_H__ | ||
|
||
#include <mach/irqs.h> | ||
#include <asm-generic/gpio.h> | ||
|
||
#define gpio_get_value __gpio_get_value | ||
#define gpio_set_value __gpio_set_value | ||
#define gpio_cansleep __gpio_cansleep | ||
|
||
#define gpio_to_irq(x) ((x) + GPIO_IRQ_BASE) | ||
#define irq_to_gpio(x) ((x) - GPIO_IRQ_BASE) | ||
|
||
#endif /* __MACH_GPIO_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters