gpio fixes for v6.13-rc3

- fix several low-level issues in gpio-graniterapids
 - fix an initialization order issue that manifests itself with
   __counted_by() checks in gpio-ljca
 - don't default to y for CONFIG_GPIO_MVEBU with COMPILE_TEST enabled
 - move the DEFAULT_SYMBOL_NAMESPACE define before the export.h include
   in gpio-idio-16
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmdcOcIACgkQEacuoBRx
 13Ky3g/+JZawOniCmm5vBEH5SS4lhjEMts0i0WkaH5oIhESxsLgfZO8e0ucQt4td
 AmVk7ingHaoY1GYL1bmhkZEELHhqrSYb0uCMMtK1AxvXOeMUdGRj2QYpdKLGdWL3
 dCrWemJi8sx0UDWs4LLvR5HcoKAACB5Mu2NmOMTtuYiBB8qIfCWQ0+0Q09/yhJM8
 WNhGComnuKPvVgndHrGcd5H7CTUJobyacYu3dwvzPjPC+PvC6YTrkos5xonbyx1E
 GQQ3bxgU/ZvuGp6OKKeugaMxJcWOcrBm7emYiCyYwcasrh3GghUAcQ8UAP9CLYSx
 U1AzWI1lDqNdh7a+pr+HYR43aJ8RJ8lWFKA5wlUHSZv97G4aZyFRPBIC0AI4C9os
 OvW/sS4IvJ/snY7dyQ7972RLEMzmSSpEDWyYdrwOCDAtRt6KGpK7GH6yQrxQJCUN
 6g30wry+zzlybki0gyyQB53b8X5pth6VuDtpaPSwFPQo1JL+Z0abbIPjqJKrVZBt
 UoVLKAev5Jo6U5/aiPvddBMw31RPeAN2dQTuYxKI8fv9xtWMYrpa9y9Hzgt4s1HX
 F+Pl2cVUnM+cKWYQbk7m1s07jHMjsnaH0RCxPX54RnXaQ7hevXfBn0HeNkETN426
 uZmlQIPgIB7cP2zdBDnJ6Jzgzv5mu+azIuTb11PL6JmL+DOXzhw=
 =nunS
 -----END PGP SIGNATURE-----

Merge tag 'gpio-fixes-for-v6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:

 - fix several low-level issues in gpio-graniterapids

 - fix an initialization order issue that manifests itself with
   __counted_by() checks in gpio-ljca

 - don't default to y for CONFIG_GPIO_MVEBU with COMPILE_TEST enabled

 - move the DEFAULT_SYMBOL_NAMESPACE define before the export.h include
   in gpio-idio-16

* tag 'gpio-fixes-for-v6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpio: idio-16: Actually make use of the GPIO_IDIO_16 symbol namespace
  gpio: graniterapids: Fix GPIO Ack functionality
  gpio: graniterapids: Check if GPIO line can be used for IRQs
  gpio: graniterapids: Determine if GPIO pad can be used by driver
  gpio: graniterapids: Fix invalid RXEVCFG register bitmask
  gpio: graniterapids: Fix invalid GPI_IS register offset
  gpio: graniterapids: Fix incorrect BAR assignment
  gpio: graniterapids: Fix vGPIO driver crash
  gpio: ljca: Initialize num before accessing item in ljca_gpio_config
  gpio: GPIO_MVEBU should not default to y when compile-testing
This commit is contained in:
Linus Torvalds 2024-12-13 09:57:15 -08:00
commit 243f750a2d
4 changed files with 47 additions and 15 deletions

View File

@ -482,8 +482,9 @@ config GPIO_MT7621
Say yes here to support the Mediatek MT7621 SoC GPIO device.
config GPIO_MVEBU
def_bool y
bool "Marvell Orion and EBU GPIO support" if COMPILE_TEST
depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
default PLAT_ORION || ARCH_MVEBU
select GENERIC_IRQ_CHIP
select REGMAP_MMIO

View File

