pinctrl: baytrail: Update gpio chip operations
authorCristina Ciocan <cristina.ciocan@intel.com>
Fri, 1 Apr 2016 11:00:04 +0000 (14:00 +0300)
committerLinus Walleij <linus.walleij@linaro.org>
Mon, 4 Apr 2016 14:02:19 +0000 (16:02 +0200)
This patch updates the gpio chip implementation in order
to interact with the pin control model: the chip contains
reference to SOC data and pin/group/community information
is retrieved through the SOC reference.

Signed-off-by: Cristina Ciocan <cristina.ciocan@intel.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
drivers/pinctrl/intel/pinctrl-baytrail.c

index 415d2d5554b54a2ebdcbc1dd3b3e4f562b160040..a24b51e47f00e00cab6ee9352adf6a383ac53148 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
+#include <linux/gpio.h>
 #include <linux/gpio/driver.h>
 #include <linux/acpi.h>
 #include <linux/platform_device.h>
@@ -1363,44 +1364,45 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        unsigned long flags;
        u32 old_val;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       if (!reg)
+               return;
 
+       raw_spin_lock_irqsave(&vg->lock, flags);
        old_val = readl(reg);
-
        if (value)
                writel(old_val | BYT_LEVEL, reg);
        else
                writel(old_val & ~BYT_LEVEL, reg);
-
        raw_spin_unlock_irqrestore(&vg->lock, flags);
 }
 
-static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
 {
        struct byt_gpio *vg = gpiochip_get_data(chip);
        void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
        unsigned long flags;
        u32 value;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
-
-       value = readl(reg) | BYT_DIR_MASK;
-       value &= ~BYT_INPUT_EN;         /* active low */
-       writel(value, reg);
+       if (!reg)
+               return -EINVAL;
 
+       raw_spin_lock_irqsave(&vg->lock, flags);
+       value = readl(reg);
        raw_spin_unlock_irqrestore(&vg->lock, flags);
 
-       return 0;
+       if (!(value & BYT_OUTPUT_EN))
+               return GPIOF_DIR_OUT;
+       if (!(value & BYT_INPUT_EN))
+               return GPIOF_DIR_IN;
+
+       return -EINVAL;
 }
 
-static int byt_gpio_direction_output(struct gpio_chip *chip,
-                                    unsigned gpio, int value)
+static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
 {
        struct byt_gpio *vg = gpiochip_get_data(chip);
-       void __iomem *conf_reg = byt_gpio_reg(vg, gpio, BYT_CONF0_REG);
-       void __iomem *reg = byt_gpio_reg(vg, gpio, BYT_VAL_REG);
+       void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
        unsigned long flags;
-       u32 reg_val;
 
        raw_spin_lock_irqsave(&vg->lock, flags);
 
@@ -1413,15 +1415,18 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
        WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
                "Potential Error: Setting GPIO with direct_irq_en to output");
 
-       reg_val = readl(reg) | BYT_DIR_MASK;
-       reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN);
+       return pinctrl_gpio_direction_input(chip->base + offset);
+}
 
-       if (value)
-               writel(reg_val | BYT_LEVEL, reg);
-       else
-               writel(reg_val & ~BYT_LEVEL, reg);
+static int byt_gpio_direction_output(struct gpio_chip *chip,
+                                    unsigned int offset, int value)
+{
+       int ret = pinctrl_gpio_direction_output(chip->base + offset);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       if (ret)
+               return ret;
+
+       byt_gpio_set(chip, offset, value);
 
        return 0;
 }
@@ -1430,20 +1435,42 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
        struct byt_gpio *vg = gpiochip_get_data(chip);
        int i;
-       u32 conf0, val, offs;
+       u32 conf0, val;
 
-       for (i = 0; i < vg->chip.ngpio; i++) {
+       for (i = 0; i < vg->soc_data->npins; i++) {
+               const struct byt_community *comm;
                const char *pull_str = NULL;
                const char *pull = NULL;
+               void __iomem *reg;
                unsigned long flags;
                const char *label;
-               offs = vg->range->pins[i] * 16;
+               unsigned int pin;
 
                raw_spin_lock_irqsave(&vg->lock, flags);
-               conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
-               val = readl(vg->reg_base + offs + BYT_VAL_REG);
+               pin = vg->soc_data->pins[i].number;
+               reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+               if (!reg) {
+                       seq_printf(s,
+                                  "Could not retrieve pin %i conf0 reg\n",
+                                  pin);
+                       continue;
+               }
+               conf0 = readl(reg);
+
+               reg = byt_gpio_reg(vg, pin, BYT_VAL_REG);
+               if (!reg) {
+                       seq_printf(s,
+                                  "Could not retrieve pin %i val reg\n", pin);
+               }
+               val = readl(reg);
                raw_spin_unlock_irqrestore(&vg->lock, flags);
 
+               comm = byt_get_community(vg, pin);
+               if (!comm) {
+                       seq_printf(s,
+                                  "Could not get community for pin %i\n", pin);
+                       continue;
+               }
                label = gpiochip_is_requested(chip, i);
                if (!label)
                        label = "Unrequested";
@@ -1474,12 +1501,12 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 
                seq_printf(s,
                           " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
-                          i,
+                          pin,
                           label,
                           val & BYT_INPUT_EN ? "  " : "in",
                           val & BYT_OUTPUT_EN ? "   " : "out",
                           val & BYT_LEVEL ? "hi" : "lo",
-                          vg->range->pins[i], offs,
+                          comm->pad_map[i], comm->pad_map[i] * 32,
                           conf0 & 0x7,
                           conf0 & BYT_TRIG_NEG ? " fall" : "     ",
                           conf0 & BYT_TRIG_POS ? " rise" : "     ",
@@ -1519,6 +1546,18 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
        chip->irq_eoi(data);
 }
 
+static const struct gpio_chip byt_gpio_chip = {
+       .owner                  = THIS_MODULE,
+       .request                = gpiochip_generic_request,
+       .free                   = gpiochip_generic_free,
+       .get_direction          = byt_gpio_get_direction,
+       .direction_input        = byt_gpio_direction_input,
+       .direction_output       = byt_gpio_direction_output,
+       .get                    = byt_gpio_get,
+       .set                    = byt_gpio_set,
+       .dbg_show               = byt_gpio_dbg_show,
+};
+
 static void byt_irq_ack(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);