#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>
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) {
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;
}
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) {
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;
}
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/irqdomain.h>
+#include <linux/spinlock.h>
#include "core.h"
#include "pinctrl-samsung.h"
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;
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);
}
}
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);
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;
}
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, ®_base,
if (!width)
return -EINVAL;
+ spin_lock_irqsave(&bank->slock, flags);
+
mask = (1 << width) - 1;
shift = pin_offset * width;
data = readl(reg_base + cfg_reg);
data &= mask;
*config = PINCFG_PACK(cfg_type, data);
}
+
+ spin_unlock_irqrestore(&bank->slock, flags);
+
return 0;
}
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 */
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;