Skip to content

Commit

Permalink
pinctrl: baytrail: Update gpio chip operations
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Cristina Ciocan authored and Linus Walleij committed Apr 4, 2016
1 parent c501d0b commit 86e3ef8
Showing 1 changed file with 68 additions and 29 deletions.
97 changes: 68 additions & 29 deletions drivers/pinctrl/intel/pinctrl-baytrail.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);

Expand All @@ -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;
}
Expand All @@ -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";
Expand Down Expand Up @@ -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" : " ",
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 86e3ef8

Please sign in to comment.