Skip to content

Commit

Permalink
Merge tag 'gpio-v5.4-updates-for-linus' of git://git.kernel.org/pub/s…
Browse files Browse the repository at this point in the history
…cm/linux/kernel/git/brgl/linux into devel

gpio: updates for v5.4

- use a helper variable for &pdev->dev in gpio-em
- tweak the ifdefs in GPIO headers
- fix function links in HTML docs
- remove an unneeded error message from ixp4xx
- use the optional clk_get in gpio-mxc instead of checking the return value
- a couple improvements in pca953x
- allow to build gpio-lpc32xx on non-lpc32xx targets
  • Loading branch information
Linus Walleij committed Sep 3, 2019
2 parents f6a7053 + f2ee731 commit 8a6abcd
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 144 deletions.
16 changes: 8 additions & 8 deletions Documentation/driver-api/gpio/driver.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ driver code:

The code implementing a gpio_chip should support multiple instances of the
controller, preferably using the driver model. That code will configure each
gpio_chip and issue ``gpiochip_add[_data]()`` or ``devm_gpiochip_add_data()``.
Removing a GPIO controller should be rare; use ``[devm_]gpiochip_remove()``
when it is unavoidable.
gpio_chip and issue gpiochip_add(), gpiochip_add_data(), or
devm_gpiochip_add_data(). Removing a GPIO controller should be rare; use
gpiochip_remove() when it is unavoidable.

Often a gpio_chip is part of an instance-specific structure with states not
exposed by the GPIO interfaces, such as addressing, power management, and more.
Expand Down Expand Up @@ -512,11 +512,11 @@ available but we try to move away from this:

If there is a need to exclude certain GPIO lines from the IRQ domain handled by
these helpers, we can set .irq.need_valid_mask of the gpiochip before
``[devm_]gpiochip_add_data()`` is called. This allocates an .irq.valid_mask with as
many bits set as there are GPIO lines in the chip, each bit representing line
0..n-1. Drivers can exclude GPIO lines by clearing bits from this mask. The mask
must be filled in before gpiochip_irqchip_add() or gpiochip_irqchip_add_nested()
is called.
devm_gpiochip_add_data() or gpiochip_add_data() is called. This allocates an
.irq.valid_mask with as many bits set as there are GPIO lines in the chip, each
bit representing line 0..n-1. Drivers can exclude GPIO lines by clearing bits
from this mask. The mask must be filled in before gpiochip_irqchip_add() or
gpiochip_irqchip_add_nested() is called.

To use the helpers please keep the following in mind:

Expand Down
1 change: 1 addition & 0 deletions arch/arm/configs/lpc32xx_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ CONFIG_SERIAL_HS_LPC32XX_CONSOLE=y
# CONFIG_HW_RANDOM is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PNX=y
CONFIG_GPIO_LPC32XX=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_GPIO_SYSFS=y
Expand Down
7 changes: 7 additions & 0 deletions drivers/gpio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,13 @@ config GPIO_LPC18XX
Select this option to enable GPIO driver for
NXP LPC18XX/43XX devices.

config GPIO_LPC32XX
tristate "NXP LPC32XX GPIO support"
depends on OF_GPIO && (ARCH_LPC32XX || COMPILE_TEST)
help
Select this option to enable GPIO driver for
NXP LPC32XX devices.

config GPIO_LYNXPOINT
tristate "Intel Lynxpoint GPIO support"
depends on ACPI && X86
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpio/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ obj-$(CONFIG_GPIO_LP3943) += gpio-lp3943.o
obj-$(CONFIG_GPIO_LP873X) += gpio-lp873x.o
obj-$(CONFIG_GPIO_LP87565) += gpio-lp87565.o
obj-$(CONFIG_GPIO_LPC18XX) += gpio-lpc18xx.o
obj-$(CONFIG_ARCH_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LPC32XX) += gpio-lpc32xx.o
obj-$(CONFIG_GPIO_LYNXPOINT) += gpio-lynxpoint.o
obj-$(CONFIG_GPIO_MADERA) += gpio-madera.o
obj-$(CONFIG_GPIO_MAX3191X) += gpio-max3191x.o
Expand Down
37 changes: 19 additions & 18 deletions drivers/gpio/gpio-em.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,12 @@ static int em_gio_probe(struct platform_device *pdev)
struct resource *io[2], *irq[2];
struct gpio_chip *gpio_chip;
struct irq_chip *irq_chip;
const char *name = dev_name(&pdev->dev);
struct device *dev = &pdev->dev;
const char *name = dev_name(dev);
unsigned int ngpios;
int ret;

