#include <linux/gpio/driver.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
  * @irq:       interrupt for the GPIO device
  * @p_data:    pointer to platform data
  * @context:   context registers
+ * @dirlock:   lock used for direction in/out synchronization
  */
 struct zynq_gpio {
        struct gpio_chip chip;
        int irq;
        const struct zynq_platform_data *p_data;
        struct gpio_regs context;
+       spinlock_t dirlock; /* lock */
 };
 
 /**
 {
        u32 reg;
        unsigned int bank_num, bank_pin_num;
+       unsigned long flags;
        struct zynq_gpio *gpio = gpiochip_get_data(chip);
 
        zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
                return -EINVAL;
 
        /* clear the bit in direction mode reg to set the pin as input */
+       spin_lock_irqsave(&gpio->dirlock, flags);
        reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
        reg &= ~BIT(bank_pin_num);
        writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+       spin_unlock_irqrestore(&gpio->dirlock, flags);
 
        return 0;
 }
 {
        u32 reg;
        unsigned int bank_num, bank_pin_num;
+       unsigned long flags;
        struct zynq_gpio *gpio = gpiochip_get_data(chip);
 
        zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
 
        /* set the GPIO pin as output */
+       spin_lock_irqsave(&gpio->dirlock, flags);
        reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
        reg |= BIT(bank_pin_num);
        writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
        reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
        reg |= BIT(bank_pin_num);
        writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+       spin_unlock_irqrestore(&gpio->dirlock, flags);
 
        /* set the state of the pin */
        zynq_gpio_set_value(chip, pin, state);
                return ret;
        }
 
+       spin_lock_init(&gpio->dirlock);
+
        pm_runtime_set_active(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
        ret = pm_runtime_get_sync(&pdev->dev);