gpio updates for v5.8-rc1 - part1

- correct the IRQ type used in to_irq() in gpio-xgene-sb
 - add new item to the TODO list
 - support building gpio-pl061 as module
 - improve pull-up/down support on GPIO expanders in device-tree
 - several improvements in gpio-pca953x
 - emit a warning for too long GPIO line names
 - add MODULE_DEVICE_TABLE to gpio-tegra186
 - add support for new variant to gpio-f7188x
 - lsgpio can now display bias flags
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAl6xlyIACgkQEacuoBRx
 13KzDg/+NP0kPNGE+aU1vqqUWNpADFP0vkJ0skoWA7wr4NeMtG9rfPMeURZQBqfl
 AYDLUi5aJabBs1EqxTztgd76zGJ+nqq8gdTJigzwwCuPjviDYbQYYjr51W0mQ72h
 t9NNcELdsBdv+ZrIF6phz1ArML6426gkCIq4IsSLK57scZ3teTRjqJvqFfbv8tsD
 ewSNblY7ASqObS8RzbTok94CjT/fP8O1Ja1Xz5p0Uwpq8EdI/UglzCQFWDq9d3dv
 qizhrCCGffj1Al3VQwDjmZJHfx/h1pjYCxVMEvy8XTjFOZ4rLopmQo6e0r5WJy4Q
 F9+kEHmUlV2lXiI6DFSssNUfl43iAFFjvK7TABUipfPfddg981WUgu6l/ACnoonE
 dEiPQc7i9pl+Nl74Hbh9UAmaB95TqW0QoGiKgi9ImZFqMcvnXcrn+iORRTF2iL0X
 fzw9jfjstEpVBjAOvomtAcfzElkmRlCK4strP4/Wo7jb4hw2HBlfcS2XMJoMi/Ez
 jRUjBlZwchXbk7VdFKsIoZAf+aVS7s1lREGDbtVbgXsmq8fvpLylEgpR3KHs0q7t
 Zrs6TpyiQX1zrc9uA3FSRYwSKjdPQwdZ+4K6zU5TmKf4QW3tm/XiHmUegC7PYeNf
 7p9SmkKK1iy4g+ECLkMRZBKM7gF9t1V1jfHmxV7AWcSV7Hh31EU=
 =1vvZ
 -----END PGP SIGNATURE-----

Merge tag 'gpio-updates-for-v5.8-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into devel

gpio updates for v5.8-rc1 - part1

- correct the IRQ type used in to_irq() in gpio-xgene-sb
- add new item to the TODO list
- support building gpio-pl061 as module
- improve pull-up/down support on GPIO expanders in device-tree
- several improvements in gpio-pca953x
- emit a warning for too long GPIO line names
- add MODULE_DEVICE_TABLE to gpio-tegra186
- add support for new variant to gpio-f7188x
- lsgpio can now display bias flags
This commit is contained in:
Linus Walleij 2020-05-09 00:33:32 +02:00
commit 29f9f8e1fc
10 changed files with 123 additions and 45 deletions

View File

@ -422,7 +422,7 @@ config GPIO_OMAP
Say yes here to enable GPIO support for TI OMAP SoCs. Say yes here to enable GPIO support for TI OMAP SoCs.
config GPIO_PL061 config GPIO_PL061
bool "PrimeCell PL061 GPIO support" tristate "PrimeCell PL061 GPIO support"
depends on ARM_AMBA depends on ARM_AMBA
select IRQ_DOMAIN select IRQ_DOMAIN
select GPIOLIB_IRQCHIP select GPIOLIB_IRQCHIP

View File

@ -99,6 +99,10 @@ similar and probe a proper driver in the gpiolib subsystem.
In some cases it makes sense to create a GPIO chip from the local driver In some cases it makes sense to create a GPIO chip from the local driver
for a few GPIOs. Those should stay where they are. for a few GPIOs. Those should stay where they are.
At the same time it makes sense to get rid of code duplication in existing or
new coming drivers. For example, gpio-ml-ioh should be incorporated into
gpio-pch. In similar way gpio-intel-mid into gpio-pxa.
Generic MMIO GPIO Generic MMIO GPIO

View File