p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL);
if (!p)
return -ENOMEM;

Expand All @@ -290,27 +291,27 @@ static int em_gio_probe(struct platform_device *pdev)
irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1);

if (!io[0] || !io[1] || !irq[0] || !irq[1]) {
dev_err(&pdev->dev, "missing IRQ or IOMEM\n");
dev_err(dev, "missing IRQ or IOMEM\n");
return -EINVAL;
}

p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start,
p->base0 = devm_ioremap_nocache(dev, io[0]->start,
resource_size(io[0]));
if (!p->base0)
return -ENOMEM;

p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start,
p->base1 = devm_ioremap_nocache(dev, io[1]->start,
resource_size(io[1]));
if (!p->base1)
return -ENOMEM;

if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) {
dev_err(&pdev->dev, "Missing ngpios OF property\n");
if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) {
dev_err(dev, "Missing ngpios OF property\n");
return -EINVAL;
}

gpio_chip = &p->gpio_chip;
gpio_chip->of_node = pdev->dev.of_node;
gpio_chip->of_node = dev->of_node;
gpio_chip->direction_input = em_gio_direction_input;
gpio_chip->get = em_gio_get;
gpio_chip->direction_output = em_gio_direction_output;
Expand All @@ -319,7 +320,7 @@ static int em_gio_probe(struct platform_device *pdev)
gpio_chip->request = em_gio_request;
gpio_chip->free = em_gio_free;
gpio_chip->label = name;
gpio_chip->parent = &pdev->dev;
gpio_chip->parent = dev;
gpio_chip->owner = THIS_MODULE;
gpio_chip->base = -1;
gpio_chip->ngpio = ngpios;
Expand All @@ -333,33 +334,33 @@ static int em_gio_probe(struct platform_device *pdev)
irq_chip->irq_release_resources = em_gio_irq_relres;
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND;

p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0,
p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0,
&em_gio_irq_domain_ops, p);
if (!p->irq_domain) {
dev_err(&pdev->dev, "cannot initialize irq domain\n");
dev_err(dev, "cannot initialize irq domain\n");
return -ENXIO;
}

ret = devm_add_action_or_reset(&pdev->dev, em_gio_irq_domain_remove,
ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove,
p->irq_domain);
if (ret)
return ret;