@ -32,12 +32,14 @@
#define GNR_PINS_PER_REG 32
#define GNR_NUM_REGS DIV_ROUND_UP(GNR_NUM_PINS, GNR_PINS_PER_REG)
#define GNR_CFG_BAR 0x00
#define GNR_CFG_PADBAR 0x00
#define GNR_CFG_LOCK_OFFSET 0x04
#define GNR_GPI_STATUS_OFFSET 0x20
#define GNR_GPI_STATUS_OFFSET 0x14
#define GNR_GPI_ENABLE_OFFSET 0x24
#define GNR_CFG_DW_RX_MASK GENMASK(25, 22)
#define GNR_CFG_DW_HOSTSW_MODE BIT(27)
#define GNR_CFG_DW_RX_MASK GENMASK(23, 22)
#define GNR_CFG_DW_INTSEL_MASK GENMASK(21, 14)
#define GNR_CFG_DW_RX_DISABLE FIELD_PREP(GNR_CFG_DW_RX_MASK, 2)
#define GNR_CFG_DW_RX_EDGE FIELD_PREP(GNR_CFG_DW_RX_MASK, 1)
#define GNR_CFG_DW_RX_LEVEL FIELD_PREP(GNR_CFG_DW_RX_MASK, 0)
@ -50,6 +52,7 @@
* struct gnr_gpio - Intel Granite Rapids-D vGPIO driver state
* @gc: GPIO controller interface
* @reg_base: base address of the GPIO registers
* @pad_base: base address of the vGPIO pad configuration registers
* @ro_bitmap: bitmap of read-only pins
* @lock: guard the registers
* @pad_backup: backup of the register state for suspend
@ -57,6 +60,7 @@
struct gnr_gpio {
struct gpio_chip gc;
void __iomem *reg_base;
void __iomem *pad_base;
DECLARE_BITMAP(ro_bitmap, GNR_NUM_PINS);
raw_spinlock_t lock;
u32 pad_backup[];
@ -65,7 +69,7 @@ struct gnr_gpio {
static void __iomem *gnr_gpio_get_padcfg_addr(const struct gnr_gpio *priv,
unsigned int gpio)
{
return priv->reg_base + gpio * sizeof(u32);
return priv->pad_base + gpio * sizeof(u32);
}
static int gnr_gpio_configure_line(struct gpio_chip *gc, unsigned int gpio,
@ -88,6 +92,20 @@ static int gnr_gpio_configure_line(struct gpio_chip *gc, unsigned int gpio,
return 0;
}
static int gnr_gpio_request(struct gpio_chip *gc, unsigned int gpio)
{
struct gnr_gpio *priv = gpiochip_get_data(gc);
u32 dw;
dw = readl(gnr_gpio_get_padcfg_addr(priv, gpio));
if (!(dw & GNR_CFG_DW_HOSTSW_MODE)) {
dev_warn(gc->parent, "GPIO %u is not owned by host", gpio);
return -EBUSY;
}
return 0;
}
static int gnr_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
const struct gnr_gpio *priv = gpiochip_get_data(gc);
@ -139,6 +157,7 @@ static int gnr_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, in
static const struct gpio_chip gnr_gpio_chip = {
.owner = THIS_MODULE,
.request = gnr_gpio_request,
.get = gnr_gpio_get,
.set = gnr_gpio_set,
.get_direction = gnr_gpio_get_direction,
@ -166,7 +185,7 @@ static void gnr_gpio_irq_ack(struct irq_data *d)
guard(raw_spinlock_irqsave)(&priv->lock);
reg = readl(addr);
reg &= ~BIT(bit_idx);
reg |= BIT(bit_idx);
writel(reg, addr);
}
@ -209,10 +228,18 @@ static void gnr_gpio_irq_unmask(struct irq_data *d)
static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
irq_hw_number_t pin = irqd_to_hwirq(d);
u32 mask = GNR_CFG_DW_RX_MASK;
struct gnr_gpio *priv = gpiochip_get_data(gc);
irq_hw_number_t hwirq = irqd_to_hwirq(d);
u32 reg;
u32 set;
/* Allow interrupts only if Interrupt Select field is non-zero */
reg = readl(gnr_gpio_get_padcfg_addr(priv, hwirq));
if (!(reg & GNR_CFG_DW_INTSEL_MASK)) {
dev_dbg(gc->parent, "GPIO %lu cannot be used as IRQ", hwirq);
return -EPERM;
}
/* Falling edge and level low triggers not supported by the GPIO controller */
switch (type) {
case IRQ_TYPE_NONE:
@ -230,10 +257,11 @@ static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
return gnr_gpio_configure_line(gc, pin, mask, set);
return gnr_gpio_configure_line(gc, hwirq, GNR_CFG_DW_RX_MASK, set);
}
static const struct irq_chip gnr_gpio_irq_chip = {
.name = "gpio-graniterapids",
.irq_ack = gnr_gpio_irq_ack,
.irq_mask = gnr_gpio_irq_mask,
.irq_unmask = gnr_gpio_irq_unmask,
@ -291,6 +319,7 @@ static int gnr_gpio_probe(struct platform_device *pdev)
struct gnr_gpio *priv;
void __iomem *regs;
int irq, ret;
u32 offset;
priv = devm_kzalloc(dev, struct_size(priv, pad_backup, num_backup_pins), GFP_KERNEL);
if (!priv)
@ -302,6 +331,10 @@ static int gnr_gpio_probe(struct platform_device *pdev)
if (IS_ERR(regs))
return PTR_ERR(regs);
priv->reg_base = regs;
offset = readl(priv->reg_base + GNR_CFG_PADBAR);
priv->pad_base = priv->reg_base + offset;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@ -311,8 +344,6 @@ static int gnr_gpio_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "failed to request interrupt\n");
priv->reg_base = regs + readl(regs + GNR_CFG_BAR);
gnr_gpio_init_pin_ro_bits(dev, priv->reg_base + GNR_CFG_LOCK_OFFSET,
priv->ro_bitmap);
@ -324,7 +355,6 @@ static int gnr_gpio_probe(struct platform_device *pdev)
girq = &priv->gc.irq;
gpio_irq_chip_set_chip(girq, &gnr_gpio_irq_chip);
girq->chip->name = dev_name(dev);
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;

View File

@ -3,6 +3,9 @@
* GPIO library for the ACCES IDIO-16 family
* Copyright (C) 2022 William Breathitt Gray
*/
#define DEFAULT_SYMBOL_NAMESPACE "GPIO_IDIO_16"
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/err.h>
@ -14,8 +17,6 @@
#include "gpio-idio-16.h"
#define DEFAULT_SYMBOL_NAMESPACE "GPIO_IDIO_16"
#define IDIO_16_DAT_BASE 0x0
#define IDIO_16_OUT_BASE IDIO_16_DAT_BASE
#define IDIO_16_IN_BASE (IDIO_16_DAT_BASE + 1)

View File

@ -82,9 +82,9 @@ static int ljca_gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
int ret;
mutex_lock(&ljca_gpio->trans_lock);
packet->num = 1;
packet->item[0].index = gpio_id;
packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];
packet->num = 1;
ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_CONFIG, (u8 *)packet,
struct_size(packet, item, packet->num), NULL, 0);