mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-13 15:56:37 +07:00
Merge branch 'devel' into for-next
This commit is contained in:
commit
4672a4a9fb
@ -19,6 +19,7 @@ Required properties:
|
||||
nxp,pca9698
|
||||
nxp,pcal6416
|
||||
nxp,pcal6524
|
||||
nxp,pcal9535
|
||||
nxp,pcal9555a
|
||||
maxim,max7310
|
||||
maxim,max7312
|
||||
|
@ -6,7 +6,9 @@ Required properties:
|
||||
- First cell is the GPIO line number
|
||||
- Second cell is used to specify optional
|
||||
parameters (unused)
|
||||
- compatible : Should be "xlnx,zynq-gpio-1.0" or "xlnx,zynqmp-gpio-1.0"
|
||||
- compatible : Should be "xlnx,zynq-gpio-1.0" or
|
||||
"xlnx,zynqmp-gpio-1.0" or "xlnx,versal-gpio-1.0
|
||||
or "xlnx,pmc-gpio-1.0
|
||||
- clocks : Clock specifier (see clock bindings for details)
|
||||
- gpio-controller : Marks the device node as a GPIO controller.
|
||||
- interrupts : Interrupt specifier (see interrupt bindings for
|
||||
|
@ -89,6 +89,13 @@ hardware descriptions such as device tree or ACPI:
|
||||
Consumer Electronics Control bus using only GPIO. It is used to communicate
|
||||
with devices on the HDMI bus.
|
||||
|
||||
- gpio-charger: drivers/power/supply/gpio-charger.c is used if you need to do
|
||||
battery charging and all you have to go by to check the presence of the
|
||||
AC charger or more complex tasks such as indicating charging status using
|
||||
nothing but GPIO lines, this driver provides that and also a clearly defined
|
||||
way to pass the charging parameters from hardware descriptions such as the
|
||||
device tree.
|
||||
|
||||
Apart from this there are special GPIO drivers in subsystems like MMC/SD to
|
||||
read card detect and write protect GPIO lines, and in the TTY serial subsystem
|
||||
to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines. The
|
||||
|
@ -442,6 +442,7 @@ static void orion_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
|
||||
struct orion_gpio_chip *ochip = gpiochip_get_data(chip);
|
||||
u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
|
||||
const char *label;
|
||||
int i;
|
||||
|
||||
out = readl_relaxed(GPIO_OUT(ochip));
|
||||
@ -453,15 +454,10 @@ static void orion_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
edg_msk = readl_relaxed(GPIO_EDGE_MASK(ochip));
|
||||
lvl_msk = readl_relaxed(GPIO_LEVEL_MASK(ochip));
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
const char *label;
|
||||
for_each_requested_gpio(chip, i, label) {
|
||||
u32 msk;
|
||||
bool is_out;
|
||||
|
||||
label = gpiochip_is_requested(chip, i);
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
msk = 1 << i;
|
||||
is_out = !(io_conf & msk);
|
||||
|
||||
|
@ -410,7 +410,7 @@ config GPIO_MXS
|
||||
|
||||
config GPIO_OCTEON
|
||||
tristate "Cavium OCTEON GPIO"
|
||||
depends on GPIOLIB && CAVIUM_OCTEON_SOC
|
||||
depends on CAVIUM_OCTEON_SOC
|
||||
default y
|
||||
help
|
||||
Say yes here to support the on-chip GPIO lines on the OCTEON
|
||||
@ -1117,7 +1117,7 @@ config GPIO_DLN2
|
||||
|
||||
config HTC_EGPIO
|
||||
bool "HTC EGPIO support"
|
||||
depends on GPIOLIB && ARM
|
||||
depends on ARM
|
||||
help
|
||||
This driver supports the CPLD egpio chip present on
|
||||
several HTC phones. It provides basic support for input
|
||||
|
@ -7,6 +7,7 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-devres.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-cdev.o
|
||||
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
|
||||
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
|
||||
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
|
||||
|
@ -5,7 +5,7 @@ subsystem.
|
||||
GPIO descriptors
|
||||
|
||||
Starting with commit 79a9becda894 the GPIO subsystem embarked on a journey
|
||||
to move away from the global GPIO numberspace and toward a decriptor-based
|
||||
to move away from the global GPIO numberspace and toward a descriptor-based
|
||||
approach. This means that GPIO consumers, drivers and machine descriptions
|
||||
ideally have no use or idea of the global GPIO numberspace that has/was
|
||||
used in the inception of the GPIO subsystem.
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/gpio/machine.h>
|
||||
@ -38,9 +39,9 @@ static DEFINE_IDR(gpio_aggregator_idr);
|
||||
|
||||
static char *get_arg(char **args)
|
||||
{
|
||||
char *start = *args, *end;
|
||||
char *start, *end;
|
||||
|
||||
start = skip_spaces(start);
|
||||
start = skip_spaces(*args);
|
||||
if (!*start)
|
||||
return NULL;
|
||||
|
||||
@ -111,55 +112,45 @@ static int aggr_add_gpio(struct gpio_aggregator *aggr, const char *key,
|
||||
|
||||
static int aggr_parse(struct gpio_aggregator *aggr)
|
||||
{
|
||||
unsigned int first_index, last_index, i, n = 0;
|
||||
char *name, *offsets, *first, *last, *next;
|
||||
char *args = aggr->args;
|
||||
int error;
|
||||
unsigned long *bitmap;
|
||||
unsigned int i, n = 0;
|
||||
char *name, *offsets;
|
||||
int error = 0;
|
||||
|
||||
bitmap = bitmap_alloc(ARCH_NR_GPIOS, GFP_KERNEL);
|
||||
if (!bitmap)
|
||||
return -ENOMEM;
|
||||
|
||||
for (name = get_arg(&args), offsets = get_arg(&args); name;
|
||||
offsets = get_arg(&args)) {
|
||||
if (IS_ERR(name)) {
|
||||
pr_err("Cannot get GPIO specifier: %pe\n", name);
|
||||
return PTR_ERR(name);
|
||||
error = PTR_ERR(name);
|
||||
goto free_bitmap;
|
||||
}
|
||||
|
||||
if (!isrange(offsets)) {
|
||||
/* Named GPIO line */
|
||||
error = aggr_add_gpio(aggr, name, U16_MAX, &n);
|
||||
if (error)
|
||||
return error;
|
||||
goto free_bitmap;
|
||||
|
||||
name = offsets;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* GPIO chip + offset(s) */
|
||||
for (first = offsets; *first; first = next) {
|
||||
next = strchrnul(first, ',');
|
||||
if (*next)
|
||||
*next++ = '\0';
|
||||
error = bitmap_parselist(offsets, bitmap, ARCH_NR_GPIOS);
|
||||
if (error) {
|
||||
pr_err("Cannot parse %s: %d\n", offsets, error);
|
||||
goto free_bitmap;
|
||||
}
|
||||
|
||||
last = strchr(first, '-');
|
||||
if (last)
|
||||
*last++ = '\0';
|
||||
|
||||
if (kstrtouint(first, 10, &first_index)) {
|
||||
pr_err("Cannot parse GPIO index %s\n", first);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!last) {
|
||||
last_index = first_index;
|
||||
} else if (kstrtouint(last, 10, &last_index)) {
|
||||
pr_err("Cannot parse GPIO index %s\n", last);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = first_index; i <= last_index; i++) {
|
||||
error = aggr_add_gpio(aggr, name, i, &n);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
for_each_set_bit(i, bitmap, ARCH_NR_GPIOS) {
|
||||
error = aggr_add_gpio(aggr, name, i, &n);
|
||||
if (error)
|
||||
goto free_bitmap;
|
||||
}
|
||||
|
||||
name = get_arg(&args);
|
||||
@ -167,10 +158,12 @@ static int aggr_parse(struct gpio_aggregator *aggr)
|
||||
|
||||
if (!n) {
|
||||
pr_err("No GPIOs specified\n");
|
||||
return -EINVAL;
|
||||
error = -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
free_bitmap:
|
||||
bitmap_free(bitmap);
|
||||
return error;
|
||||
}
|
||||
|
||||
static ssize_t new_device_store(struct device_driver *driver, const char *buf,
|
||||
|
@ -24,6 +24,7 @@
|
||||
* @interrupt_trigger : specifies the hardware configured IRQ trigger type
|
||||
* (rising, falling, both, high)
|
||||
* @mapped_irq : kernel mapped irq number.
|
||||
* @irq_chip : IRQ chip configuration
|
||||
*/
|
||||
struct altera_gpio_chip {
|
||||
struct of_mm_gpio_chip mmchip;
|
||||
@ -69,7 +70,7 @@ static void altera_gpio_irq_mask(struct irq_data *d)
|
||||
raw_spin_unlock_irqrestore(&altera_gc->gpio_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* This controller's IRQ type is synthesized in hardware, so this function
|
||||
* just checks if the requested set_type matches the synthesized IRQ type
|
||||
*/
|
||||
|
@ -47,13 +47,13 @@
|
||||
|
||||
/**
|
||||
* struct it87_gpio - it87-specific GPIO chip
|
||||
* @chip the underlying gpio_chip structure
|
||||
* @lock a lock to avoid races between operations
|
||||
* @io_base base address for gpio ports
|
||||
* @io_size size of the port rage starting from io_base.
|
||||
* @output_base Super I/O register address for Output Enable register
|
||||
* @simple_base Super I/O 'Simple I/O' Enable register
|
||||
* @simple_size Super IO 'Simple I/O' Enable register size; this is
|
||||
* @chip: the underlying gpio_chip structure
|
||||
* @lock: a lock to avoid races between operations
|
||||
* @io_base: base address for gpio ports
|
||||
* @io_size: size of the port rage starting from io_base.
|
||||
* @output_base: Super I/O register address for Output Enable register
|
||||
* @simple_base: Super I/O 'Simple I/O' Enable register
|
||||
* @simple_size: Super IO 'Simple I/O' Enable register size; this is
|
||||
* required because IT87xx chips might only provide Simple I/O
|
||||
* switches on a subset of lines, whereas the others keep the
|
||||
* same status all time.
|
||||
|
@ -703,7 +703,7 @@ static int max732x_probe(struct i2c_client *client,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pdata && pdata->setup) {
|
||||
if (pdata->setup) {
|
||||
ret = pdata->setup(client, chip->gpio_chip.base,
|
||||
chip->gpio_chip.ngpio, pdata->context);
|
||||
if (ret < 0)
|
||||
|
@ -127,7 +127,7 @@ static int mlxbf_gpio_resume(struct platform_device *pdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct acpi_device_id mlxbf_gpio_acpi_match[] = {
|
||||
static const struct acpi_device_id __maybe_unused mlxbf_gpio_acpi_match[] = {
|
||||
{ "MLNXBF02", 0 },
|
||||
{}
|
||||
};
|
||||
|
@ -149,6 +149,8 @@ static int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs)
|
||||
* Release the YU arm_gpio_lock after changing the direction mode.
|
||||
*/
|
||||
static void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs)
|
||||
__releases(&gs->gc.bgpio_lock)
|
||||
__releases(yu_arm_gpio_lock_param.lock)
|
||||
{
|
||||
writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io);
|
||||
spin_unlock(&gs->gc.bgpio_lock);
|
||||
@ -309,7 +311,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct acpi_device_id mlxbf2_gpio_acpi_match[] = {
|
||||
static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = {
|
||||
{ "MLNXBF22", 0 },
|
||||
{},
|
||||
};
|
||||
|
@ -417,7 +417,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, mpc8xxx_gc->irqn,
|
||||
mpc8xxx_gpio_irq_cascade,
|
||||
IRQF_NO_THREAD | IRQF_SHARED, "gpio-cascade",
|
||||
IRQF_SHARED, "gpio-cascade",
|
||||
mpc8xxx_gc);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: failed to devm_request_irq(%d), ret = %d\n",
|
||||
|
@ -846,6 +846,7 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
struct mvebu_gpio_chip *mvchip = gpiochip_get_data(chip);
|
||||
u32 out, io_conf, blink, in_pol, data_in, cause, edg_msk, lvl_msk;
|
||||
const char *label;
|
||||
int i;
|
||||
|
||||
regmap_read(mvchip->regs, GPIO_OUT_OFF + mvchip->offset, &out);
|
||||
@ -857,15 +858,10 @@ static void mvebu_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
edg_msk = mvebu_gpio_read_edge_mask(mvchip);
|
||||
lvl_msk = mvebu_gpio_read_level_mask(mvchip);
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
const char *label;
|
||||
for_each_requested_gpio(chip, i, label) {
|
||||
u32 msk;
|
||||
bool is_out;
|
||||
|
||||
label = gpiochip_is_requested(chip, i);
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
msk = BIT(i);
|
||||
is_out = !(io_conf & msk);
|
||||
|
||||
|
@ -60,6 +60,7 @@ struct gpio_bank {
|
||||
struct clk *dbck;
|
||||
struct notifier_block nb;
|
||||
unsigned int is_suspended:1;
|
||||
unsigned int needs_resume:1;
|
||||
u32 mod_usage;
|
||||
u32 irq_usage;
|
||||
u32 dbck_enable_mask;
|
||||
@ -1504,9 +1505,34 @@ static int __maybe_unused omap_gpio_runtime_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap_gpio_suspend(struct device *dev)
|
||||
{
|
||||
struct gpio_bank *bank = dev_get_drvdata(dev);
|
||||
|
||||
if (bank->is_suspended)
|
||||
return 0;
|
||||
|
||||
bank->needs_resume = 1;
|
||||
|
||||
return omap_gpio_runtime_suspend(dev);
|
||||
}
|
||||
|
||||
static int omap_gpio_resume(struct device *dev)
|
||||
{
|
||||
struct gpio_bank *bank = dev_get_drvdata(dev);
|
||||
|
||||
if (!bank->needs_resume)
|
||||
return 0;
|
||||
|
||||
bank->needs_resume = 0;
|
||||
|
||||
return omap_gpio_runtime_resume(dev);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops gpio_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(omap_gpio_runtime_suspend, omap_gpio_runtime_resume,
|
||||
NULL)
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(omap_gpio_suspend, omap_gpio_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver omap_gpio_driver = {
|
||||
|
@ -89,6 +89,7 @@ static const struct i2c_device_id pca953x_id[] = {
|
||||
|
||||
{ "pcal6416", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
|
||||
{ "pcal6524", 24 | PCA953X_TYPE | PCA_LATCH_INT, },
|
||||
{ "pcal9535", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
|
||||
{ "pcal9555a", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
|
||||
|
||||
{ "max7310", 8 | PCA953X_TYPE, },
|
||||
@ -1234,6 +1235,7 @@ static const struct of_device_id pca953x_dt_ids[] = {
|
||||
|
||||
{ .compatible = "nxp,pcal6416", .data = OF_953X(16, PCA_LATCH_INT), },
|
||||
{ .compatible = "nxp,pcal6524", .data = OF_953X(24, PCA_LATCH_INT), },
|
||||
{ .compatible = "nxp,pcal9535", .data = OF_953X(16, PCA_LATCH_INT), },
|
||||
{ .compatible = "nxp,pcal9555a", .data = OF_953X(16, PCA_LATCH_INT), },
|
||||
|
||||
{ .compatible = "maxim,max7310", .data = OF_953X( 8, 0), },
|
||||
|
@ -48,7 +48,7 @@ enum {
|
||||
* struct sprd_pmic_eic - PMIC EIC controller
|
||||
* @chip: the gpio_chip structure.
|
||||
* @intc: the irq_chip structure.
|
||||
* @regmap: the regmap from the parent device.
|
||||
* @map: the regmap from the parent device.
|
||||
* @offset: the EIC controller's offset address of the PMIC.
|
||||
* @reg: the array to cache the EIC registers.
|
||||
* @buslock: for bus lock/sync and unlock.
|
||||
|
@ -49,7 +49,7 @@ struct sama5d2_piobu {
|
||||
struct regmap *regmap;
|
||||
};
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_setup_pin() - prepares a pin for set_direction call
|
||||
*
|
||||
* Do not consider pin for tamper detection (normal and backup modes)
|
||||
@ -73,7 +73,7 @@ static int sama5d2_piobu_setup_pin(struct gpio_chip *chip, unsigned int pin)
|
||||
return regmap_update_bits(piobu->regmap, PIOBU_WKPR, mask, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_write_value() - writes value & mask at the pin's PIOBU register
|
||||
*/
|
||||
static int sama5d2_piobu_write_value(struct gpio_chip *chip, unsigned int pin,
|
||||
@ -88,7 +88,7 @@ static int sama5d2_piobu_write_value(struct gpio_chip *chip, unsigned int pin,
|
||||
return regmap_update_bits(piobu->regmap, reg, mask, value);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_read_value() - read the value with masking from the pin's PIOBU
|
||||
* register
|
||||
*/
|
||||
@ -108,7 +108,7 @@ static int sama5d2_piobu_read_value(struct gpio_chip *chip, unsigned int pin,
|
||||
return val & mask;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_get_direction() - gpiochip get_direction
|
||||
*/
|
||||
static int sama5d2_piobu_get_direction(struct gpio_chip *chip,
|
||||
@ -123,7 +123,7 @@ static int sama5d2_piobu_get_direction(struct gpio_chip *chip,
|
||||
GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_direction_input() - gpiochip direction_input
|
||||
*/
|
||||
static int sama5d2_piobu_direction_input(struct gpio_chip *chip,
|
||||
@ -132,7 +132,7 @@ static int sama5d2_piobu_direction_input(struct gpio_chip *chip,
|
||||
return sama5d2_piobu_write_value(chip, pin, PIOBU_DIRECTION, PIOBU_IN);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_direction_output() - gpiochip direction_output
|
||||
*/
|
||||
static int sama5d2_piobu_direction_output(struct gpio_chip *chip,
|
||||
@ -147,7 +147,7 @@ static int sama5d2_piobu_direction_output(struct gpio_chip *chip,
|
||||
val);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_get() - gpiochip get
|
||||
*/
|
||||
static int sama5d2_piobu_get(struct gpio_chip *chip, unsigned int pin)
|
||||
@ -166,7 +166,7 @@ static int sama5d2_piobu_get(struct gpio_chip *chip, unsigned int pin)
|
||||
return !!ret;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* sama5d2_piobu_set() - gpiochip set
|
||||
*/
|
||||
static void sama5d2_piobu_set(struct gpio_chip *chip, unsigned int pin,
|
||||
|
@ -24,16 +24,16 @@
|
||||
|
||||
/**
|
||||
* struct syscon_gpio_data - Configuration for the device.
|
||||
* compatible: SYSCON driver compatible string.
|
||||
* flags: Set of GPIO_SYSCON_FEAT_ flags:
|
||||
* @compatible: SYSCON driver compatible string.
|
||||
* @flags: Set of GPIO_SYSCON_FEAT_ flags:
|
||||
* GPIO_SYSCON_FEAT_IN: GPIOs supports input,
|
||||
* GPIO_SYSCON_FEAT_OUT: GPIOs supports output,
|
||||
* GPIO_SYSCON_FEAT_DIR: GPIOs supports switch direction.
|
||||
* bit_count: Number of bits used as GPIOs.
|
||||
* dat_bit_offset: Offset (in bits) to the first GPIO bit.
|
||||
* dir_bit_offset: Optional offset (in bits) to the first bit to switch
|
||||
* @bit_count: Number of bits used as GPIOs.
|
||||
* @dat_bit_offset: Offset (in bits) to the first GPIO bit.
|
||||
* @dir_bit_offset: Optional offset (in bits) to the first bit to switch
|
||||
* GPIO direction (Used with GPIO_SYSCON_FEAT_DIR flag).
|
||||
* set: HW specific callback to assigns output value
|
||||
* @set: HW specific callback to assigns output value
|
||||
* for signal "offset"
|
||||
*/
|
||||
|
||||
|
@ -121,6 +121,7 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
struct xra1403 *xra = gpiochip_get_data(chip);
|
||||
int value[XRA_LAST];
|
||||
int i;
|
||||
const char *label;
|
||||
unsigned int gcr;
|
||||
unsigned int gsr;
|
||||
|
||||
@ -136,12 +137,7 @@ static void xra1403_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
|
||||
gcr = value[XRA_GCR + 1] << 8 | value[XRA_GCR];
|
||||
gsr = value[XRA_GSR + 1] << 8 | value[XRA_GSR];
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
const char *label = gpiochip_is_requested(chip, i);
|
||||
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
for_each_requested_gpio(chip, i, label) {
|
||||
seq_printf(s, " gpio-%-3d (%-12s) %s %s\n",
|
||||
chip->base + i, label,
|
||||
(gcr & BIT(i)) ? "in" : "out",
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -21,6 +22,9 @@
|
||||
/* Maximum banks */
|
||||
#define ZYNQ_GPIO_MAX_BANK 4
|
||||
#define ZYNQMP_GPIO_MAX_BANK 6
|
||||
#define VERSAL_GPIO_MAX_BANK 4
|
||||
#define PMC_GPIO_MAX_BANK 5
|
||||
#define VERSAL_UNUSED_BANKS 2
|
||||
|
||||
#define ZYNQ_GPIO_BANK0_NGPIO 32
|
||||
#define ZYNQ_GPIO_BANK1_NGPIO 22
|
||||
@ -95,6 +99,7 @@
|
||||
/* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
|
||||
#define ZYNQ_GPIO_QUIRK_IS_ZYNQ BIT(0)
|
||||
#define GPIO_QUIRK_DATA_RO_BUG BIT(1)
|
||||
#define GPIO_QUIRK_VERSAL BIT(2)
|
||||
|
||||
struct gpio_regs {
|
||||
u32 datamsw[ZYNQMP_GPIO_MAX_BANK];
|
||||
@ -116,6 +121,7 @@ struct gpio_regs {
|
||||
* @irq: interrupt for the GPIO device
|
||||
* @p_data: pointer to platform data
|
||||
* @context: context registers
|
||||
* @dirlock: lock used for direction in/out synchronization
|
||||
*/
|
||||
struct zynq_gpio {
|
||||
struct gpio_chip chip;
|
||||
@ -124,6 +130,7 @@ struct zynq_gpio {
|
||||
int irq;
|
||||
const struct zynq_platform_data *p_data;
|
||||
struct gpio_regs context;
|
||||
spinlock_t dirlock; /* lock */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -196,6 +203,8 @@ static inline void zynq_gpio_get_bank_pin(unsigned int pin_num,
|
||||
gpio->p_data->bank_min[bank];
|
||||
return;
|
||||
}
|
||||
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
|
||||
bank = bank + VERSAL_UNUSED_BANKS;
|
||||
}
|
||||
|
||||
/* default */
|
||||
@ -297,6 +306,7 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int bank_num, bank_pin_num;
|
||||
unsigned long flags;
|
||||
struct zynq_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
|
||||
@ -310,9 +320,11 @@ static int zynq_gpio_dir_in(struct gpio_chip *chip, unsigned int pin)
|
||||
return -EINVAL;
|
||||
|
||||
/* clear the bit in direction mode reg to set the pin as input */
|
||||
spin_lock_irqsave(&gpio->dirlock, flags);
|
||||
reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
|
||||
reg &= ~BIT(bank_pin_num);
|
||||
writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
|
||||
spin_unlock_irqrestore(&gpio->dirlock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -334,11 +346,13 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
|
||||
{
|
||||
u32 reg;
|
||||
unsigned int bank_num, bank_pin_num;
|
||||
unsigned long flags;
|
||||
struct zynq_gpio *gpio = gpiochip_get_data(chip);
|
||||
|
||||
zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
|
||||
|
||||
/* set the GPIO pin as output */
|
||||
spin_lock_irqsave(&gpio->dirlock, flags);
|
||||
reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
|
||||
reg |= BIT(bank_pin_num);
|
||||
writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
|
||||
@ -347,6 +361,7 @@ static int zynq_gpio_dir_out(struct gpio_chip *chip, unsigned int pin,
|
||||
reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
|
||||
reg |= BIT(bank_pin_num);
|
||||
writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
|
||||
spin_unlock_irqrestore(&gpio->dirlock, flags);
|
||||
|
||||
/* set the state of the pin */
|
||||
zynq_gpio_set_value(chip, pin, state);
|
||||
@ -647,6 +662,8 @@ static void zynq_gpio_irqhandler(struct irq_desc *desc)
|
||||
int_enb = readl_relaxed(gpio->base_addr +
|
||||
ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
|
||||
zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb);
|
||||
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
|
||||
bank_num = bank_num + VERSAL_UNUSED_BANKS;
|
||||
}
|
||||
|
||||
chained_irq_exit(irqchip, desc);
|
||||
@ -676,6 +693,8 @@ static void zynq_gpio_save_context(struct zynq_gpio *gpio)
|
||||
gpio->context.int_any[bank_num] =
|
||||
readl_relaxed(gpio->base_addr +
|
||||
ZYNQ_GPIO_INTANY_OFFSET(bank_num));
|
||||
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
|
||||
bank_num = bank_num + VERSAL_UNUSED_BANKS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -707,6 +726,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
|
||||
writel_relaxed(~(gpio->context.int_en[bank_num]),
|
||||
gpio->base_addr +
|
||||
ZYNQ_GPIO_INTEN_OFFSET(bank_num));
|
||||
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
|
||||
bank_num = bank_num + VERSAL_UNUSED_BANKS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,6 +736,9 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev)
|
||||
struct zynq_gpio *gpio = dev_get_drvdata(dev);
|
||||
struct irq_data *data = irq_get_irq_data(gpio->irq);
|
||||
|
||||
if (!device_may_wakeup(dev))
|
||||
disable_irq(gpio->irq);
|
||||
|
||||
if (!irqd_is_wakeup_set(data)) {
|
||||
zynq_gpio_save_context(gpio);
|
||||
return pm_runtime_force_suspend(dev);
|
||||
@ -729,6 +753,9 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev)
|
||||
struct irq_data *data = irq_get_irq_data(gpio->irq);
|
||||
int ret;
|
||||
|
||||
if (!device_may_wakeup(dev))
|
||||
enable_irq(gpio->irq);
|
||||
|
||||
if (!irqd_is_wakeup_set(data)) {
|
||||
ret = pm_runtime_force_resume(dev);
|
||||
zynq_gpio_restore_context(gpio);
|
||||
@ -778,6 +805,31 @@ static const struct dev_pm_ops zynq_gpio_dev_pm_ops = {
|
||||
zynq_gpio_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct zynq_platform_data versal_gpio_def = {
|
||||
.label = "versal_gpio",
|
||||
.quirks = GPIO_QUIRK_VERSAL,
|
||||
.ngpio = 58,
|
||||
.max_bank = VERSAL_GPIO_MAX_BANK,
|
||||
.bank_min[0] = 0,
|
||||
.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
|
||||
.bank_min[3] = 26,
|
||||
.bank_max[3] = 57, /* Bank 3 is connected to FMIOs (32 pins) */
|
||||
};
|
||||
|
||||
static const struct zynq_platform_data pmc_gpio_def = {
|
||||
.label = "pmc_gpio",
|
||||
.ngpio = 116,
|
||||
.max_bank = PMC_GPIO_MAX_BANK,
|
||||
.bank_min[0] = 0,
|
||||
.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
|
||||
.bank_min[1] = 26,
|
||||
.bank_max[1] = 51, /* Bank 1 are connected to MIOs (26 pins) */
|
||||
.bank_min[3] = 52,
|
||||
.bank_max[3] = 83, /* Bank 3 is connected to EMIOs (32 pins) */
|
||||
.bank_min[4] = 84,
|
||||
.bank_max[4] = 115, /* Bank 4 is connected to EMIOs (32 pins) */
|
||||
};
|
||||
|
||||
static const struct zynq_platform_data zynqmp_gpio_def = {
|
||||
.label = "zynqmp_gpio",
|
||||
.quirks = GPIO_QUIRK_DATA_RO_BUG,
|
||||
@ -815,6 +867,8 @@ static const struct zynq_platform_data zynq_gpio_def = {
|
||||
static const struct of_device_id zynq_gpio_of_match[] = {
|
||||
{ .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def },
|
||||
{ .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def },
|
||||
{ .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def },
|
||||
{ .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def },
|
||||
{ /* end of table */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
|
||||
@ -876,7 +930,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
|
||||
/* Retrieve GPIO clock */
|
||||
gpio->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(gpio->clk)) {
|
||||
dev_err(&pdev->dev, "input clock not found.\n");
|
||||
if (PTR_ERR(gpio->clk) != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "input clock not found.\n");
|
||||
return PTR_ERR(gpio->clk);
|
||||
}
|
||||
ret = clk_prepare_enable(gpio->clk);
|
||||
@ -885,6 +940,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock_init(&gpio->dirlock);
|
||||
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
ret = pm_runtime_get_sync(&pdev->dev);
|
||||
@ -892,9 +949,12 @@ static int zynq_gpio_probe(struct platform_device *pdev)
|
||||
goto err_pm_dis;
|
||||
|
||||
/* disable interrupts for all banks */
|
||||
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)
|
||||
for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
|
||||
writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
|
||||
ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
|
||||
if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
|
||||
bank_num = bank_num + VERSAL_UNUSED_BANKS;
|
||||
}
|
||||
|
||||
/* Set up the GPIO irqchip */
|
||||
girq = &chip->irq;
|
||||
@ -919,6 +979,8 @@ static int zynq_gpio_probe(struct platform_device *pdev)
|
||||
goto err_pm_put;
|
||||
}
|
||||
|
||||
irq_set_status_flags(gpio->irq, IRQ_DISABLE_UNLAZY);
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
1154
drivers/gpio/gpiolib-cdev.c
Normal file
1154
drivers/gpio/gpiolib-cdev.c
Normal file
File diff suppressed because it is too large
Load Diff
11
drivers/gpio/gpiolib-cdev.h
Normal file
11
drivers/gpio/gpiolib-cdev.h
Normal file
@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef GPIOLIB_CDEV_H
|
||||
#define GPIOLIB_CDEV_H
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt);
|
||||
void gpiolib_cdev_unregister(struct gpio_device *gdev);
|
||||
|
||||
#endif /* GPIOLIB_CDEV_H */
|
@ -25,6 +25,9 @@
|
||||
|
||||
/**
|
||||
* of_gpio_spi_cs_get_count() - special GPIO counting for SPI
|
||||
* @dev: Consuming device
|
||||
* @con_id: Function within the GPIO consumer
|
||||
*
|
||||
* Some elder GPIO controllers need special quirks. Currently we handle
|
||||
* the Freescale GPIO controller with bindings that doesn't use the
|
||||
* established "cs-gpios" for chip selects but instead rely on
|
||||
|
@ -365,7 +365,7 @@ static DEVICE_ATTR_RW(active_low);
|
||||
static umode_t gpio_is_visible(struct kobject *kobj, struct attribute *attr,
|
||||
int n)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct gpiod_data *data = dev_get_drvdata(dev);
|
||||
struct gpio_desc *desc = data->desc;
|
||||
umode_t mode = attr->mode;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1486,14 +1486,11 @@ static void at91_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
int i;
|
||||
struct at91_gpio_chip *at91_gpio = gpiochip_get_data(chip);
|
||||
void __iomem *pio = at91_gpio->regbase;
|
||||
const char *gpio_label;
|
||||
|
||||
for (i = 0; i < chip->ngpio; i++) {
|
||||
for_each_requested_gpio(chip, i, gpio_label) {
|
||||
unsigned mask = pin_to_mask(i);
|
||||
const char *gpio_label;
|
||||
|
||||
gpio_label = gpiochip_is_requested(chip, i);
|
||||
if (!gpio_label)
|
||||
continue;
|
||||
mode = at91_gpio->ops->get_periph(pio, mask);
|
||||
seq_printf(s, "[%s] GPIO%s%d: ",
|
||||
gpio_label, chip->label, i);
|
||||
|
@ -474,6 +474,22 @@ struct gpio_chip {
|
||||
extern const char *gpiochip_is_requested(struct gpio_chip *gc,
|
||||
unsigned int offset);
|
||||
|
||||
/**
|
||||
* for_each_requested_gpio_in_range - iterates over requested GPIOs in a given range
|
||||
* @chip: the chip to query
|
||||
* @i: loop variable
|
||||
* @base: first GPIO in the range
|
||||
* @size: amount of GPIOs to check starting from @base
|
||||
* @label: label of current GPIO
|
||||
*/
|
||||
#define for_each_requested_gpio_in_range(chip, i, base, size, label) \
|
||||
for (i = 0; i < size; i++) \
|
||||
if ((label = gpiochip_is_requested(chip, base + i)) == NULL) {} else
|
||||
|
||||
/* Iterates over all requested GPIO of the given @chip */
|
||||
#define for_each_requested_gpio(chip, i, label) \
|
||||
for_each_requested_gpio_in_range(chip, i, 0, chip->ngpio, label)
|
||||
|
||||
/* add/remove chips */
|
||||
extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
||||
struct lock_class_key *lock_key,
|
||||
@ -481,7 +497,7 @@ extern int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
||||
|
||||
/**
|
||||
* gpiochip_add_data() - register a gpio_chip
|
||||
* @chip: the chip to register, with chip->base initialized
|
||||
* @gc: the chip to register, with chip->base initialized
|
||||
* @data: driver-private data associated with this chip
|
||||
*
|
||||
* Context: potentially before irqs will work
|
||||
|
Loading…
Reference in New Issue
Block a user