Commit 86e3ef81 authored by Cristina Ciocan's avatar Cristina Ciocan Committed by Linus Walleij

pinctrl: baytrail: Update gpio chip operations

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: default avatarCristina Ciocan <cristina.ciocan@intel.com>
Acked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent c501d0b1
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -1363,44 +1364,45 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ...@@ -1363,44 +1364,45 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
unsigned long flags; unsigned long flags;
u32 old_val; u32 old_val;
raw_spin_lock_irqsave(&vg->lock, flags); if (!reg)
return;
raw_spin_lock_irqsave(&vg->lock, flags);
old_val = readl(reg); old_val = readl(reg);
if (value) if (value)
writel(old_val | BYT_LEVEL, reg); writel(old_val | BYT_LEVEL, reg);
else else
writel(old_val & ~BYT_LEVEL, reg); writel(old_val & ~BYT_LEVEL, reg);
raw_spin_unlock_irqrestore(&vg->lock, flags); 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); struct byt_gpio *vg = gpiochip_get_data(chip);
void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); void __iomem *reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
unsigned long flags; unsigned long flags;
u32 value; u32 value;
raw_spin_lock_irqsave(&vg->lock, flags); if (!reg)
return -EINVAL;
value = readl(reg) | BYT_DIR_MASK;
value &= ~BYT_INPUT_EN; /* active low */
writel(value, reg);
raw_spin_lock_irqsave(&vg->lock, flags);
value = readl(reg);
raw_spin_unlock_irqrestore(&vg->lock, flags); 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, static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
unsigned gpio, int value)
{ {
struct byt_gpio *vg = gpiochip_get_data(chip); struct byt_gpio *vg = gpiochip_get_data(chip);
void __iomem *conf_reg = byt_gpio_reg(vg, gpio, BYT_CONF0_REG); void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
void __iomem *reg = byt_gpio_reg(vg, gpio, BYT_VAL_REG);
unsigned long flags; unsigned long flags;
u32 reg_val;
raw_spin_lock_irqsave(&vg->lock, flags); raw_spin_lock_irqsave(&vg->lock, flags);
...@@ -1413,15 +1415,18 @@ static int byt_gpio_direction_output(struct gpio_chip *chip, ...@@ -1413,15 +1415,18 @@ static int byt_gpio_direction_output(struct gpio_chip *chip,
WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
"Potential Error: Setting GPIO with direct_irq_en to output"); "Potential Error: Setting GPIO with direct_irq_en to output");
reg_val = readl(reg) | BYT_DIR_MASK; return pinctrl_gpio_direction_input(chip->base + offset);
reg_val &= ~(BYT_OUTPUT_EN | BYT_INPUT_EN); }
if (value) static int byt_gpio_direction_output(struct gpio_chip *chip,
writel(reg_val | BYT_LEVEL, reg); unsigned int offset, int value)
else {
writel(reg_val & ~BYT_LEVEL, reg); 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; return 0;
} }
...@@ -1430,20 +1435,42 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -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); struct byt_gpio *vg = gpiochip_get_data(chip);
int i; 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_str = NULL;
const char *pull = NULL; const char *pull = NULL;
void __iomem *reg;
unsigned long flags; unsigned long flags;
const char *label; const char *label;
offs = vg->range->pins[i] * 16; unsigned int pin;
raw_spin_lock_irqsave(&vg->lock, flags); raw_spin_lock_irqsave(&vg->lock, flags);
conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); pin = vg->soc_data->pins[i].number;
val = readl(vg->reg_base + offs + BYT_VAL_REG); 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); 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); label = gpiochip_is_requested(chip, i);
if (!label) if (!label)
label = "Unrequested"; label = "Unrequested";
...@@ -1474,12 +1501,12 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) ...@@ -1474,12 +1501,12 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_printf(s, seq_printf(s,
" gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s", " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
i, pin,
label, label,
val & BYT_INPUT_EN ? " " : "in", val & BYT_INPUT_EN ? " " : "in",
val & BYT_OUTPUT_EN ? " " : "out", val & BYT_OUTPUT_EN ? " " : "out",
val & BYT_LEVEL ? "hi" : "lo", val & BYT_LEVEL ? "hi" : "lo",
vg->range->pins[i], offs, comm->pad_map[i], comm->pad_map[i] * 32,
conf0 & 0x7, conf0 & 0x7,
conf0 & BYT_TRIG_NEG ? " fall" : " ", conf0 & BYT_TRIG_NEG ? " fall" : " ",
conf0 & BYT_TRIG_POS ? " rise" : " ", conf0 & BYT_TRIG_POS ? " rise" : " ",
...@@ -1519,6 +1546,18 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) ...@@ -1519,6 +1546,18 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
chip->irq_eoi(data); 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) static void byt_irq_ack(struct irq_data *d)
{ {
struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment