Commit 576db734 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-updates-for-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio updates from Bartosz Golaszewski:
 "We have two new drivers, an assortment of updates and cleanups to many
  others, and first part of the big rework of the core GPIOLIB that's
  currently underway.

  Add to that some code shrink in the character device module and
  updates to DT bindings and that's pretty much it.

  Core GPIOLIB:
   - protect the global list of GPIO devices with a read-write semaphore
     as it is rarely modified but can be traversed by multiple readers
     at once
   - remove GPIO devices from the global list when they are
     *unregistered* and not when they are *released* (which only happens
     when the last reference is dropped) as this may lead to a
     successful lookup of an unregistered device
   - remove the unnecessary "extra_checks" switch
   - rename functions that are called with a lock taken
   - remove duplicate includes

  Character device handling:
   - use locking guards to reduce the code size
   - allocate the big linereq structure using the more suitable
     kvzalloc()
   - redulce the size of critical sections
   - improve documentation
   - move the debounce_period_us field out of struct gpio_desc

  New drivers:
   - Nuvoton NPCM SGPIO driver for BMC NPCM7xx/NPCM8xx
   - Realtek DHC (Digital Home Center) SoC GPIO driver

  Driver improvements:
   - replace gpiochip_is_requested() with a safer alternative in the
     form of gpiochip_dup_line_label() as the former returns a pointer
     to a string that can be deleted
   - implement the dbg_show() callback in gpio-sim
   - improve the coding style for local variables by removing
     unnecessary tabs
   - use generic device properties instead of OF variants in gpio-mmio
   - use the preferred coding style for __free() in gpio-mockup
   - reuse PM ops from the gpio-tangier in gpio-elkhartlake
   - rework PM and use cleanup helpers in gpio-tangier
   - fix the EIC configuration in gpio-pmic-eic-sprd
   - remove the unneeded call to platform_set_drvdata() in gpio-sifive
   - use generic GPIO helpers for driver callbacks in gpio-dwapb
   - add clock support on certain pins of gpio-ixp4xx
   - don't use the core-specific DEBUG_GPIO switch in drivers
   - kerneldoc improvements

  DT bindings:
   - add bindings for the new Realtek and Nuvoton devices
   - allow gpio-ranges in gpio-dwapb
   - support GPIO hogs in gpio-rockchip
   - describe the label property in gpio-zynqmp-modepin

  Other:
   - header cleanups
   - forward declarations cleanups"

* tag 'gpio-updates-for-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: (55 commits)
  gpiolib: replace the GPIO device mutex with a read-write semaphore
  gpiolib: remove the GPIO device from the list when it's unregistered
  gpio: nuvoton: Add Nuvoton NPCM sgpio driver
  dt-bindings: gpio: add NPCM sgpio driver bindings
  gpio: rtd: Add support for Realtek DHC(Digital Home Center) RTD SoCs
  dt-bindings: gpio: realtek: Add realtek,rtd-gpio
  gpio: pmic-eic-sprd: Configure the bit corresponding to the EIC through offset
  gpio: dwapb: Use generic request, free and set_config
  gpio: sysfs: drop tabs from local variable declarations
  gpiolib: drop tabs from local variable declarations
  gpiolib: remove extra_checks
  gpio: tps65219: don't use CONFIG_DEBUG_GPIO
  gpiolib: cdev: replace locking wrappers for gpio_device with guards
  gpiolib: cdev: replace locking wrappers for config_mutex with guards
  gpiolib: cdev: allocate linereq using kvzalloc()
  gpiolib: cdev: include overflow.h
  gpiolib: cdev: reduce locking in gpio_desc_to_lineinfo()
  gpiolib: cdev: improve documentation of get/set values
  gpiolib: cdev: fully adopt guard() and scoped_guard()
  gpiolib: remove debounce_period_us from struct gpio_desc
  ...
