Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 350533
b: refs/heads/master
c: ac652d7
h: refs/heads/master
i:
  350531: ca11ffa
v: v3
  • Loading branch information
Lee Jones authored and Linus Walleij committed Feb 10, 2013
1 parent 4a1f1a6 commit 7811ac4
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 297 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7ac63ac61d67703aba1add4a89c4de702068d2f2
refs/heads/master: ac652d7941f84c24cb27378aefbb4015f4c1da67
299 changes: 3 additions & 296 deletions trunk/drivers/pinctrl/pinctrl-abx500.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/mfd/abx500.h>
Expand Down Expand Up @@ -87,20 +88,11 @@
#define AB8540_GPIO_VINSEL_REG 0x47
#define AB8540_GPIO_PULL_UPDOWN_REG 0x48
#define AB8500_GPIO_ALTFUN_REG 0x50
#define AB8500_NUM_VIR_GPIO_IRQ 16
#define AB8540_GPIO_PULL_UPDOWN_MASK 0x03
#define AB8540_GPIO_VINSEL_MASK 0x03
#define AB8540_GPIOX_VBAT_START 51
#define AB8540_GPIOX_VBAT_END 54

enum abx500_gpio_action {
NONE,
STARTUP,
SHUTDOWN,
MASK,
UNMASK
};

struct abx500_pinctrl {
struct device *dev;
struct pinctrl_dev *pctldev;
Expand All @@ -109,14 +101,8 @@ struct abx500_pinctrl {
struct ab8500 *parent;
struct mutex lock;
u32 irq_base;
enum abx500_gpio_action irq_action;
u16 rising;
u16 falling;
struct abx500_gpio_irq_cluster *irq_cluster;
int irq_cluster_size;
int irq_gpio_rising_offset;
int irq_gpio_falling_offset;
int irq_gpio_factor;
};

/**
Expand Down Expand Up @@ -473,7 +459,6 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
struct gpio_chip *chip,
unsigned offset, unsigned gpio)
{
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
const char *label = gpiochip_is_requested(chip, offset - 1);
u8 gpio_offset = offset - 1;
int mode = -1;
Expand Down Expand Up @@ -502,25 +487,6 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
: "? ")
: (pull ? "pull up" : "pull down"),
(mode < 0) ? "unknown" : modes[mode]);

if (label && !is_out) {
int irq = gpio_to_irq(gpio);
struct irq_desc *desc = irq_to_desc(irq);

if (irq >= 0 && desc->action) {
char *trigger;
int irq_offset = irq - pct->irq_base;

if (pct->rising & BIT(irq_offset))
trigger = "edge-rising";
else if (pct->falling & BIT(irq_offset))
trigger = "edge-falling";
else
trigger = "edge-undefined";

seq_printf(s, " irq-%d %s", irq, trigger);
}
}
}

static void abx500_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
Expand Down Expand Up @@ -574,219 +540,6 @@ static struct gpio_chip abx500gpio_chip = {
.dbg_show = abx500_gpio_dbg_show,
};

static unsigned int irq_to_rising(unsigned int irq)
{
struct abx500_pinctrl *pct = irq_get_chip_data(irq);
int offset = irq - pct->irq_base;
int new_irq;

new_irq = offset * pct->irq_gpio_factor
+ pct->irq_gpio_rising_offset
+ pct->parent->irq_base;

return new_irq;
}

static unsigned int irq_to_falling(unsigned int irq)
{
struct abx500_pinctrl *pct = irq_get_chip_data(irq);
int offset = irq - pct->irq_base;
int new_irq;

new_irq = offset * pct->irq_gpio_factor
+ pct->irq_gpio_falling_offset
+ pct->parent->irq_base;
return new_irq;

}

static unsigned int rising_to_irq(unsigned int irq, void *dev)
{
struct abx500_pinctrl *pct = dev;
int offset, new_irq;

offset = irq - pct->irq_gpio_rising_offset
- pct->parent->irq_base;
new_irq = (offset / pct->irq_gpio_factor)
+ pct->irq_base;

return new_irq;
}

static unsigned int falling_to_irq(unsigned int irq, void *dev)
{
struct abx500_pinctrl *pct = dev;
int offset, new_irq;

offset = irq - pct->irq_gpio_falling_offset
- pct->parent->irq_base;
new_irq = (offset / pct->irq_gpio_factor)
+ pct->irq_base;

return new_irq;
}

/*
* IRQ handler
*/

static irqreturn_t handle_rising(int irq, void *dev)
{

handle_nested_irq(rising_to_irq(irq , dev));
return IRQ_HANDLED;
}

static irqreturn_t handle_falling(int irq, void *dev)
{

handle_nested_irq(falling_to_irq(irq, dev));
return IRQ_HANDLED;
}

static void abx500_gpio_irq_lock(struct irq_data *data)
{
struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data);
mutex_lock(&pct->lock);
}

static void abx500_gpio_irq_sync_unlock(struct irq_data *data)
{
struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data);
unsigned int irq = data->irq;
int offset = irq - pct->irq_base;
bool rising = pct->rising & BIT(offset);
bool falling = pct->falling & BIT(offset);
int ret;

switch (pct->irq_action) {
case STARTUP:
if (rising)
ret = request_threaded_irq(irq_to_rising(irq),
NULL, handle_rising,
IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
"abx500-gpio-r", pct);
if (falling)
ret = request_threaded_irq(irq_to_falling(irq),
NULL, handle_falling,
IRQF_TRIGGER_FALLING | IRQF_NO_SUSPEND,
"abx500-gpio-f", pct);
break;
case SHUTDOWN:
if (rising)
free_irq(irq_to_rising(irq), pct);
if (falling)
free_irq(irq_to_falling(irq), pct);
break;
case MASK:
if (rising)
disable_irq(irq_to_rising(irq));
if (falling)
disable_irq(irq_to_falling(irq));
break;
case UNMASK:
if (rising)
enable_irq(irq_to_rising(irq));
if (falling)
enable_irq(irq_to_falling(irq));
break;
case NONE:
break;
}
pct->irq_action = NONE;
pct->rising &= ~(BIT(offset));
pct->falling &= ~(BIT(offset));
mutex_unlock(&pct->lock);
}