@ -36,9 +36,19 @@
#define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */ #define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */
#define SIO_F81866_ID 0x1010 /* F81866 chipset ID */ #define SIO_F81866_ID 0x1010 /* F81866 chipset ID */
#define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same for f81966 */ #define SIO_F81804_ID 0x1502 /* F81804 chipset ID, same for f81966 */
#define SIO_F81865_ID 0x0704 /* F81865 chipset ID */
enum chips { f71869, f71869a, f71882fg, f71889a, f71889f, f81866, f81804 }; enum chips {
f71869,
f71869a,
f71882fg,
f71889a,
f71889f,
f81866,
f81804,
f81865,
};
static const char * const f7188x_names[] = { static const char * const f7188x_names[] = {
"f71869", "f71869",
@ -48,6 +58,7 @@ static const char * const f7188x_names[] = {
"f71889f", "f71889f",
"f81866", "f81866",
"f81804", "f81804",
"f81865",
}; };
struct f7188x_sio { struct f7188x_sio {
@ -233,6 +244,15 @@ static struct f7188x_gpio_bank f81804_gpio_bank[] = {
F7188X_GPIO_BANK(90, 8, 0x98), F7188X_GPIO_BANK(90, 8, 0x98),
}; };
static struct f7188x_gpio_bank f81865_gpio_bank[] = {
F7188X_GPIO_BANK(0, 8, 0xF0),
F7188X_GPIO_BANK(10, 8, 0xE0),
F7188X_GPIO_BANK(20, 8, 0xD0),
F7188X_GPIO_BANK(30, 8, 0xC0),
F7188X_GPIO_BANK(40, 8, 0xB0),
F7188X_GPIO_BANK(50, 8, 0xA0),
F7188X_GPIO_BANK(60, 5, 0x90),
};
static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
{ {
@ -425,6 +445,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
data->nr_bank = ARRAY_SIZE(f81804_gpio_bank); data->nr_bank = ARRAY_SIZE(f81804_gpio_bank);
data->bank = f81804_gpio_bank; data->bank = f81804_gpio_bank;
break; break;
case f81865:
data->nr_bank = ARRAY_SIZE(f81865_gpio_bank);
data->bank = f81865_gpio_bank;
break;
default: default:
return -ENODEV; return -ENODEV;
} }
@ -490,6 +514,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
case SIO_F81804_ID: case SIO_F81804_ID:
sio->type = f81804; sio->type = f81804;
break; break;
case SIO_F81865_ID:
sio->type = f81865;
break;
default: default:
pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid); pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid);
goto err; goto err;

View File

