aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pinctrl/intel/pinctrl-intel.c
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2020-06-12 17:50:00 +0300
committerAndy Shevchenko <andriy.shevchenko@linux.intel.com>2020-06-22 10:58:52 +0300
commite64fbfa51e8fc4eeca2d2bbf0d31a30a15734229 (patch)
tree519b11cafe2340cb8f9bcca67e600dfd3f297478 /drivers/pinctrl/intel/pinctrl-intel.c
parentpinctrl: intel: Split intel_config_get() to three functions (diff)
downloadlinux-dev-e64fbfa51e8fc4eeca2d2bbf0d31a30a15734229.tar.xz
linux-dev-e64fbfa51e8fc4eeca2d2bbf0d31a30a15734229.zip
pinctrl: intel: Protect IO in few call backs by lock
Protect IO in intel_gpio_get_direction(), intel_gpio_community_irq_handler(), intel_config_get_debounce() and intel_config_get_pull() by lock. Even for simple readl() we better serialize IO to avoid potential problems. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/pinctrl/intel/pinctrl-intel.c')
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index d6ef012f2cc4..35c88fcb75a2 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -526,11 +526,15 @@ static int intel_config_get_pull(struct intel_pinctrl *pctrl, unsigned int pin,
{
const struct intel_community *community;
void __iomem *padcfg1;
+ unsigned long flags;
u32 value, term;
community = intel_get_community(pctrl, pin);
padcfg1 = intel_get_padcfg(pctrl, pin, PADCFG1);
+
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
value = readl(padcfg1);
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
term = (value & PADCFG1_TERM_MASK) >> PADCFG1_TERM_SHIFT;
@@ -592,6 +596,7 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p
enum pin_config_param param, u32 *arg)
{
void __iomem *padcfg2;
+ unsigned long flags;
unsigned long v;
u32 value2;
@@ -599,7 +604,9 @@ static int intel_config_get_debounce(struct intel_pinctrl *pctrl, unsigned int p
if (!padcfg2)
return -ENOTSUPP;
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
value2 = readl(padcfg2);
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
if (!(value2 & PADCFG2_DEBEN))
return -EINVAL;
@@ -934,6 +941,7 @@ static void intel_gpio_set(struct gpio_chip *chip, unsigned int offset,
static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
+ unsigned long flags;
void __iomem *reg;
u32 padcfg0;
int pin;
@@ -946,8 +954,9 @@ static int intel_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
if (!reg)
return -EINVAL;
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
padcfg0 = readl(reg);
-
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
if (padcfg0 & PADCFG0_PMODE_MASK)
return -EINVAL;
@@ -1134,12 +1143,17 @@ static int intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
for (gpp = 0; gpp < community->ngpps; gpp++) {
const struct intel_padgroup *padgrp = &community->gpps[gpp];
unsigned long pending, enabled, gpp_offset;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&pctrl->lock, flags);
pending = readl(community->regs + community->is_offset +
padgrp->reg_num * 4);
enabled = readl(community->regs + community->ie_offset +
padgrp->reg_num * 4);
+ raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
/* Only interrupts that are enabled */
pending &= enabled;