parents 61f4c3e6 1979a280
......@@ -72,7 +72,7 @@ required:
- reg
- gpio-controller
- "#gpio-cells"
- "brcm,gpio-bank-widths"
- brcm,gpio-bank-widths
additionalProperties: false
......
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/nuvoton,sgpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Nuvoton SGPIO controller
maintainers:
- Jim LIU <JJLIU0@nuvoton.com>
description: |
This SGPIO controller is for NUVOTON NPCM7xx and NPCM8xx SoC and detailed
information is in the NPCM7XX/8XX SERIAL I/O EXPANSION INTERFACE section.
Nuvoton NPCM7xx SGPIO module is combines a serial to parallel IC (HC595)
and a parallel to serial IC (HC165).
Clock is a division of the APB3 clock.
This interface has 4 pins (D_out , D_in, S_CLK, LDSH).
NPCM7xx/NPCM8xx have two sgpio modules. Each module can support up
to 64 output pins, and up to 64 input pins, the pin is only for GPI or GPO.
GPIO pins can be programmed to support the following options
- Support interrupt option for each input port and various interrupt
sensitivity options (level-high, level-low, edge-high, edge-low)
- ngpios is number of nuvoton,input-ngpios GPIO lines and nuvoton,output-ngpios GPIO lines.
nuvoton,input-ngpios GPIO lines is only for GPI.
nuvoton,output-ngpios GPIO lines is only for GPO.
properties:
compatible:
enum:
- nuvoton,npcm750-sgpio
- nuvoton,npcm845-sgpio
reg:
maxItems: 1
gpio-controller: true
'#gpio-cells':
const: 2
interrupts:
maxItems: 1
clocks:
maxItems: 1
nuvoton,input-ngpios:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The numbers of GPIO's exposed. GPIO lines are only for GPI.
minimum: 0
maximum: 64
nuvoton,output-ngpios:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The numbers of GPIO's exposed. GPIO lines are only for GPO.
minimum: 0
maximum: 64
required:
- compatible
- reg
- gpio-controller
- '#gpio-cells'
- interrupts
- nuvoton,input-ngpios
- nuvoton,output-ngpios
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/nuvoton,npcm7xx-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
gpio8: gpio@101000 {
compatible = "nuvoton,npcm750-sgpio";
reg = <0x101000 0x200>;
clocks = <&clk NPCM7XX_CLK_APB3>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
gpio-controller;
#gpio-cells = <2>;
nuvoton,input-ngpios = <64>;
nuvoton,output-ngpios = <64>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2023 Realtek Semiconductor Corporation
%YAML 1.2
---
$id: http://devicetree.org/schemas/gpio/realtek,rtd-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Realtek DHC GPIO controller
maintainers:
- Tzuyi Chang <tychang@realtek.com>
description:
The GPIO controller is designed for the Realtek DHC (Digital Home Center)
RTD series SoC family, which are high-definition media processor SoCs.
properties:
compatible:
enum:
- realtek,rtd1295-misc-gpio
- realtek,rtd1295-iso-gpio
- realtek,rtd1315e-iso-gpio
- realtek,rtd1319-iso-gpio
- realtek,rtd1319d-iso-gpio
- realtek,rtd1395-iso-gpio
- realtek,rtd1619-iso-gpio
- realtek,rtd1619b-iso-gpio
reg:
items:
- description: GPIO controller registers
- description: GPIO interrupt registers
interrupts:
items:
- description: Interrupt number of the assert GPIO interrupt, which is
triggered when there is a rising edge.
- description: Interrupt number of the deassert GPIO interrupt, which is
triggered when there is a falling edge.
gpio-ranges: true
gpio-controller: true
"#gpio-cells":
const: 2
required:
- compatible
- reg
- interrupts
- gpio-ranges
- gpio-controller
- "#gpio-cells"
additionalProperties: false
examples:
- |
gpio@100 {
compatible = "realtek,rtd1319d-iso-gpio";
reg = <0x100 0x100>,
<0x0 0xb0>;
interrupt-parent = <&iso_irq_mux>;
interrupts = <19>, <20>;
gpio-ranges = <&pinctrl 0 0 82>;
gpio-controller;
#gpio-cells = <2>;
};
......@@ -41,6 +41,13 @@ properties:
"#interrupt-cells":
const: 2
patternProperties:
"^.+-hog(-[0-9]+)?$":
type: object
required:
- gpio-hog
required:
- compatible
- reg
......
......@@ -65,6 +65,8 @@ patternProperties:
minItems: 1
maxItems: 32
gpio-ranges: true
ngpios:
default: 32
minimum: 1
......
......@@ -23,6 +23,8 @@ properties:
"#gpio-cells":
const: 2
label: true
required:
- compatible
- gpio-controller
......@@ -37,6 +39,7 @@ examples:
compatible = "xlnx,zynqmp-gpio-modepin";
gpio-controller;
#gpio-cells = <2>;
label = "modepin";
};
};
......
......@@ -478,6 +478,13 @@ config GPIO_MXS
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
config GPIO_NPCM_SGPIO
bool "Nuvoton SGPIO support"
depends on ARCH_NPCM || COMPILE_TEST
select GPIOLIB_IRQCHIP
help
Say Y here to support Nuvoton NPCM7XX/NPCM8XX SGPIO functionality.
config GPIO_OCTEON
tristate "Cavium OCTEON GPIO"
depends on CAVIUM_OCTEON_SOC
......@@ -553,6 +560,19 @@ config GPIO_ROCKCHIP
help
Say yes here to support GPIO on Rockchip SoCs.
config GPIO_RTD
tristate "Realtek DHC GPIO support"
depends on ARCH_REALTEK
default y
select GPIOLIB_IRQCHIP
help
This option enables support for GPIOs found on Realtek DHC(Digital
Home Center) SoCs family, including RTD1295, RTD1315E, RTD1319,
RTD1319D, RTD1395, RTD1619 and RTD1619B.
Say yes here to support GPIO functionality and GPIO interrupt on
Realtek DHC SoCs.
config GPIO_SAMA5D2_PIOBU
tristate "SAMA5D2 PIOBU GPIO support"
depends on MFD_SYSCON
......
......@@ -116,6 +116,7 @@ obj-$(CONFIG_GPIO_MT7621) += gpio-mt7621.o
obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o
obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o
obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o
obj-$(CONFIG_GPIO_NPCM_SGPIO) += gpio-npcm-sgpio.o
obj-$(CONFIG_GPIO_OCTEON) += gpio-octeon.o
obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
obj-$(CONFIG_GPIO_PALMAS) += gpio-palmas.o
......@@ -137,6 +138,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
obj-$(CONFIG_GPIO_REG) += gpio-reg.o
obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o
obj-$(CONFIG_GPIO_RTD) += gpio-rtd.o
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o
......
......@@ -416,11 +416,12 @@ static int dwapb_gpio_set_config(struct gpio_chip *gc, unsigned offset,
{
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) {
debounce = pinconf_to_config_argument(config);
return dwapb_gpio_set_debounce(gc, offset, debounce);
}
debounce = pinconf_to_config_argument(config);
return dwapb_gpio_set_debounce(gc, offset, debounce);
return gpiochip_generic_config(gc, offset, config);
}
static int dwapb_convert_irqs(struct dwapb_gpio_port_irqchip *pirq,
......@@ -530,10 +531,14 @@ static int dwapb_gpio_add_port(struct dwapb_gpio *gpio,
port->gc.fwnode = pp->fwnode;
port->gc.ngpio = pp->ngpio;
port->gc.base = pp->gpio_base;
port->gc.request = gpiochip_generic_request;
port->gc.free = gpiochip_generic_free;
/* Only port A support debounce */
if (pp->idx == 0)
port->gc.set_config = dwapb_gpio_set_config;
else
port->gc.set_config = gpiochip_generic_config;
/* Only port A can provide interrupts in all configurations of the IP */
if (pp->idx == 0)
......
......@@ -55,18 +55,6 @@ static int ehl_gpio_probe(struct platform_device *pdev)
return 0;
}
static int ehl_gpio_suspend(struct device *dev)
{
return tng_gpio_suspend(dev);
}
static int ehl_gpio_resume(struct device *dev)
{
return tng_gpio_resume(dev);
}
static DEFINE_SIMPLE_DEV_PM_OPS(ehl_gpio_pm_ops, ehl_gpio_suspend, ehl_gpio_resume);
static const struct platform_device_id ehl_gpio_ids[] = {
{ "gpio-elkhartlake" },
{ }
......@@ -76,7 +64,7 @@ MODULE_DEVICE_TABLE(platform, ehl_gpio_ids);
static struct platform_driver ehl_gpio_driver = {
.driver = {
.name = "gpio-elkhartlake",
.pm = pm_sleep_ptr(&ehl_gpio_pm_ops),
.pm = pm_sleep_ptr(&tng_gpio_pm_ops),
},
.probe = ehl_gpio_probe,
.id_table = ehl_gpio_ids,
......
......@@ -38,6 +38,18 @@
#define IXP4XX_GPIO_STYLE_MASK GENMASK(2, 0)
#define IXP4XX_GPIO_STYLE_SIZE 3
/*
* Clock output control register defines.
*/
#define IXP4XX_GPCLK_CLK0DC_SHIFT 0
#define IXP4XX_GPCLK_CLK0TC_SHIFT 4
#define IXP4XX_GPCLK_CLK0_MASK GENMASK(7, 0)
#define IXP4XX_GPCLK_MUX14 BIT(8)
#define IXP4XX_GPCLK_CLK1DC_SHIFT 16
#define IXP4XX_GPCLK_CLK1TC_SHIFT 20
#define IXP4XX_GPCLK_CLK1_MASK GENMASK(23, 16)
#define IXP4XX_GPCLK_MUX15 BIT(24)
/**
* struct ixp4xx_gpio - IXP4 GPIO state container
* @dev: containing device for this instance
......@@ -202,6 +214,8 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
struct ixp4xx_gpio *g;
struct gpio_irq_chip *girq;
struct device_node *irq_parent;
bool clk_14, clk_15;
u32 val;
int ret;
g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
......@@ -225,13 +239,48 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)
}
g->fwnode = of_node_to_fwnode(np);
/*
* If either clock output is enabled explicitly in the device tree
* we take full control of the clock by masking off all bits for
* the clock control and selectively enabling them. Otherwise
* we leave the hardware default settings.
*
* Enable clock outputs with default timings of requested clock.
* If you need control over TC and DC, add these to the device
* tree bindings and use them here.
*/
clk_14 = of_property_read_bool(np, "intel,ixp4xx-gpio14-clkout");
clk_15 = of_property_read_bool(np, "intel,ixp4xx-gpio15-clkout");
/*
* Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
* specific machines.
*/
if (of_machine_is_compatible("dlink,dsm-g600-a") ||
of_machine_is_compatible("iom,nas-100d"))
__raw_writel(0x0, g->base + IXP4XX_REG_GPCLK);
val = 0;
else {
val = __raw_readl(g->base + IXP4XX_REG_GPCLK);
if (clk_14 || clk_15) {
val &= ~(IXP4XX_GPCLK_MUX14 | IXP4XX_GPCLK_MUX15);
val &= ~IXP4XX_GPCLK_CLK0_MASK;
val &= ~IXP4XX_GPCLK_CLK1_MASK;
if (clk_14) {
/* IXP4XX_GPCLK_CLK0DC implicit low */
val |= (1 << IXP4XX_GPCLK_CLK0TC_SHIFT);
val |= IXP4XX_GPCLK_MUX14;
}
if (clk_15) {
/* IXP4XX_GPCLK_CLK1DC implicit low */
val |= (1 << IXP4XX_GPCLK_CLK1TC_SHIFT);
val |= IXP4XX_GPCLK_MUX15;
}
}
}
__raw_writel(val, g->base + IXP4XX_REG_GPCLK);
/*
* This is a very special big-endian ARM issue: when the IXP4xx is
......
// SPDX-License-Identifier: GPL-2.0-only
/**
/*
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
* Copyright (C) 2009 Wolfram Sang, Pengutronix
......
......@@ -40,25 +40,22 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
* `.......````.```
*/
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/log2.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/log2.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include "gpiolib.h"
......@@ -688,7 +685,6 @@ static void __iomem *bgpio_map(struct platform_device *pdev,
return devm_ioremap_resource(&pdev->dev, r);
}
#ifdef CONFIG_OF
static const struct of_device_id bgpio_of_match[] = {
{ .compatible = "brcm,bcm6345-gpio" },
{ .compatible = "wd,mbl-gpio" },
......@@ -697,36 +693,27 @@ static const struct of_device_id bgpio_of_match[] = {
};
MODULE_DEVICE_TABLE(of, bgpio_of_match);
static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
unsigned long *flags)
static struct bgpio_pdata *bgpio_parse_fw(struct device *dev, unsigned long *flags)
{
struct bgpio_pdata *pdata;
if (!pdev->dev.of_node)
if (!dev_fwnode(dev))
return NULL;
pdata = devm_kzalloc(&pdev->dev, sizeof(struct bgpio_pdata),
GFP_KERNEL);
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
pdata->base = -1;
if (of_device_is_big_endian(pdev->dev.of_node))
if (device_is_big_endian(dev))
*flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
if (of_property_read_bool(pdev->dev.of_node, "no-output"))
if (device_property_read_bool(dev, "no-output"))
*flags |= BGPIOF_NO_OUTPUT;
return pdata;
}
#else
static struct bgpio_pdata *bgpio_parse_dt(struct platform_device *pdev,
unsigned long *flags)
{
return NULL;
}
#endif /* CONFIG_OF */
static int bgpio_pdev_probe(struct platform_device *pdev)
{
......@@ -743,7 +730,7 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
struct gpio_chip *gc;
struct bgpio_pdata *pdata;
pdata = bgpio_parse_dt(pdev, &flags);
pdata = bgpio_parse_fw(dev, &flags);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
......@@ -814,7 +801,7 @@ MODULE_DEVICE_TABLE(platform, bgpio_id_table);
static struct platform_driver bgpio_driver = {
.driver = {
.name = "basic-mmio-gpio",
.of_match_table = of_match_ptr(bgpio_of_match),
.of_match_table = bgpio_of_match,
},
.id_table = bgpio_id_table,
.probe = bgpio_pdev_probe,
......
......@@ -354,7 +354,6 @@ static const struct file_operations gpio_mockup_debugfs_ops = {
static void gpio_mockup_debugfs_setup(struct device *dev,
struct gpio_mockup_chip *chip)
{
struct device *child __free(put_device) = NULL;
struct gpio_mockup_dbgfs_private *priv;
struct gpio_chip *gc;
const char *devname;
......@@ -367,7 +366,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev,
* There can only be a single GPIO device per platform device in
* gpio-mockup so using device_find_any_child() is OK.
*/
child = device_find_any_child(dev);
struct device *child __free(put_device) = device_find_any_child(dev);
if (!child)
return;
......
This diff is collapsed.
......@@ -151,8 +151,8 @@ static void sprd_pmic_eic_irq_mask(struct irq_data *data)
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
u32 offset = irqd_to_hwirq(data);
pmic_eic->reg[REG_IE] = 0;
pmic_eic->reg[REG_TRIG] = 0;
pmic_eic->reg[REG_IE] &= ~BIT(offset);
pmic_eic->reg[REG_TRIG] &= ~BIT(offset);
gpiochip_disable_irq(chip, offset);
}
......@@ -165,8 +165,8 @@ static void sprd_pmic_eic_irq_unmask(struct irq_data *data)
gpiochip_enable_irq(chip, offset);
pmic_eic->reg[REG_IE] = 1;
pmic_eic->reg[REG_TRIG] = 1;
pmic_eic->reg[REG_IE] |= BIT(offset);
pmic_eic->reg[REG_TRIG] |= BIT(offset);
}
static int sprd_pmic_eic_irq_set_type(struct irq_data *data,
......@@ -174,13 +174,14 @@ static int sprd_pmic_eic_irq_set_type(struct irq_data *data,
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct sprd_pmic_eic *pmic_eic = gpiochip_get_data(chip);
u32 offset = irqd_to_hwirq(data);
switch (flow_type) {
case IRQ_TYPE_LEVEL_HIGH:
pmic_eic->reg[REG_IEV] = 1;
pmic_eic->reg[REG_IEV] |= BIT(offset);
break;
case IRQ_TYPE_LEVEL_LOW:
pmic_eic->reg[REG_IEV] = 0;
pmic_eic->reg[REG_IEV] &= ~BIT(offset);
break;
case IRQ_TYPE_EDGE_RISING:
case IRQ_TYPE_EDGE_FALLING:
......@@ -222,15 +223,15 @@ static void sprd_pmic_eic_bus_sync_unlock(struct irq_data *data)
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV, 1);
} else {
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IEV,
pmic_eic->reg[REG_IEV]);
!!(pmic_eic->reg[REG_IEV] & BIT(offset)));
}
/* Set irq unmask */
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_IE,
pmic_eic->reg[REG_IE]);
!!(pmic_eic->reg[REG_IE] & BIT(offset)));
/* Generate trigger start pulse for debounce EIC */
sprd_pmic_eic_update(chip, offset, SPRD_PMIC_EIC_TRIG,
pmic_eic->reg[REG_TRIG]);
!!(pmic_eic->reg[REG_TRIG] & BIT(offset)));
mutex_unlock(&pmic_eic->buslock);
}
......
This diff is collapsed.
......@@ -250,7 +250,6 @@ static int sifive_gpio_probe(struct platform_device *pdev)
girq->handler = handle_bad_irq;
girq->default_type = IRQ_TYPE_NONE;
platform_set_drvdata(pdev, chip);
return gpiochip_add_data(&chip->gc, chip);
}
......
......@@ -20,6 +20,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irq_sim.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/minmax.h>
#include <linux/mod_devicetable.h>
......@@ -28,6 +29,7 @@
#include <linux/notifier.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
......@@ -224,6 +226,25 @@ static void gpio_sim_free(struct gpio_chip *gc, unsigned int offset)
}
}
static void gpio_sim_dbg_show(struct seq_file *seq, struct gpio_chip *gc)
{
struct gpio_sim_chip *chip = gpiochip_get_data(gc);
const char *label;
int i;
guard(mutex)(&chip->lock);
for_each_requested_gpio(gc, i, label)
seq_printf(seq, " gpio-%-3d (%s) %s,%s\n",
gc->base + i,
label,
test_bit(i, chip->direction_map) ? "input" :
test_bit(i, chip->value_map) ? "output-high" :
"output-low",
test_bit(i, chip->pull_map) ? "pull-up" :
"pull-down");
}
static ssize_t gpio_sim_sysfs_val_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
......@@ -460,6 +481,7 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev)
gc->to_irq = gpio_sim_to_irq;
gc->request = gpio_sim_request;
gc->free = gpio_sim_free;
gc->dbg_show = PTR_IF(IS_ENABLED(CONFIG_DEBUG_FS), gpio_sim_dbg_show);
gc->can_sleep = true;
ret = devm_gpiochip_add_data(dev, gc, chip);
......@@ -1546,6 +1568,6 @@ static void __exit gpio_sim_exit(void)
}
module_exit(gpio_sim_exit);
MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl");
MODULE_AUTHOR("Bartosz Golaszewski <brgl@bgdev.pl>");
MODULE_DESCRIPTION("GPIO Simulator Module");
MODULE_LICENSE("GPL");
......@@ -5,6 +5,7 @@
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
*/
#include <linux/cleanup.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
......@@ -255,7 +256,6 @@ static void stmpe_dbg_show_one(struct seq_file *s,
{
struct stmpe_gpio *stmpe_gpio = gpiochip_get_data(gc);
struct stmpe *stmpe = stmpe_gpio->stmpe;
const char *label = gpiochip_is_requested(gc, offset);
bool val = !!stmpe_gpio_get(gc, offset);
u8 bank = offset / 8;
u8 dir_reg = stmpe->regs[STMPE_IDX_GPDR_LSB + bank];
......@@ -263,6 +263,10 @@ static void stmpe_dbg_show_one(struct seq_file *s,
int ret;
u8 dir;
char *label __free(kfree) = gpiochip_dup_line_label(gc, offset);
if (IS_ERR(label))
return;
ret = stmpe_reg_read(stmpe, dir_reg);
if (ret < 0)
return;
......
......@@ -10,6 +10,7 @@
*/
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/export.h>
......@@ -19,6 +20,7 @@
#include <linux/math.h>
#include <linux/module.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pm.h>
#include <linux/spinlock.h>
#include <linux/string_helpers.h>
#include <linux/types.h>
......@@ -91,37 +93,31 @@ static int tng_gpio_get(struct gpio_chip *chip, unsigned int offset)
static void tng_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct tng_gpio *priv = gpiochip_get_data(chip);
unsigned long flags;
void __iomem *reg;
u8 shift;
reg = gpio_reg_and_bit(chip, offset, value ? GPSR : GPCR, &shift);
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
writel(BIT(shift), reg);
raw_spin_unlock_irqrestore(&priv->lock, flags);
}
static int tng_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct tng_gpio *priv = gpiochip_get_data(chip);
unsigned long flags;
void __iomem *gpdr;
u32 value;
u8 shift;
gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift);
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
value = readl(gpdr);
value &= ~BIT(shift);
writel(value, gpdr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
......@@ -129,21 +125,18 @@ static int tng_gpio_direction_output(struct gpio_chip *chip, unsigned int offset
int value)
{
struct tng_gpio *priv = gpiochip_get_data(chip);
unsigned long flags;
void __iomem *gpdr;
u8 shift;
gpdr = gpio_reg_and_bit(chip, offset, GPDR, &shift);
tng_gpio_set(chip, offset, value);
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
value = readl(gpdr);
value |= BIT(shift);
writel(value, gpdr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
......@@ -164,14 +157,13 @@ static int tng_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
unsigned int debounce)
{
struct tng_gpio *priv = gpiochip_get_data(chip);
unsigned long flags;
void __iomem *gfbr;
u32 value;
u8 shift;
gfbr = gpio_reg_and_bit(chip, offset, GFBR, &shift);
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
value = readl(gfbr);
if (debounce)
......@@ -180,8 +172,6 @@ static int tng_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
value |= BIT(shift);
writel(value, gfbr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
......@@ -207,27 +197,25 @@ static void tng_irq_ack(struct irq_data *d)
{
struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
irq_hw_number_t gpio = irqd_to_hwirq(d);
unsigned long flags;
void __iomem *gisr;
u8 shift;
gisr = gpio_reg_and_bit(&priv->chip, gpio, GISR, &shift);
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
writel(BIT(shift), gisr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
}
static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask)
{
unsigned long flags;
void __iomem *gimr;
u32 value;
u8 shift;
gimr = gpio_reg_and_bit(&priv->chip, gpio, GIMR, &shift);
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
value = readl(gimr);
if (unmask)
......@@ -235,8 +223,6 @@ static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask)
else
value &= ~BIT(shift);
writel(value, gimr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
}
static void tng_irq_mask(struct irq_data *d)
......@@ -267,10 +253,9 @@ static int tng_irq_set_type(struct irq_data *d, unsigned int type)
void __iomem *gitr = gpio_reg(&priv->chip, gpio, GITR);
void __iomem *glpr = gpio_reg(&priv->chip, gpio, GLPR);
u8 shift = gpio % 32;
unsigned long flags;
u32 value;
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
value = readl(grer);
if (type & IRQ_TYPE_EDGE_RISING)
......@@ -311,8 +296,6 @@ static int tng_irq_set_type(struct irq_data *d, unsigned int type)
irq_set_handler_locked(d, handle_edge_irq);
}
raw_spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
......@@ -324,10 +307,11 @@ static int tng_irq_set_wake(struct irq_data *d, unsigned int on)
void __iomem *gwmr = gpio_reg(&priv->chip, gpio, priv->wake_regs.gwmr);
void __iomem *gwsr = gpio_reg(&priv->chip, gpio, priv->wake_regs.gwsr);
u8 shift = gpio % 32;
unsigned long flags;
u32 value;
raw_spin_lock_irqsave(&priv->lock, flags);
dev_dbg(priv->dev, "%s wake for gpio %lu\n", str_enable_disable(on), gpio);
guard(raw_spinlock_irqsave)(&priv->lock);
/* Clear the existing wake status */
writel(BIT(shift), gwsr);
......@@ -339,9 +323,6 @@ static int tng_irq_set_wake(struct irq_data *d, unsigned int on)
value &= ~BIT(shift);
writel(value, gwmr);
raw_spin_unlock_irqrestore(&priv->lock, flags);
dev_dbg(priv->dev, "%s wake for gpio %lu\n", str_enable_disable(on), gpio);
return 0;
}
......@@ -477,14 +458,13 @@ int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio)
}
EXPORT_SYMBOL_NS_GPL(devm_tng_gpio_probe, GPIO_TANGIER);
int tng_gpio_suspend(struct device *dev)
static int tng_gpio_suspend(struct device *dev)
{
struct tng_gpio *priv = dev_get_drvdata(dev);
struct tng_gpio_context *ctx = priv->ctx;
unsigned long flags;
unsigned int base;
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
for (base = 0; base < priv->chip.ngpio; base += 32, ctx++) {
/* GPLR is RO, values read will be restored using GPSR */
......@@ -498,20 +478,16 @@ int tng_gpio_suspend(struct device *dev)
ctx->gwmr = readl(gpio_reg(&priv->chip, base, priv->wake_regs.gwmr));
}
raw_spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
EXPORT_SYMBOL_NS_GPL(tng_gpio_suspend, GPIO_TANGIER);
int tng_gpio_resume(struct device *dev)
static int tng_gpio_resume(struct device *dev)
{
struct tng_gpio *priv = dev_get_drvdata(dev);
struct tng_gpio_context *ctx = priv->ctx;
unsigned long flags;
unsigned int base;
raw_spin_lock_irqsave(&priv->lock, flags);
guard(raw_spinlock_irqsave)(&priv->lock);
for (base = 0; base < priv->chip.ngpio; base += 32, ctx++) {
/* GPLR is RO, values read will be restored using GPSR */
......@@ -525,11 +501,10 @@ int tng_gpio_resume(struct device *dev)
writel(ctx->gwmr, gpio_reg(&priv->chip, base, priv->wake_regs.gwmr));
}
raw_spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
EXPORT_SYMBOL_NS_GPL(tng_gpio_resume, GPIO_TANGIER);
EXPORT_NS_GPL_SIMPLE_DEV_PM_OPS(tng_gpio_pm_ops, tng_gpio_suspend, tng_gpio_resume, GPIO_TANGIER);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Pandith N <pandith.n@intel.com>");
......
......@@ -13,6 +13,7 @@
#define _GPIO_TANGIER_H_
#include <linux/gpio/driver.h>
#include <linux/pm.h>
#include <linux/spinlock_types.h>
#include <linux/types.h>
......@@ -111,7 +112,6 @@ struct tng_gpio {
int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio);
int tng_gpio_suspend(struct device *dev);
int tng_gpio_resume(struct device *dev);
extern const struct dev_pm_ops tng_gpio_pm_ops;
#endif /* _GPIO_TANGIER_H_ */
......@@ -96,16 +96,16 @@ static int tps65219_gpio_change_direction(struct gpio_chip *gc, unsigned int off
* Below can be used for test purpose only.
*/
if (IS_ENABLED(CONFIG_DEBUG_GPIO)) {
int ret = regmap_update_bits(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG,
TPS65219_GPIO0_DIR_MASK, direction);
if (ret) {
dev_err(dev,
"GPIO DEBUG enabled: Fail to change direction to %u for GPIO%d.\n",
direction, offset);
return ret;
}
#if 0
int ret = regmap_update_bits(gpio->tps->regmap, TPS65219_REG_MFP_1_CONFIG,
TPS65219_GPIO0_DIR_MASK, direction);
if (ret) {
dev_err(dev,
"GPIO DEBUG enabled: Fail to change direction to %u for GPIO%d.\n",
direction, offset);
return ret;
}
#endif
dev_err(dev,
"GPIO%d direction set by NVM, change to %u failed, not allowed by specification\n",
......
......@@ -8,6 +8,7 @@
*
*/
#include <linux/cleanup.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
......@@ -160,18 +161,21 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < chip->ngpio; i++) {
int gpio = i + chip->base;
int reg;
const char *label, *pull, *powerdomain;
const char *pull, *powerdomain;
/* We report the GPIO even if it's not requested since
* we're also reporting things like alternate
* functions which apply even when the GPIO is not in
* use as a GPIO.
*/
label = gpiochip_is_requested(chip, i);
if (!label)
label = "Unrequested";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label)) {
dev_err(wm831x->dev, "Failed to duplicate label\n");
continue;
}
seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
seq_printf(s, " gpio-%-3d (%-20.20s) ",
gpio, label ?: "Unrequested");
reg = wm831x_reg_read(wm831x, WM831X_GPIO1_CONTROL + i);
if (reg < 0) {
......
......@@ -8,6 +8,7 @@
*
*/
#include <linux/cleanup.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
......@@ -193,18 +194,20 @@ static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
for (i = 0; i < chip->ngpio; i++) {
int gpio = i + chip->base;
int reg;
const char *label;
/* We report the GPIO even if it's not requested since
* we're also reporting things like alternate
* functions which apply even when the GPIO is not in
* use as a GPIO.
*/
label = gpiochip_is_requested(chip, i);
if (!label)
label = "Unrequested";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label)) {
dev_err(wm8994->dev, "Failed to duplicate label\n");
continue;
}
seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio,
label ?: "Unrequested");
reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
if (reg < 0) {
......
......@@ -52,7 +52,6 @@
* @dir: GPIO direction shadow register
* @gpio_lock: Lock used for synchronization
* @irq: IRQ used by GPIO device
* @irqchip: IRQ chip
* @enable: GPIO IRQ enable/disable bitfield
* @rising_edge: GPIO IRQ rising edge enable/disable bitfield
* @falling_edge: GPIO IRQ falling edge enable/disable bitfield
......
This diff is collapsed.
......@@ -165,10 +165,10 @@ static irqreturn_t gpio_sysfs_irq(int irq, void *priv)
/* Caller holds gpiod-data mutex. */
static int gpio_sysfs_request_irq(struct device *dev, unsigned char flags)
{
struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc;
unsigned long irq_flags;
int ret;
struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc;
unsigned long irq_flags;
int ret;
data->irq = gpiod_to_irq(desc);
if (data->irq < 0)
......@@ -259,7 +259,7 @@ static ssize_t edge_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct gpiod_data *data = dev_get_drvdata(dev);
ssize_t status = size;
ssize_t status = size;
int flags;
flags = sysfs_match_string(trigger_names, buf);
......@@ -292,10 +292,11 @@ static DEVICE_ATTR_RW(edge);
/* Caller holds gpiod-data mutex. */
static int gpio_sysfs_set_active_low(struct device *dev, int value)
{
struct gpiod_data *data = dev_get_drvdata(dev);
struct gpio_desc *desc = data->desc;
int status = 0;
unsigned int flags = data->irq_flags;
struct gpiod_data *data = dev_get_drvdata(dev);
unsigned int flags = data->irq_flags;
struct gpio_desc *desc = data->desc;
int status = 0;
if (!!test_bit(FLAG_ACTIVE_LOW, &desc->flags) == !!value)
return 0;
......@@ -331,9 +332,9 @@ static ssize_t active_low_show(struct device *dev,
static ssize_t active_low_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct gpiod_data *data = dev_get_drvdata(dev);
ssize_t status;
long value;
struct gpiod_data *data = dev_get_drvdata(dev);
ssize_t status;
long value;
status = kstrtol(buf, 0, &value);
if (status)
......@@ -399,7 +400,7 @@ static const struct attribute_group *gpio_groups[] = {
static ssize_t base_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_chip *chip = dev_get_drvdata(dev);
const struct gpio_chip *chip = dev_get_drvdata(dev);
return sysfs_emit(buf, "%d\n", chip->base);
}
......@@ -408,7 +409,7 @@ static DEVICE_ATTR_RO(base);
static ssize_t label_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_chip *chip = dev_get_drvdata(dev);
const struct gpio_chip *chip = dev_get_drvdata(dev);
return sysfs_emit(buf, "%s\n", chip->label ?: "");
}
......@@ -417,7 +418,7 @@ static DEVICE_ATTR_RO(label);
static ssize_t ngpio_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
const struct gpio_chip *chip = dev_get_drvdata(dev);
const struct gpio_chip *chip = dev_get_drvdata(dev);
return sysfs_emit(buf, "%u\n", chip->ngpio);
}
......@@ -441,11 +442,10 @@ static ssize_t export_store(const struct class *class,
const struct class_attribute *attr,
const char *buf, size_t len)
{
long gpio;
struct gpio_desc *desc;
int status;
struct gpio_chip *gc;
int offset;
struct gpio_desc *desc;
struct gpio_chip *gc;
int status, offset;
long gpio;
status = kstrtol(buf, 0, &gpio);
if (status < 0)
......@@ -496,9 +496,9 @@ static ssize_t unexport_store(const struct class *class,
const struct class_attribute *attr,
const char *buf, size_t len)
{
long gpio;
struct gpio_desc *desc;
int status;
struct gpio_desc *desc;
int status;
long gpio;
status = kstrtol(buf, 0, &gpio);
if (status < 0)
......@@ -559,14 +559,13 @@ static struct class gpio_class = {
*/
int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
{
struct gpio_chip *chip;
struct gpio_device *gdev;
struct gpiod_data *data;
unsigned long flags;
int status;
const char *ioname = NULL;
struct device *dev;
int offset;
const char *ioname = NULL;
struct gpio_device *gdev;
struct gpiod_data *data;
struct gpio_chip *chip;
unsigned long flags;
struct device *dev;
int status, offset;
/* can't export until sysfs is available ... */
if (!class_is_registered(&gpio_class)) {
......@@ -733,9 +732,9 @@ EXPORT_SYMBOL_GPL(gpiod_unexport);
int gpiochip_sysfs_register(struct gpio_device *gdev)
{
struct device *dev;
struct device *parent;
struct gpio_chip *chip = gdev->chip;
struct device *parent;
struct device *dev;
/*
* Many systems add gpio chips for SOC support very early,
......@@ -769,6 +768,25 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
return 0;
}
int gpiochip_sysfs_register_all(void)
{
struct gpio_device *gdev;
int ret;
guard(rwsem_read)(&gpio_devices_sem);
list_for_each_entry(gdev, &gpio_devices, list) {
if (gdev->mockdev)
continue;
ret = gpiochip_sysfs_register(gdev);
if (ret)
return ret;
}
return 0;
}
void gpiochip_sysfs_unregister(struct gpio_device *gdev)
{
struct gpio_desc *desc;
......@@ -793,9 +811,7 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
static int __init gpiolib_sysfs_init(void)
{
int status;
unsigned long flags;
struct gpio_device *gdev;
int status;
status = class_register(&gpio_class);
if (status < 0)
......@@ -807,26 +823,6 @@ static int __init gpiolib_sysfs_init(void)
* We run before arch_initcall() so chip->dev nodes can have
* registered, and so arch_initcall() can always gpiod_export().
*/
spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(gdev, &gpio_devices, list) {
if (gdev->mockdev)
continue;
/*
* TODO we yield gpio_lock here because
* gpiochip_sysfs_register() acquires a mutex. This is unsafe
* and needs to be fixed.
*
* Also it would be nice to use gpio_device_find() here so we
* can keep gpio_chips local to gpiolib.c, but the yield of
* gpio_lock prevents us from doing this.
*/
spin_unlock_irqrestore(&gpio_lock, flags);
status = gpiochip_sysfs_register(gdev);
spin_lock_irqsave(&gpio_lock, flags);
}
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
return gpiochip_sysfs_register_all();
}
postcore_initcall(gpiolib_sysfs_init);
......@@ -3,11 +3,12 @@
#ifndef GPIOLIB_SYSFS_H
#define GPIOLIB_SYSFS_H
#ifdef CONFIG_GPIO_SYSFS
struct gpio_device;
#ifdef CONFIG_GPIO_SYSFS
int gpiochip_sysfs_register(struct gpio_device *gdev);
int gpiochip_sysfs_register_all(void);
void gpiochip_sysfs_unregister(struct gpio_device *gdev);
#else
......@@ -17,6 +18,11 @@ static inline int gpiochip_sysfs_register(struct gpio_device *gdev)
return 0;
}
static inline int gpiochip_sysfs_register_all(void)
{
return 0;
}
static inline void gpiochip_sysfs_unregister(struct gpio_device *gdev)
{
}
......
This diff is collapsed.
......@@ -15,6 +15,7 @@
#include <linux/gpio/consumer.h> /* for enum gpiod_flags */
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/rwsem.h>
......@@ -136,6 +137,7 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory);
extern spinlock_t gpio_lock;
extern struct list_head gpio_devices;
extern struct rw_semaphore gpio_devices_sem;
void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
......@@ -147,7 +149,6 @@ void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action);
* @label: Name of the consumer
* @name: Line name
* @hog: Pointer to the device node that hogs this line (if any)
* @debounce_period_us: Debounce period in microseconds
*
* These are obtained using gpiod_get() and are preferable to the old
* integer-based handles.
......@@ -185,10 +186,6 @@ struct gpio_desc {
#ifdef CONFIG_OF_DYNAMIC
struct device_node *hog;
#endif
#ifdef CONFIG_GPIO_CDEV
/* debounce period in microseconds */
unsigned int debounce_period_us;
#endif
};
#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
......
......@@ -9,6 +9,7 @@
#include <linux/acpi.h>
#include <linux/array_size.h>
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
#include <linux/interrupt.h>
......@@ -1173,7 +1174,6 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
const char *pull_str = NULL;
const char *pull = NULL;
unsigned long flags;
const char *label;
unsigned int pin;
pin = vg->soc->pins[i].number;
......@@ -1200,9 +1200,10 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
seq_printf(s, "Pin %i: can't retrieve community\n", pin);
continue;
}
label = gpiochip_is_requested(chip, i);
if (!label)
label = "Unrequested";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label))
continue;
switch (conf0 & BYT_PULL_ASSIGN_MASK) {
case BYT_PULL_ASSIGN_UP:
......@@ -1231,7 +1232,7 @@ 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",
pin,
label,
label ?: "Unrequested",
val & BYT_INPUT_EN ? " " : "in",
val & BYT_OUTPUT_EN ? " " : "out",
str_hi_lo(val & BYT_LEVEL),
......
......@@ -6,7 +6,9 @@
*
* Driver allows to use AxB5xx unused pins to be used as GPIO
*/
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
......@@ -453,12 +455,11 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
unsigned offset, unsigned gpio)
{
struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev);
const char *label = gpiochip_is_requested(chip, offset - 1);
u8 gpio_offset = offset - 1;
int mode = -1;
bool is_out;
bool pd;
int ret;
int ret = -ENOMEM;
const char *modes[] = {
[ABX500_DEFAULT] = "default",
......@@ -474,6 +475,10 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
[ABX500_GPIO_PULL_UP] = "pull up",
};
char *label __free(kfree) = gpiochip_dup_line_label(chip, offset - 1);
if (IS_ERR(label))
goto out;
ret = abx500_gpio_get_bit(chip, AB8500_GPIO_DIR1_REG,
gpio_offset, &is_out);
if (ret < 0)
......
......@@ -8,6 +8,7 @@
* Copyright (C) 2011-2013 Linus Walleij <linus.walleij@linaro.org>
*/
#include <linux/bitops.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/err.h>
......@@ -917,7 +918,6 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
struct pinctrl_dev *pctldev, struct gpio_chip *chip,
unsigned offset, unsigned gpio)
{
const char *label = gpiochip_is_requested(chip, offset);
struct nmk_gpio_chip *nmk_chip = gpiochip_get_data(chip);
int mode;
bool is_out;
......@@ -934,6 +934,10 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s,
[NMK_GPIO_ALT_C+4] = "altC4",
};
char *label = gpiochip_dup_line_label(chip, offset);
if (IS_ERR(label))
return;
clk_enable(nmk_chip->clk);
is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & BIT(offset));
pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & BIT(offset));
......
......@@ -4,6 +4,7 @@
* Copyright (C) Sunplus Tech / Tibbo Tech.
*/
#include <linux/cleanup.h>
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/err.h>
......@@ -500,16 +501,15 @@ static int sppctl_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
static void sppctl_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
const char *label;
int i;
for (i = 0; i < chip->ngpio; i++) {
label = gpiochip_is_requested(chip, i);
if (!label)
label = "";
char *label __free(kfree) = gpiochip_dup_line_label(chip, i);
if (IS_ERR(label))
continue;
seq_printf(s, " gpio-%03d (%-16.16s | %-16.16s)", i + chip->base,
chip->names[i], label);
chip->names[i], label ?: "");
seq_printf(s, " %c", sppctl_gpio_get_direction(chip, i) ? 'I' : 'O');
seq_printf(s, ":%d", sppctl_gpio_get(chip, i));
seq_printf(s, " %s", sppctl_first_get(chip, i) ? "gpi" : "mux");
......
......@@ -531,19 +531,40 @@ struct gpio_chip {
#endif /* CONFIG_OF_GPIO */
};
const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset);
char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset);
struct _gpiochip_for_each_data {
const char **label;
unsigned int *i;
};
DEFINE_CLASS(_gpiochip_for_each_data,
struct _gpiochip_for_each_data,
if (*_T.label) kfree(*_T.label),
({
struct _gpiochip_for_each_data _data = { label, i };
*_data.i = 0;
_data;
}),
const char **label, int *i)
/**
* 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
* @_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
#define for_each_requested_gpio_in_range(_chip, _i, _base, _size, _label) \
for (CLASS(_gpiochip_for_each_data, _data)(&_label, &_i); \
*_data.i < _size; \
(*_data.i)++, kfree(*(_data.label)), *_data.label = NULL) \
if ((*_data.label = \
gpiochip_dup_line_label(_chip, _base + *_data.i)) == NULL) {} \
else if (IS_ERR(*_data.label)) {} \
else
/* Iterates over all requested GPIO of the given @chip */
#define for_each_requested_gpio(chip, i, label) \
......@@ -701,7 +722,6 @@ int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
#else
#include <asm/bug.h>
#include <asm/errno.h>
static inline int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
struct irq_domain *domain)
......@@ -786,11 +806,10 @@ struct gpio_device *gpiod_to_gpio_device(struct gpio_desc *desc);
/* struct gpio_device getters */
int gpio_device_get_base(struct gpio_device *gdev);
const char *gpio_device_get_label(struct gpio_device *gdev);
#else /* CONFIG_GPIOLIB */
#include <linux/err.h>
#include <asm/bug.h>
static inline struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
......
......@@ -80,12 +80,38 @@ int fwnode_property_match_string(const struct fwnode_handle *fwnode,
bool fwnode_device_is_available(const struct fwnode_handle *fwnode);
static inline bool fwnode_device_is_big_endian(const struct fwnode_handle *fwnode)
{
if (fwnode_property_present(fwnode, "big-endian"))
return true;
if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
fwnode_property_present(fwnode, "native-endian"))
return true;
return false;
}
static inline
bool fwnode_device_is_compatible(const struct fwnode_handle *fwnode, const char *compat)
{
return fwnode_property_match_string(fwnode, "compatible", compat) >= 0;
}
/**
* device_is_big_endian - check if a device has BE registers
* @dev: Pointer to the struct device
*
* Returns: true if the device has a "big-endian" property, or if the kernel
* was compiled for BE *and* the device has a "native-endian" property.
* Returns false otherwise.
*
* Callers would nominally use ioread32be/iowrite32be if
* device_is_big_endian() == true, or readl/writel otherwise.
*/
static inline bool device_is_big_endian(const struct device *dev)
{
return fwnode_device_is_big_endian(dev_fwnode(dev));
}
/**
* device_is_compatible - match 'compatible' property of the device with a given string
* @dev: Pointer to the struct device
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment