// SPDX-License-Identifier: GPL-2.0-only
/*
* GPIO driver for AMD
*
* Copyright (c) 2014,2015 AMD Corporation.
* Authors: Ken Xue <Ken.Xue@amd.com>
* Wu, Jeff <Jeff.Wu@amd.com>
*
*/
#include <linux/err.h>
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/log2.h>
#include <linux/io.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/acpi.h>
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/bitops.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/suspend.h>
#include "core.h"
#include "pinctrl-utils.h"
#include "pinctrl-amd.h"
static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
{
unsigned long flags;
u32 pin_reg;
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + offset * 4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
if (pin_reg & BIT(OUTPUT_ENABLE_OFF))
return GPIO_LINE_DIRECTION_OUT;
return GPIO_LINE_DIRECTION_IN;
}
static int amd_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
{
unsigned long flags;
u32 pin_reg;
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + offset * 4);
pin_reg &= ~BIT(OUTPUT_ENABLE_OFF);
writel(pin_reg, gpio_dev->base + offset * 4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
return 0;
}
static int amd_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
int value)
{
u32 pin_reg;
unsigned long flags;
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + offset * 4);
pin_reg |= BIT(OUTPUT_ENABLE_OFF);
if (value)
pin_reg |= BIT(OUTPUT_VALUE_OFF);
else
pin_reg &= ~BIT(OUTPUT_VALUE_OFF);
writel(pin_reg, gpio_dev->base + offset * 4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
return 0;
}
static int amd_gpio_get_value(struct gpio_chip *gc, unsigned offset)
{
u32 pin_reg;
unsigned long flags;
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + offset * 4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
return !!(pin_reg & BIT(PIN_STS_OFF));
}
static void amd_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
{
u32 pin_reg;
unsigned long flags;
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + offset * 4);
if (value)
pin_reg |= BIT(OUTPUT_VALUE_OFF);
else
pin_reg &= ~BIT(OUTPUT_VALUE_OFF);
writel(pin_reg, gpio_dev->base + offset * 4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}
static