drivers/gpio/gpio-loongson.c

Source file repositories/reference/linux-study-clean/drivers/gpio/gpio-loongson.c

File Facts

System
Linux kernel
Corpus path
drivers/gpio/gpio-loongson.c
Extension
.c
Size
3051 bytes
Lines
138
Domain
Driver Families
Bucket
drivers/gpio
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Loongson-2F/3A/3B GPIO Support
 *
 *  Copyright (c) 2008 Richard Liu,  STMicroelectronics	 <richard.liu@st.com>
 *  Copyright (c) 2008-2010 Arnaud Patard <apatard@mandriva.com>
 *  Copyright (c) 2013 Hongbing Hu <huhb@lemote.com>
 *  Copyright (c) 2014 Huacai Chen <chenhc@lemote.com>
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <asm/types.h>
#include <loongson.h>

#define STLS2F_N_GPIO		4
#define STLS3A_N_GPIO		16

#ifdef CONFIG_CPU_LOONGSON64
#define LOONGSON_N_GPIO	STLS3A_N_GPIO
#else
#define LOONGSON_N_GPIO	STLS2F_N_GPIO
#endif

/*
 * Offset into the register where we read lines, we write them from offset 0.
 * This offset is the only thing that stand between us and using
 * GPIO_GENERIC.
 */
#define LOONGSON_GPIO_IN_OFFSET	16

static DEFINE_SPINLOCK(gpio_lock);

static int loongson_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
{
	u32 val;

	spin_lock(&gpio_lock);
	val = LOONGSON_GPIODATA;
	spin_unlock(&gpio_lock);

	return !!(val & BIT(gpio + LOONGSON_GPIO_IN_OFFSET));
}

static int loongson_gpio_set_value(struct gpio_chip *chip, unsigned int gpio,
				   int value)
{
	u32 val;

	spin_lock(&gpio_lock);
	val = LOONGSON_GPIODATA;
	if (value)
		val |= BIT(gpio);
	else
		val &= ~BIT(gpio);
	LOONGSON_GPIODATA = val;
	spin_unlock(&gpio_lock);

	return 0;
}

static int loongson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
{
	u32 temp;

	spin_lock(&gpio_lock);
	temp = LOONGSON_GPIOIE;
	temp |= BIT(gpio);
	LOONGSON_GPIOIE = temp;
	spin_unlock(&gpio_lock);

	return 0;
}

static int loongson_gpio_direction_output(struct gpio_chip *chip,
		unsigned gpio, int level)
{
	u32 temp;

	loongson_gpio_set_value(chip, gpio, level);
	spin_lock(&gpio_lock);
	temp = LOONGSON_GPIOIE;
	temp &= ~BIT(gpio);
	LOONGSON_GPIOIE = temp;

Annotation

Implementation Notes