Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 363005
b: refs/heads/master
c: 1984695
h: refs/heads/master
i:
  363003: 04908e5
v: v3
  • Loading branch information
Tomasz Figa authored and Linus Walleij committed Apr 9, 2013
1 parent b722212 commit 381fbe3
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6a7b3e970426f4bc2a8d52f81a4fda6595a9f052
refs/heads/master: 198469504ac77ee04fe0f185bd668e1909aaba5f
11 changes: 11 additions & 0 deletions trunk/drivers/pinctrl/pinctrl-exynos.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/of_irq.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/err.h>

#include <asm/mach/irq.h>
Expand Down Expand Up @@ -81,6 +82,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
unsigned int con, trig_type;
unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
unsigned long flags;
unsigned int mask;

switch (type) {
Expand Down Expand Up @@ -118,11 +120,15 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
shift = pin * bank->func_width;
mask = (1 << bank->func_width) - 1;

spin_lock_irqsave(&bank->slock, flags);

con = readl(d->virt_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_EINT_FUNC << shift;
writel(con, d->virt_base + reg_con);

spin_unlock_irqrestore(&bank->slock, flags);

return 0;
}

Expand Down Expand Up @@ -258,6 +264,7 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
unsigned long con, trig_type;
unsigned long flags;
unsigned int mask;

switch (type) {
Expand Down Expand Up @@ -295,11 +302,15 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
shift = pin * bank->func_width;
mask = (1 << bank->func_width) - 1;

spin_lock_irqsave(&bank->slock, flags);

con = readl(d->virt_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_EINT_FUNC << shift;
writel(con, d->virt_base + reg_con);

spin_unlock_irqrestore(&bank->slock, flags);

return 0;
}

Expand Down
24 changes: 24 additions & 0 deletions trunk/drivers/pinctrl/pinctrl-samsung.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/irqdomain.h>
#include <linux/spinlock.h>

#include "core.h"
#include "pinctrl-samsung.h"
Expand Down Expand Up @@ -289,6 +290,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
struct samsung_pin_bank *bank;
void __iomem *reg;
u32 mask, shift, data, pin_offset, cnt;
unsigned long flags;

drvdata = pinctrl_dev_get_drvdata(pctldev);
pins = drvdata->pin_groups[group].pins;
Expand All @@ -303,11 +305,15 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector,
mask = (1 << bank->func_width) - 1;
shift = pin_offset * bank->func_width;

spin_lock_irqsave(&bank->slock, flags);

data = readl(reg);
data &= ~(mask << shift);
if (enable)
data |= drvdata->pin_groups[group].func << shift;
writel(data, reg);

spin_unlock_irqrestore(&bank->slock, flags);
}
}

Expand Down Expand Up @@ -338,6 +344,7 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
struct samsung_pinctrl_drv_data *drvdata;
void __iomem *reg;
u32 data, pin_offset, mask, shift;
unsigned long flags;

bank = gc_to_pin_bank(range->gc);
drvdata = pinctrl_dev_get_drvdata(pctldev);
Expand All @@ -348,11 +355,16 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
mask = (1 << bank->func_width) - 1;
shift = pin_offset * bank->func_width;

spin_lock_irqsave(&bank->slock, flags);

data = readl(reg);
data &= ~(mask << shift);
if (!input)
data |= FUNC_OUTPUT << shift;
writel(data, reg);

spin_unlock_irqrestore(&bank->slock, flags);

return 0;
}

Expand All @@ -376,6 +388,7 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
u32 data, width, pin_offset, mask, shift;
u32 cfg_value, cfg_reg;
unsigned long flags;

drvdata = pinctrl_dev_get_drvdata(pctldev);
pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, &reg_base,
Expand Down Expand Up @@ -406,6 +419,8 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
if (!width)
return -EINVAL;

spin_lock_irqsave(&bank->slock, flags);

mask = (1 << width) - 1;
shift = pin_offset * width;
data = readl(reg_base + cfg_reg);
Expand All @@ -420,6 +435,9 @@ static int samsung_pinconf_rw(struct pinctrl_dev *pctldev, unsigned int pin,
data &= mask;
*config = PINCFG_PACK(cfg_type, data);
}

spin_unlock_irqrestore(&bank->slock, flags);

return 0;
}

Expand Down Expand Up @@ -479,16 +497,21 @@ static const struct pinconf_ops samsung_pinconf_ops = {
static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
{
struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
unsigned long flags;
void __iomem *reg;
u32 data;

reg = bank->drvdata->virt_base + bank->pctl_offset;

spin_lock_irqsave(&bank->slock, flags);

data = readl(reg + DAT_REG);
data &= ~(1 << offset);
if (value)
data |= 1 << offset;
writel(data, reg + DAT_REG);

spin_unlock_irqrestore(&bank->slock, flags);
}

/* gpiolib gpio_get callback function */
Expand Down Expand Up @@ -859,6 +882,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(

bank = ctrl->pin_banks;
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
spin_lock_init(&bank->slock);
bank->drvdata = d;
bank->pin_base = ctrl->nr_pins;
ctrl->nr_pins += bank->nr_pins;
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/pinctrl/pinctrl-samsung.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ struct samsung_pinctrl_drv_data;
* @irq_domain: IRQ domain of the bank.
* @gpio_chip: GPIO chip of the bank.
* @grange: linux gpio pin range supported by this bank.
* @slock: spinlock protecting bank registers
*/
struct samsung_pin_bank {
u32 pctl_offset;
Expand All @@ -137,6 +138,7 @@ struct samsung_pin_bank {
struct irq_domain *irq_domain;
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range grange;
spinlock_t slock;
};

/**
Expand Down

0 comments on commit 381fbe3

Please sign in to comment.