@ -306,37 +306,39 @@ static const struct regmap_config pca953x_i2c_regmap = {
.writeable_reg = pca953x_writeable_register, .writeable_reg = pca953x_writeable_register,
.volatile_reg = pca953x_volatile_register, .volatile_reg = pca953x_volatile_register,
.disable_locking = true,
.cache_type = REGCACHE_RBTREE, .cache_type = REGCACHE_RBTREE,
/* REVISIT: should be 0x7f but some 24 bit chips use REG_ADDR_AI */ .max_register = 0x7f,
.max_register = 0xff,
}; };
static u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off, static const struct regmap_config pca953x_ai_i2c_regmap = {
bool write, bool addrinc) .reg_bits = 8,
.val_bits = 8,
.read_flag_mask = REG_ADDR_AI,
.write_flag_mask = REG_ADDR_AI,
.readable_reg = pca953x_readable_register,
.writeable_reg = pca953x_writeable_register,
.volatile_reg = pca953x_volatile_register,
.cache_type = REGCACHE_RBTREE,
.max_register = 0x7f,
};
static u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off)
{ {
int bank_shift = pca953x_bank_shift(chip); int bank_shift = pca953x_bank_shift(chip);
int addr = (reg & PCAL_GPIO_MASK) << bank_shift; int addr = (reg & PCAL_GPIO_MASK) << bank_shift;
int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1; int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
u8 regaddr = pinctrl | addr | (off / BANK_SZ); u8 regaddr = pinctrl | addr | (off / BANK_SZ);
/* Single byte read doesn't need AI bit set. */
if (!addrinc)
return regaddr;
/* Chips with 24 and more GPIOs always support Auto Increment */
if (write && NBANK(chip) > 2)
regaddr |= REG_ADDR_AI;
/* PCA9575 needs address-increment on multi-byte writes */
if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE)
regaddr |= REG_ADDR_AI;
return regaddr; return regaddr;
} }
static int pca953x_write_regs(struct pca953x_chip *chip, int reg, unsigned long *val) static int pca953x_write_regs(struct pca953x_chip *chip, int reg, unsigned long *val)
{ {
u8 regaddr = pca953x_recalc_addr(chip, reg, 0, true, true); u8 regaddr = pca953x_recalc_addr(chip, reg, 0);
u8 value[MAX_BANK]; u8 value[MAX_BANK];
int i, ret; int i, ret;
@ -354,7 +356,7 @@ static int pca953x_write_regs(struct pca953x_chip *chip, int reg, unsigned long
static int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *val) static int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *val)
{ {
u8 regaddr = pca953x_recalc_addr(chip, reg, 0, false, true); u8 regaddr = pca953x_recalc_addr(chip, reg, 0);
u8 value[MAX_BANK]; u8 value[MAX_BANK];
int i, ret; int i, ret;
@ -373,8 +375,7 @@ static int pca953x_read_regs(struct pca953x_chip *chip, int reg, unsigned long *
static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off);
true, false);
u8 bit = BIT(off % BANK_SZ); u8 bit = BIT(off % BANK_SZ);
int ret; int ret;
@ -388,10 +389,8 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
unsigned off, int val) unsigned off, int val)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off);
true, false); u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off);
u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off,
true, false);
u8 bit = BIT(off % BANK_SZ); u8 bit = BIT(off % BANK_SZ);
int ret; int ret;
@ -411,8 +410,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 inreg = pca953x_recalc_addr(chip, chip->regs->input, off, u8 inreg = pca953x_recalc_addr(chip, chip->regs->input, off);
true, false);
u8 bit = BIT(off % BANK_SZ); u8 bit = BIT(off % BANK_SZ);
u32 reg_val; u32 reg_val;
int ret; int ret;
@ -436,8 +434,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off, u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off);
true, false);
u8 bit = BIT(off % BANK_SZ); u8 bit = BIT(off % BANK_SZ);
mutex_lock(&chip->i2c_lock); mutex_lock(&chip->i2c_lock);
@ -448,8 +445,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off, u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off);
true, false);
u8 bit = BIT(off % BANK_SZ); u8 bit = BIT(off % BANK_SZ);
u32 reg_val; u32 reg_val;
int ret; int ret;
@ -466,6 +462,23 @@ static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
return GPIO_LINE_DIRECTION_OUT; return GPIO_LINE_DIRECTION_OUT;
} }
static int pca953x_gpio_get_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits)
{
struct pca953x_chip *chip = gpiochip_get_data(gc);
DECLARE_BITMAP(reg_val, MAX_LINE);
int ret;
mutex_lock(&chip->i2c_lock);
ret = pca953x_read_regs(chip, chip->regs->input, reg_val);
mutex_unlock(&chip->i2c_lock);
if (ret)
return ret;
bitmap_replace(bits, bits, reg_val, mask, gc->ngpio);
return 0;
}
static void pca953x_gpio_set_multiple(struct gpio_chip *gc, static void pca953x_gpio_set_multiple(struct gpio_chip *gc,
unsigned long *mask, unsigned long *bits) unsigned long *mask, unsigned long *bits)
{ {
@ -489,10 +502,8 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip,
unsigned int offset, unsigned int offset,
unsigned long config) unsigned long config)
{ {
u8 pull_en_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_EN, offset, u8 pull_en_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_EN, offset);
true, false); u8 pull_sel_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_SEL, offset);
u8 pull_sel_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_SEL, offset,
true, false);
u8 bit = BIT(offset % BANK_SZ); u8 bit = BIT(offset % BANK_SZ);
int ret; int ret;
@ -551,6 +562,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
gc->get = pca953x_gpio_get_value; gc->get = pca953x_gpio_get_value;
gc->set = pca953x_gpio_set_value; gc->set = pca953x_gpio_set_value;
gc->get_direction = pca953x_gpio_get_direction; gc->get_direction = pca953x_gpio_get_direction;
gc->get_multiple = pca953x_gpio_get_multiple;
gc->set_multiple = pca953x_gpio_set_multiple; gc->set_multiple = pca953x_gpio_set_multiple;
gc->set_config = pca953x_gpio_set_config; gc->set_config = pca953x_gpio_set_config;
gc->can_sleep = true; gc->can_sleep = true;
@ -863,6 +875,7 @@ static int pca953x_probe(struct i2c_client *client,
int ret; int ret;
u32 invert = 0; u32 invert = 0;
struct regulator *reg; struct regulator *reg;
const struct regmap_config *regmap_config;
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL) if (chip == NULL)
@ -925,7 +938,17 @@ static int pca953x_probe(struct i2c_client *client,
i2c_set_clientdata(client, chip); i2c_set_clientdata(client, chip);
chip->regmap = devm_regmap_init_i2c(client, &pca953x_i2c_regmap); pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
if (NBANK(chip) > 2 || PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) {
dev_info(&client->dev, "using AI\n");
regmap_config = &pca953x_ai_i2c_regmap;
} else {
dev_info(&client->dev, "using no AI\n");
regmap_config = &pca953x_i2c_regmap;
}
chip->regmap = devm_regmap_init_i2c(client, regmap_config);
if (IS_ERR(chip->regmap)) { if (IS_ERR(chip->regmap)) {
ret = PTR_ERR(chip->regmap); ret = PTR_ERR(chip->regmap);
goto err_exit; goto err_exit;
@ -956,7 +979,6 @@ static int pca953x_probe(struct i2c_client *client,
/* initialize cached registers from their original values. /* initialize cached registers from their original values.
* we can't share this chip with another i2c master. * we can't share this chip with another i2c master.
*/ */
pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) { if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) {
chip->regs = &pca953x_regs; chip->regs = &pca953x_regs;

View File

@ -16,6 +16,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/irqchip/chained_irq.h> #include <linux/irqchip/chained_irq.h>
#include <linux/module.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/device.h> #include <linux/device.h>
@ -408,6 +409,7 @@ static const struct amba_id pl061_ids[] = {
}, },
{ 0, 0 }, { 0, 0 },
}; };
MODULE_DEVICE_TABLE(amba, pl061_ids);
static struct amba_driver pl061_gpio_driver = { static struct amba_driver pl061_gpio_driver = {
.drv = { .drv = {
@ -419,9 +421,6 @@ static struct amba_driver pl061_gpio_driver = {
.id_table = pl061_ids, .id_table = pl061_ids,
.probe = pl061_probe, .probe = pl061_probe,
}; };
module_amba_driver(pl061_gpio_driver);
static int __init pl061_gpio_init(void) MODULE_LICENSE("GPL v2");
{
return amba_driver_register(&pl061_gpio_driver);
}
device_initcall(pl061_gpio_init);

View File

@ -894,6 +894,7 @@ static const struct of_device_id tegra186_gpio_of_match[] = {
/* sentinel */ /* sentinel */
} }
}; };
MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match);
static struct platform_driver tegra186_gpio_driver = { static struct platform_driver tegra186_gpio_driver = {
.driver = { .driver = {

View File

@ -122,7 +122,7 @@ static int xgene_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio)
fwspec.fwnode = gc->parent->fwnode; fwspec.fwnode = gc->parent->fwnode;
fwspec.param_count = 2; fwspec.param_count = 2;
fwspec.param[0] = GPIO_TO_HWIRQ(priv, gpio); fwspec.param[0] = GPIO_TO_HWIRQ(priv, gpio);
fwspec.param[1] = IRQ_TYPE_NONE; fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
return irq_create_fwspec_mapping(&fwspec); return irq_create_fwspec_mapping(&fwspec);
} }

View File

@ -37,8 +37,11 @@ void devprop_gpiochip_set_names(struct gpio_chip *chip,
if (count < 0) if (count < 0)
return; return;
if (count > gdev->ngpio) if (count > gdev->ngpio) {
dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d",
count, gdev->ngpio);
count = gdev->ngpio; count = gdev->ngpio;
}
names = kcalloc(count, sizeof(*names), GFP_KERNEL); names = kcalloc(count, sizeof(*names), GFP_KERNEL);
if (!names) if (!names)

View File

@ -344,6 +344,12 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
if (transitory) if (transitory)
lflags |= GPIO_TRANSITORY; lflags |= GPIO_TRANSITORY;
if (flags & OF_GPIO_PULL_UP)
lflags |= GPIO_PULL_UP;
if (flags & OF_GPIO_PULL_DOWN)
lflags |= GPIO_PULL_DOWN;
ret = gpiod_configure_flags(desc, propname, lflags, dflags); ret = gpiod_configure_flags(desc, propname, lflags, dflags);
if (ret < 0) { if (ret < 0) {
gpiod_put(desc); gpiod_put(desc);
@ -585,6 +591,10 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
*lflags |= GPIO_ACTIVE_LOW; *lflags |= GPIO_ACTIVE_LOW;
if (xlate_flags & OF_GPIO_TRANSITORY) if (xlate_flags & OF_GPIO_TRANSITORY)
*lflags |= GPIO_TRANSITORY; *lflags |= GPIO_TRANSITORY;
if (xlate_flags & OF_GPIO_PULL_UP)
*lflags |= GPIO_PULL_UP;
if (xlate_flags & OF_GPIO_PULL_DOWN)
*lflags |= GPIO_PULL_DOWN;
if (of_property_read_bool(np, "input")) if (of_property_read_bool(np, "input"))
*dflags |= GPIOD_IN; *dflags |= GPIOD_IN;

View File

@ -49,6 +49,18 @@ struct gpio_flag flagnames[] = {
.name = "open-source", .name = "open-source",
.mask = GPIOLINE_FLAG_OPEN_SOURCE, .mask = GPIOLINE_FLAG_OPEN_SOURCE,
}, },
{
.name = "pull-up",
.mask = GPIOLINE_FLAG_BIAS_PULL_UP,
},
{
.name = "pull-down",
.mask = GPIOLINE_FLAG_BIAS_PULL_DOWN,
},
{
.name = "bias-disabled",
.mask = GPIOLINE_FLAG_BIAS_DISABLE,
},
}; };
void print_flags(unsigned long flags) void print_flags(unsigned long flags)