if (devm_request_irq(&pdev->dev, irq[0]->start,
if (devm_request_irq(dev, irq[0]->start,
em_gio_irq_handler, 0, name, p)) {
dev_err(&pdev->dev, "failed to request low IRQ\n");
dev_err(dev, "failed to request low IRQ\n");
return -ENOENT;
}

if (devm_request_irq(&pdev->dev, irq[1]->start,
if (devm_request_irq(dev, irq[1]->start,
em_gio_irq_handler, 0, name, p)) {
dev_err(&pdev->dev, "failed to request high IRQ\n");
dev_err(dev, "failed to request high IRQ\n");
return -ENOENT;
}

ret = devm_gpiochip_add_data(&pdev->dev, gpio_chip, p);
ret = devm_gpiochip_add_data(dev, gpio_chip, p);
if (ret) {
dev_err(&pdev->dev, "failed to add GPIO controller\n");
dev_err(dev, "failed to add GPIO controller\n");
return ret;
}

Expand Down
4 changes: 1 addition & 3 deletions drivers/gpio/gpio-ixp4xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,8 @@ static int ixp4xx_gpio_probe(struct platform_device *pdev)

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
g->base = devm_ioremap_resource(dev, res);
if (IS_ERR(g->base)) {
dev_err(dev, "ioremap error\n");
if (IS_ERR(g->base))
return PTR_ERR(g->base);
}

/*
* When we convert to device tree we will simply look up the
Expand Down
118 changes: 68 additions & 50 deletions drivers/gpio/gpio-lpc32xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,33 @@
#include <linux/platform_device.h>
#include <linux/module.h>

#include <mach/hardware.h>
#include <mach/platform.h>

#define LPC32XX_GPIO_P3_INP_STATE _GPREG(0x000)
#define LPC32XX_GPIO_P3_OUTP_SET _GPREG(0x004)
#define LPC32XX_GPIO_P3_OUTP_CLR _GPREG(0x008)
#define LPC32XX_GPIO_P3_OUTP_STATE _GPREG(0x00C)
#define LPC32XX_GPIO_P2_DIR_SET _GPREG(0x010)
#define LPC32XX_GPIO_P2_DIR_CLR _GPREG(0x014)
#define LPC32XX_GPIO_P2_DIR_STATE _GPREG(0x018)
#define LPC32XX_GPIO_P2_INP_STATE _GPREG(0x01C)
#define LPC32XX_GPIO_P2_OUTP_SET _GPREG(0x020)
#define LPC32XX_GPIO_P2_OUTP_CLR _GPREG(0x024)
#define LPC32XX_GPIO_P2_MUX_SET _GPREG(0x028)
#define LPC32XX_GPIO_P2_MUX_CLR _GPREG(0x02C)
#define LPC32XX_GPIO_P2_MUX_STATE _GPREG(0x030)
#define LPC32XX_GPIO_P0_INP_STATE _GPREG(0x040)
#define LPC32XX_GPIO_P0_OUTP_SET _GPREG(0x044)
#define LPC32XX_GPIO_P0_OUTP_CLR _GPREG(0x048)
#define LPC32XX_GPIO_P0_OUTP_STATE _GPREG(0x04C)
#define LPC32XX_GPIO_P0_DIR_SET _GPREG(0x050)
#define LPC32XX_GPIO_P0_DIR_CLR _GPREG(0x054)
#define LPC32XX_GPIO_P0_DIR_STATE _GPREG(0x058)
#define LPC32XX_GPIO_P1_INP_STATE _GPREG(0x060)
#define LPC32XX_GPIO_P1_OUTP_SET _GPREG(0x064)
#define LPC32XX_GPIO_P1_OUTP_CLR _GPREG(0x068)
#define LPC32XX_GPIO_P1_OUTP_STATE _GPREG(0x06C)
#define LPC32XX_GPIO_P1_DIR_SET _GPREG(0x070)
#define LPC32XX_GPIO_P1_DIR_CLR _GPREG(0x074)
#define LPC32XX_GPIO_P1_DIR_STATE _GPREG(0x078)
#define LPC32XX_GPIO_P3_INP_STATE (0x000)
#define LPC32XX_GPIO_P3_OUTP_SET (0x004)
#define LPC32XX_GPIO_P3_OUTP_CLR (0x008)
#define LPC32XX_GPIO_P3_OUTP_STATE (0x00C)
#define LPC32XX_GPIO_P2_DIR_SET (0x010)
#define LPC32XX_GPIO_P2_DIR_CLR (0x014)
#define LPC32XX_GPIO_P2_DIR_STATE (0x018)
#define LPC32XX_GPIO_P2_INP_STATE (0x01C)
#define LPC32XX_GPIO_P2_OUTP_SET (0x020)
#define LPC32XX_GPIO_P2_OUTP_CLR (0x024)
#define LPC32XX_GPIO_P2_MUX_SET (0x028)
#define LPC32XX_GPIO_P2_MUX_CLR (0x02C)
#define LPC32XX_GPIO_P2_MUX_STATE (0x030)
#define LPC32XX_GPIO_P0_INP_STATE (0x040)
#define LPC32XX_GPIO_P0_OUTP_SET (0x044)
#define LPC32XX_GPIO_P0_OUTP_CLR (0x048)
#define LPC32XX_GPIO_P0_OUTP_STATE (0x04C)
#define LPC32XX_GPIO_P0_DIR_SET (0x050)
#define LPC32XX_GPIO_P0_DIR_CLR (0x054)
#define LPC32XX_GPIO_P0_DIR_STATE (0x058)
#define LPC32XX_GPIO_P1_INP_STATE (0x060)
#define LPC32XX_GPIO_P1_OUTP_SET (0x064)
#define LPC32XX_GPIO_P1_OUTP_CLR (0x068)
#define LPC32XX_GPIO_P1_OUTP_STATE (0x06C)
#define LPC32XX_GPIO_P1_DIR_SET (0x070)
#define LPC32XX_GPIO_P1_DIR_CLR (0x074)
#define LPC32XX_GPIO_P1_DIR_STATE (0x078)

#define GPIO012_PIN_TO_BIT(x) (1 << (x))
#define GPIO3_PIN_TO_BIT(x) (1 << ((x) + 25))
Expand All @@ -72,12 +69,12 @@
#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)

struct gpio_regs {
void __iomem *inp_state;
void __iomem *outp_state;
void __iomem *outp_set;
void __iomem *outp_clr;
void __iomem *dir_set;
void __iomem *dir_clr;
unsigned long inp_state;
unsigned long outp_state;
unsigned long outp_set;
unsigned long outp_clr;
unsigned long dir_set;
unsigned long dir_clr;
};

/*
Expand Down Expand Up @@ -165,16 +162,27 @@ static struct gpio_regs gpio_grp_regs_p3 = {
struct lpc32xx_gpio_chip {
struct gpio_chip chip;
struct gpio_regs *gpio_grp;
void __iomem *reg_base;
};

static inline u32 gpreg_read(struct lpc32xx_gpio_chip *group, unsigned long offset)
{
return __raw_readl(group->reg_base + offset);
}

static inline void gpreg_write(struct lpc32xx_gpio_chip *group, u32 val, unsigned long offset)
{
__raw_writel(val, group->reg_base + offset);
}

static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
unsigned pin, int input)
{
if (input)
__raw_writel(GPIO012_PIN_TO_BIT(pin),
gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->dir_clr);
else
__raw_writel(GPIO012_PIN_TO_BIT(pin),
gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->dir_set);
}

Expand All @@ -184,19 +192,19 @@ static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
u32 u = GPIO3_PIN_TO_BIT(pin);

if (input)
__raw_writel(u, group->gpio_grp->dir_clr);
gpreg_write(group, u, group->gpio_grp->dir_clr);
else
__raw_writel(u, group->gpio_grp->dir_set);
gpreg_write(group, u, group->gpio_grp->dir_set);
}

static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
unsigned pin, int high)
{
if (high)
__raw_writel(GPIO012_PIN_TO_BIT(pin),
gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->outp_set);
else
__raw_writel(GPIO012_PIN_TO_BIT(pin),
gpreg_write(group, GPIO012_PIN_TO_BIT(pin),
group->gpio_grp->outp_clr);
}

Expand All @@ -206,31 +214,31 @@ static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
u32 u = GPIO3_PIN_TO_BIT(pin);

if (high)
__raw_writel(u, group->gpio_grp->outp_set);
gpreg_write(group, u, group->gpio_grp->outp_set);
else
__raw_writel(u, group->gpio_grp->outp_clr);
gpreg_write(group, u, group->gpio_grp->outp_clr);
}

static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
unsigned pin, int high)
{
if (high)
__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
else
__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
gpreg_write(group, GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
}

static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
return GPIO012_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state),
pin);
}

static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
int state = __raw_readl(group->gpio_grp->inp_state);
int state = gpreg_read(group, group->gpio_grp->inp_state);

/*
* P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
Expand All @@ -242,13 +250,13 @@ static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
return GPI3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->inp_state), pin);
}

static int __get_gpo_state_p3(struct lpc32xx_gpio_chip *group,
unsigned pin)
{
return GPO3_PIN_IN_SEL(__raw_readl(group->gpio_grp->outp_state), pin);
return GPO3_PIN_IN_SEL(gpreg_read(group, group->gpio_grp->outp_state), pin);
}

/*
Expand Down Expand Up @@ -497,12 +505,18 @@ static int lpc32xx_of_xlate(struct gpio_chip *gc,
static int lpc32xx_gpio_probe(struct platform_device *pdev)
{
int i;
void __iomem *reg_base;

reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(reg_base))
return PTR_ERR(reg_base);

for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++) {
if (pdev->dev.of_node) {
lpc32xx_gpiochip[i].chip.of_xlate = lpc32xx_of_xlate;
lpc32xx_gpiochip[i].chip.of_gpio_n_cells = 3;
lpc32xx_gpiochip[i].chip.of_node = pdev->dev.of_node;
lpc32xx_gpiochip[i].reg_base = reg_base;
}
devm_gpiochip_add_data(&pdev->dev, &lpc32xx_gpiochip[i].chip,
&lpc32xx_gpiochip[i]);
Expand All @@ -527,3 +541,7 @@ static struct platform_driver lpc32xx_gpio_driver = {
};

module_platform_driver(lpc32xx_gpio_driver);

MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("GPIO driver for LPC32xx SoC");
Loading

0 comments on commit 8a6abcd

Please sign in to comment.