mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
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:
commit
29f9f8e1fc
@ -422,7 +422,7 @@ config GPIO_OMAP
|
||||
Say yes here to enable GPIO support for TI OMAP SoCs.
|
||||
|
||||
config GPIO_PL061
|
||||
bool "PrimeCell PL061 GPIO support"
|
||||
tristate "PrimeCell PL061 GPIO support"
|
||||
depends on ARM_AMBA
|
||||
select IRQ_DOMAIN
|
||||
select GPIOLIB_IRQCHIP
|
||||
|
@ -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
|
||||
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
|
||||
|
||||
|
@ -36,9 +36,19 @@
|
||||
#define SIO_F71889A_ID 0x1005 /* F71889A chipset ID */
|
||||
#define SIO_F81866_ID 0x1010 /* F81866 chipset ID */
|
||||
#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[] = {
|
||||
"f71869",
|
||||
@ -48,6 +58,7 @@ static const char * const f7188x_names[] = {
|
||||
"f71889f",
|
||||
"f81866",
|
||||
"f81804",
|
||||
"f81865",
|
||||
};
|
||||
|
||||
struct f7188x_sio {
|
||||
@ -233,6 +244,15 @@ static struct f7188x_gpio_bank f81804_gpio_bank[] = {
|
||||
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)
|
||||
{
|
||||
@ -425,6 +445,10 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
|
||||
data->nr_bank = ARRAY_SIZE(f81804_gpio_bank);
|
||||
data->bank = f81804_gpio_bank;
|
||||
break;
|
||||
case f81865:
|
||||
data->nr_bank = ARRAY_SIZE(f81865_gpio_bank);
|
||||
data->bank = f81865_gpio_bank;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -490,6 +514,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio)
|
||||
case SIO_F81804_ID:
|
||||
sio->type = f81804;
|
||||
break;
|
||||
case SIO_F81865_ID:
|
||||
sio->type = f81865;
|
||||
break;
|
||||
default:
|
||||
pr_info(DRVNAME ": Unsupported Fintek device 0x%04x\n", devid);
|
||||
goto err;
|
||||
|
@ -306,37 +306,39 @@ static const struct regmap_config pca953x_i2c_regmap = {
|
||||
.writeable_reg = pca953x_writeable_register,
|
||||
.volatile_reg = pca953x_volatile_register,
|
||||
|
||||
.disable_locking = true,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
/* REVISIT: should be 0x7f but some 24 bit chips use REG_ADDR_AI */
|
||||
.max_register = 0xff,
|
||||
.max_register = 0x7f,
|
||||
};
|
||||
|
||||
static u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off,
|
||||
bool write, bool addrinc)
|
||||
static const struct regmap_config pca953x_ai_i2c_regmap = {
|
||||
.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 addr = (reg & PCAL_GPIO_MASK) << bank_shift;
|
||||
int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
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)
|
||||
{
|
||||
u8 regaddr = pca953x_recalc_addr(chip, reg, 0, false, true);
|
||||
u8 regaddr = pca953x_recalc_addr(chip, reg, 0);
|
||||
u8 value[MAX_BANK];
|
||||
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)
|
||||
{
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off,
|
||||
true, false);
|
||||
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off);
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
int ret;
|
||||
|
||||
@ -388,10 +389,8 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned off, int val)
|
||||
{
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off,
|
||||
true, false);
|
||||
u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off,
|
||||
true, false);
|
||||
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off);
|
||||
u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off);
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
int ret;
|
||||
|
||||
@ -411,8 +410,7 @@ exit:
|
||||
static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
|
||||
{
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
u8 inreg = pca953x_recalc_addr(chip, chip->regs->input, off,
|
||||
true, false);
|
||||
u8 inreg = pca953x_recalc_addr(chip, chip->regs->input, off);
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
u32 reg_val;
|
||||
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)
|
||||
{
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off,
|
||||
true, false);
|
||||
u8 outreg = pca953x_recalc_addr(chip, chip->regs->output, off);
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
|
||||
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)
|
||||
{
|
||||
struct pca953x_chip *chip = gpiochip_get_data(gc);
|
||||
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off,
|
||||
true, false);
|
||||
u8 dirreg = pca953x_recalc_addr(chip, chip->regs->direction, off);
|
||||
u8 bit = BIT(off % BANK_SZ);
|
||||
u32 reg_val;
|
||||
int ret;
|
||||
@ -466,6 +462,23 @@ static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
|
||||
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,
|
||||
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 long config)
|
||||
{
|
||||
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,
|
||||
true, false);
|
||||
u8 pull_en_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_EN, offset);
|
||||
u8 pull_sel_reg = pca953x_recalc_addr(chip, PCAL953X_PULL_SEL, offset);
|
||||
u8 bit = BIT(offset % BANK_SZ);
|
||||
int ret;
|
||||
|
||||
@ -551,6 +562,7 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
|
||||
gc->get = pca953x_gpio_get_value;
|
||||
gc->set = pca953x_gpio_set_value;
|
||||
gc->get_direction = pca953x_gpio_get_direction;
|
||||
gc->get_multiple = pca953x_gpio_get_multiple;
|
||||
gc->set_multiple = pca953x_gpio_set_multiple;
|
||||
gc->set_config = pca953x_gpio_set_config;
|
||||
gc->can_sleep = true;
|
||||
@ -863,6 +875,7 @@ static int pca953x_probe(struct i2c_client *client,
|
||||
int ret;
|
||||
u32 invert = 0;
|
||||
struct regulator *reg;
|
||||
const struct regmap_config *regmap_config;
|
||||
|
||||
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (chip == NULL)
|
||||
@ -925,7 +938,17 @@ static int pca953x_probe(struct i2c_client *client,
|
||||
|
||||
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)) {
|
||||
ret = PTR_ERR(chip->regmap);
|
||||
goto err_exit;
|
||||
@ -956,7 +979,6 @@ static int pca953x_probe(struct i2c_client *client,
|
||||
/* initialize cached registers from their original values.
|
||||
* 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) {
|
||||
chip->regs = &pca953x_regs;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/device.h>
|
||||
@ -408,6 +409,7 @@ static const struct amba_id pl061_ids[] = {
|
||||
},
|
||||
{ 0, 0 },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(amba, pl061_ids);
|
||||
|
||||
static struct amba_driver pl061_gpio_driver = {
|
||||
.drv = {
|
||||
@ -419,9 +421,6 @@ static struct amba_driver pl061_gpio_driver = {
|
||||
.id_table = pl061_ids,
|
||||
.probe = pl061_probe,
|
||||
};
|
||||
module_amba_driver(pl061_gpio_driver);
|
||||
|
||||
static int __init pl061_gpio_init(void)
|
||||
{
|
||||
return amba_driver_register(&pl061_gpio_driver);
|
||||
}
|
||||
device_initcall(pl061_gpio_init);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -894,6 +894,7 @@ static const struct of_device_id tegra186_gpio_of_match[] = {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match);
|
||||
|
||||
static struct platform_driver tegra186_gpio_driver = {
|
||||
.driver = {
|
||||
|
@ -122,7 +122,7 @@ static int xgene_gpio_sb_to_irq(struct gpio_chip *gc, u32 gpio)
|
||||
fwspec.fwnode = gc->parent->fwnode;
|
||||
fwspec.param_count = 2;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,11 @@ void devprop_gpiochip_set_names(struct gpio_chip *chip,
|
||||
if (count < 0)
|
||||
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;
|
||||
}
|
||||
|
||||
names = kcalloc(count, sizeof(*names), GFP_KERNEL);
|
||||
if (!names)
|
||||
|
@ -344,6 +344,12 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
if (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);
|
||||
if (ret < 0) {
|
||||
gpiod_put(desc);
|
||||
@ -585,6 +591,10 @@ static struct gpio_desc *of_parse_own_gpio(struct device_node *np,
|
||||
*lflags |= GPIO_ACTIVE_LOW;
|
||||
if (xlate_flags & OF_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"))
|
||||
*dflags |= GPIOD_IN;
|
||||
|
@ -49,6 +49,18 @@ struct gpio_flag flagnames[] = {
|
||||
.name = "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)
|
||||
|
Loading…
Reference in New Issue
Block a user