static void abx500_gpio_irq_mask(struct irq_data *data)
{
struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data);
pct->irq_action = MASK;
}

static void abx500_gpio_irq_unmask(struct irq_data *data)
{
struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data);
pct->irq_action = UNMASK;
}

static int abx500_gpio_irq_set_type(struct irq_data *data, unsigned int type)
{
struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data);
unsigned int irq = data->irq;
int offset = irq - pct->irq_base;

if (type == IRQ_TYPE_EDGE_BOTH) {
pct->rising = BIT(offset);
pct->falling = BIT(offset);
} else if (type == IRQ_TYPE_EDGE_RISING) {
pct->rising = BIT(offset);
} else {
pct->falling = BIT(offset);
}
return 0;
}

static unsigned int abx500_gpio_irq_startup(struct irq_data *data)
{
struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data);
pct->irq_action = STARTUP;
return 0;
}

static void abx500_gpio_irq_shutdown(struct irq_data *data)
{
struct abx500_pinctrl *pct = irq_data_get_irq_chip_data(data);
pct->irq_action = SHUTDOWN;
}

static struct irq_chip abx500_gpio_irq_chip = {
.name = "abx500-gpio",
.irq_startup = abx500_gpio_irq_startup,
.irq_shutdown = abx500_gpio_irq_shutdown,
.irq_bus_lock = abx500_gpio_irq_lock,
.irq_bus_sync_unlock = abx500_gpio_irq_sync_unlock,
.irq_mask = abx500_gpio_irq_mask,
.irq_unmask = abx500_gpio_irq_unmask,
.irq_set_type = abx500_gpio_irq_set_type,
};

static int abx500_gpio_irq_init(struct abx500_pinctrl *pct)
{
u32 base = pct->irq_base;
int irq;

for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) {
irq_set_chip_data(irq, pct);
irq_set_chip_and_handler(irq, &abx500_gpio_irq_chip,
handle_simple_irq);
irq_set_nested_thread(irq, 1);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
irq_set_noprobe(irq);
#endif
}

return 0;
}

static void abx500_gpio_irq_remove(struct abx500_pinctrl *pct)
{
int base = pct->irq_base;
int irq;

for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) {
#ifdef CONFIG_ARM
set_irq_flags(irq, 0);
#endif
irq_set_chip_and_handler(irq, NULL, NULL);
irq_set_chip_data(irq, NULL);
}
}

static int abx500_pmx_get_funcs_cnt(struct pinctrl_dev *pctldev)
{
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
Expand Down Expand Up @@ -815,43 +568,6 @@ static int abx500_pmx_get_func_groups(struct pinctrl_dev *pctldev,
return 0;
}

static void abx500_disable_lazy_irq(struct gpio_chip *chip, unsigned gpio)
{
struct abx500_pinctrl *pct = to_abx500_pinctrl(chip);
int irq;
int offset;
bool rising;
bool falling;

/*
* check if gpio has interrupt capability and convert
* gpio number to irq
* On ABx5xx, there is no GPIO0, GPIO1 is the
* first one, so adjust gpio number
*/
gpio--;
irq = gpio_to_irq(gpio + chip->base);
if (irq < 0)
return;

offset = irq - pct->irq_base;
rising = pct->rising & BIT(offset);
falling = pct->falling & BIT(offset);

/* nothing to do ?*/
if (!rising && !falling)
return;

if (rising) {
disable_irq(irq_to_rising(irq));
free_irq(irq_to_rising(irq), pct);
}
if (falling) {
disable_irq(irq_to_falling(irq));
free_irq(irq_to_falling(irq), pct);
}
}

static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
unsigned group)
{
Expand All @@ -871,7 +587,6 @@ static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function,
dev_dbg(pct->dev, "setting pin %d to altsetting %d\n",
g->pins[i], g->altsetting);

abx500_disable_lazy_irq(chip, g->pins[i]);
ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting);
}

Expand Down Expand Up @@ -1197,18 +912,12 @@ static int abx500_gpio_probe(struct platform_device *pdev)
pct->chip.ngpio = abx500_get_gpio_num(pct->soc);
pct->irq_cluster = pct->soc->gpio_irq_cluster;
pct->irq_cluster_size = pct->soc->ngpio_irq_cluster;
pct->irq_gpio_rising_offset = pct->soc->irq_gpio_rising_offset;
pct->irq_gpio_falling_offset = pct->soc->irq_gpio_falling_offset;
pct->irq_gpio_factor = pct->soc->irq_gpio_factor;

ret = abx500_gpio_irq_init(pct);
if (ret)
goto out_free;
ret = gpiochip_add(&pct->chip);
if (ret) {
dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret);
mutex_destroy(&pct->lock);
goto out_rem_irq;
return ret;
}
dev_info(&pdev->dev, "added gpiochip\n");

Expand Down Expand Up @@ -1243,9 +952,7 @@ static int abx500_gpio_probe(struct platform_device *pdev)
err = gpiochip_remove(&pct->chip);
if (err)
dev_info(&pdev->dev, "failed to remove gpiochip\n");
out_rem_irq:
abx500_gpio_irq_remove(pct);
out_free:

mutex_destroy(&pct->lock);
return ret;
}
Expand Down

0 comments on commit 7811ac4

Please sign in to comment.