mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-30 13:38:40 +00:00
6ea6b7faf0
As we want gpio_chip .get() calls to be able to return negative error codes and propagate to drivers, we need to go over all drivers and make sure their return values are clamped to [0,1]. We do this by using the ret = !!(val) design pattern. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Cc: linux-mips@linux-mips.org Cc: linux-gpio@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11923/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
90 lines
2.2 KiB
C
90 lines
2.2 KiB
C
/*
|
|
* A gpio chip driver for TXx9 SoCs
|
|
*
|
|
* Copyright (C) 2008 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/io.h>
|
|
#include <asm/txx9pio.h>
|
|
|
|
static DEFINE_SPINLOCK(txx9_gpio_lock);
|
|
|
|
static struct txx9_pio_reg __iomem *txx9_pioptr;
|
|
|
|
static int txx9_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
|
{
|
|
return !!(__raw_readl(&txx9_pioptr->din) & (1 << offset));
|
|
}
|
|
|
|
static void txx9_gpio_set_raw(unsigned int offset, int value)
|
|
{
|
|
u32 val;
|
|
val = __raw_readl(&txx9_pioptr->dout);
|
|
if (value)
|
|
val |= 1 << offset;
|
|
else
|
|
val &= ~(1 << offset);
|
|
__raw_writel(val, &txx9_pioptr->dout);
|
|
}
|
|
|
|
static void txx9_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
|
int value)
|
|
{
|
|
unsigned long flags;
|
|
spin_lock_irqsave(&txx9_gpio_lock, flags);
|
|
txx9_gpio_set_raw(offset, value);
|
|
mmiowb();
|
|
spin_unlock_irqrestore(&txx9_gpio_lock, flags);
|
|
}
|
|
|
|
static int txx9_gpio_dir_in(struct gpio_chip *chip, unsigned int offset)
|
|
{
|
|
unsigned long flags;
|
|
spin_lock_irqsave(&txx9_gpio_lock, flags);
|
|
__raw_writel(__raw_readl(&txx9_pioptr->dir) & ~(1 << offset),
|
|
&txx9_pioptr->dir);
|
|
mmiowb();
|
|
spin_unlock_irqrestore(&txx9_gpio_lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
static int txx9_gpio_dir_out(struct gpio_chip *chip, unsigned int offset,
|
|
int value)
|
|
{
|
|
unsigned long flags;
|
|
spin_lock_irqsave(&txx9_gpio_lock, flags);
|
|
txx9_gpio_set_raw(offset, value);
|
|
__raw_writel(__raw_readl(&txx9_pioptr->dir) | (1 << offset),
|
|
&txx9_pioptr->dir);
|
|
mmiowb();
|
|
spin_unlock_irqrestore(&txx9_gpio_lock, flags);
|
|
return 0;
|
|
}
|
|
|
|
static struct gpio_chip txx9_gpio_chip = {
|
|
.get = txx9_gpio_get,
|
|
.set = txx9_gpio_set,
|
|
.direction_input = txx9_gpio_dir_in,
|
|
.direction_output = txx9_gpio_dir_out,
|
|
.label = "TXx9",
|
|
};
|
|
|
|
int __init txx9_gpio_init(unsigned long baseaddr,
|
|
unsigned int base, unsigned int num)
|
|
{
|
|
txx9_pioptr = ioremap(baseaddr, sizeof(struct txx9_pio_reg));
|
|
if (!txx9_pioptr)
|
|
return -ENODEV;
|
|
txx9_gpio_chip.base = base;
|
|
txx9_gpio_chip.ngpio = num;
|
|
return gpiochip_add(&txx9_gpio_chip);
|
|
}
|