diff options
-rw-r--r-- | Documentation/driver-api/gpio/consumer.rst | 10 | ||||
-rw-r--r-- | Documentation/driver-api/gpio/driver.rst | 11 | ||||
-rw-r--r-- | MAINTAINERS | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-aspeed-sgpio.c | 178 | ||||
-rw-r--r-- | drivers/gpio/gpio-brcmstb.c | 45 | ||||
-rw-r--r-- | drivers/gpio/gpio-mt7621.c | 1 | ||||
-rw-r--r-- | drivers/gpio/gpio-rcar.c | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-tegra186.c | 30 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-devres.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 16 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 32 | ||||
-rw-r--r-- | include/linux/gpio/consumer.h | 8 | ||||
-rw-r--r-- | include/linux/gpio/driver.h | 4 | ||||
-rw-r--r-- | include/linux/of.h | 2 | ||||
-rw-r--r-- | include/linux/of_gpio.h | 15 |
15 files changed, 205 insertions, 155 deletions
diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst index 3366a991b4aa..47869ca8ccf0 100644 --- a/Documentation/driver-api/gpio/consumer.rst +++ b/Documentation/driver-api/gpio/consumer.rst @@ -72,6 +72,10 @@ for the GPIO. Values can be: * GPIOD_OUT_HIGH_OPEN_DRAIN same as GPIOD_OUT_HIGH but also enforce the line to be electrically used with open drain. +Note that the initial value is *logical* and the physical line level depends on +whether the line is configured active high or active low (see +:ref:`active_low_semantics`). + The two last flags are used for use cases where open drain is mandatory, such as I2C: if the line is not already configured as open drain in the mappings (see board.txt), then open drain will be enforced anyway and a warning will be @@ -252,6 +256,8 @@ that can't be accessed from hardIRQ handlers, these calls act the same as the spinlock-safe calls. +.. _active_low_semantics: + The active low and open drain semantics --------------------------------------- As a consumer should not have to care about the physical line level, all of the @@ -309,9 +315,11 @@ work on the raw line value:: void gpiod_set_raw_value_cansleep(struct gpio_desc *desc, int value) int gpiod_direction_output_raw(struct gpio_desc *desc, int value) -The active low state of a GPIO can also be queried using the following call:: +The active low state of a GPIO can also be queried and toggled using the +following calls:: int gpiod_is_active_low(const struct gpio_desc *desc) + void gpiod_toggle_active_low(struct gpio_desc *desc) Note that these functions should only be used with great moderation; a driver should not have to care about the physical line level or open drain semantics. diff --git a/Documentation/driver-api/gpio/driver.rst b/Documentation/driver-api/gpio/driver.rst index d6b0d779859b..bbc53920d4dd 100644 --- a/Documentation/driver-api/gpio/driver.rst +++ b/Documentation/driver-api/gpio/driver.rst @@ -547,13 +547,10 @@ To use the helpers please keep the following in mind: the irqchip can initialize. E.g. .dev and .can_sleep shall be set up properly. -- Nominally set all handlers to handle_bad_irq() in the setup call and pass - handle_bad_irq() as flow handler parameter in gpiochip_irqchip_add() if it is - expected for GPIO driver that irqchip .set_type() callback will be called - before using/enabling each GPIO IRQ. Then set the handler to - handle_level_irq() and/or handle_edge_irq() in the irqchip .set_type() - callback depending on what your controller supports and what is requested - by the consumer. +- Nominally set gpio_irq_chip.handler to handle_bad_irq. Then, if your irqchip + is cascaded, set the handler to handle_level_irq() and/or handle_edge_irq() + in the irqchip .set_type() callback depending on what your controller + supports and what is requested by the consumer. Locking IRQ usage diff --git a/MAINTAINERS b/MAINTAINERS index a61f4f3b78a9..6ffb5cbbeb93 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20323,7 +20323,7 @@ R: Srinivas Neeli <[email protected]> R: Michal Simek <[email protected]> S: Maintained F: Documentation/devicetree/bindings/gpio/gpio-xilinx.txt -F: Documentation/devicetree/bindings/gpio/gpio-zynq.txt +F: Documentation/devicetree/bindings/gpio/gpio-zynq.yaml F: drivers/gpio/gpio-xilinx.c F: drivers/gpio/gpio-zynq.c diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c index 64e54f8c30d2..191b82a2560c 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -17,37 +17,30 @@ #include <linux/spinlock.h> #include <linux/string.h> -/* - * MAX_NR_HW_GPIO represents the number of actual hardware-supported GPIOs (ie, - * slots within the clocked serial GPIO data). Since each HW GPIO is both an - * input and an output, we provide MAX_NR_HW_GPIO * 2 lines on our gpiochip - * device. - * - * We use SGPIO_OUTPUT_OFFSET to define the split between the inputs and - * outputs; the inputs start at line 0, the outputs start at OUTPUT_OFFSET. - */ -#define MAX_NR_HW_SGPIO 80 -#define SGPIO_OUTPUT_OFFSET MAX_NR_HW_SGPIO - #define ASPEED_SGPIO_CTRL 0x54 -#define ASPEED_SGPIO_PINS_MASK GENMASK(9, 6) #define ASPEED_SGPIO_CLK_DIV_MASK GENMASK(31, 16) #define ASPEED_SGPIO_ENABLE BIT(0) +#define ASPEED_SGPIO_PINS_SHIFT 6 + +struct aspeed_sgpio_pdata { + const u32 pin_mask; +}; struct aspeed_sgpio { struct gpio_chip chip; + struct irq_chip intc; struct clk *pclk; spinlock_t lock; void __iomem *base; int irq; - int n_sgpio; }; struct aspeed_sgpio_bank { - uint16_t val_regs; - uint16_t rdata_reg; - uint16_t irq_regs; + u16 val_regs; + u16 rdata_reg; + u16 irq_regs; + u16 tolerance_regs; const char names[4][3]; }; @@ -63,19 +56,29 @@ static const struct aspeed_sgpio_bank aspeed_sgpio_banks[] = { .val_regs = 0x0000, .rdata_reg = 0x0070, .irq_regs = 0x0004, + .tolerance_regs = 0x0018, .names = { "A", "B", "C", "D" }, }, { .val_regs = 0x001C, .rdata_reg = 0x0074, .irq_regs = 0x0020, + .tolerance_regs = 0x0034, .names = { "E", "F", "G", "H" }, }, { .val_regs = 0x0038, .rdata_reg = 0x0078, .irq_regs = 0x003C, - .names = { "I", "J" }, + .tolerance_regs = 0x0050, + .names = { "I", "J", "K", "L" }, + }, + { + .val_regs = 0x0090, + .rdata_reg = 0x007C, + .irq_regs = 0x0094, + .tolerance_regs = 0x00A8, + .names = { "M", "N", "O", "P" }, }, }; @@ -87,6 +90,7 @@ enum aspeed_sgpio_reg { reg_irq_type1, reg_irq_type2, reg_irq_status, + reg_tolerance, }; #define GPIO_VAL_VALUE 0x00 @@ -115,15 +119,17 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio, return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2; case reg_irq_status: return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS; + case reg_tolerance: + return gpio->base + bank->tolerance_regs; default: /* acturally if code runs to here, it's an error case */ BUG(); } } -#define GPIO_BANK(x) ((x % SGPIO_OUTPUT_OFFSET) >> 5) -#define GPIO_OFFSET(x) ((x % SGPIO_OUTPUT_OFFSET) & 0x1f) -#define GPIO_BIT(x) BIT(GPIO_OFFSET(x)) +#define GPIO_BANK(x) ((x) >> 6) +#define GPIO_OFFSET(x) ((x) & GENMASK(5, 0)) +#define GPIO_BIT(x) BIT(GPIO_OFFSET(x) >> 1) static const struct aspeed_sgpio_bank *to_bank(unsigned int offset) { @@ -138,39 +144,25 @@ static const struct aspeed_sgpio_bank *to_bank(unsigned int offset) static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc, unsigned long *valid_mask, unsigned int ngpios) { - struct aspeed_sgpio *sgpio = gpiochip_get_data(gc); - int n = sgpio->n_sgpio; - int c = SGPIO_OUTPUT_OFFSET - n; - - WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2); - - /* input GPIOs in the lower range */ - bitmap_set(valid_mask, 0, n); - bitmap_clear(valid_mask, n, c); - - /* output GPIOS above SGPIO_OUTPUT_OFFSET */ - bitmap_set(valid_mask, SGPIO_OUTPUT_OFFSET, n); - bitmap_clear(valid_mask, SGPIO_OUTPUT_OFFSET + n, c); - + bitmap_set(valid_mask, 0, ngpios); return 0; } static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc, unsigned long *valid_mask, unsigned int ngpios) { - struct aspeed_sgpio *sgpio = gpiochip_get_data(gc); - int n = sgpio->n_sgpio; + unsigned int i; - WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2); - - /* input GPIOs in the lower range */ - bitmap_set(valid_mask, 0, n); - bitmap_clear(valid_mask, n, ngpios - n); + /* input GPIOs are even bits */ + for (i = 0; i < ngpios; i++) { + if (i % 2) + clear_bit(i, valid_mask); + } } static bool aspeed_sgpio_is_input(unsigned int offset) { - return offset < SGPIO_OUTPUT_OFFSET; + return !(offset % 2); } static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset) @@ -412,14 +404,6 @@ static void aspeed_sgpio_irq_handler(struct irq_desc *desc) chained_irq_exit(ic, desc); } -static struct irq_chip aspeed_sgpio_irqchip = { - .name = "aspeed-sgpio", - .irq_ack = aspeed_sgpio_irq_ack, - .irq_mask = aspeed_sgpio_irq_mask, - .irq_unmask = aspeed_sgpio_irq_unmask, - .irq_set_type = aspeed_sgpio_set_type, -}; - static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, struct platform_device *pdev) { @@ -442,8 +426,14 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_status)); } + gpio->intc.name = dev_name(&pdev->dev); + gpio->intc.irq_ack = aspeed_sgpio_irq_ack; + gpio->intc.irq_mask = aspeed_sgpio_irq_mask; + gpio->intc.irq_unmask = aspeed_sgpio_irq_unmask; + gpio->intc.irq_set_type = aspeed_sgpio_set_type; + irq = &gpio->chip.irq; - irq->chip = &aspeed_sgpio_irqchip; + irq->chip = &gpio->intc; irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask; irq->handler = handle_bad_irq; irq->default_type = IRQ_TYPE_NONE; @@ -466,9 +456,56 @@ static int aspeed_sgpio_setup_irqs(struct aspeed_sgpio *gpio, return 0; } +static const struct aspeed_sgpio_pdata ast2400_sgpio_pdata = { + .pin_mask = GENMASK(9, 6), +}; + +static int aspeed_sgpio_reset_tolerance(struct gpio_chip *chip, + unsigned int offset, bool enable) +{ + struct aspeed_sgpio *gpio = gpiochip_get_data(chip); + unsigned long flags; + void __iomem *reg; + u32 val; + + reg = bank_reg(gpio, to_bank(offset), reg_tolerance); + + spin_lock_irqsave(&gpio->lock, flags); + + val = readl(reg); + + if (enable) + val |= GPIO_BIT(offset); + else + val &= ~GPIO_BIT(offset); + + writel(val, reg); + + spin_unlock_irqrestore(&gpio->lock, flags); + + return 0; +} + +static int aspeed_sgpio_set_config(struct gpio_chip *chip, unsigned int offset, + unsigned long config) +{ + unsigned long param = pinconf_to_config_param(config); + u32 arg = pinconf_to_config_argument(config); + + if (param == PIN_CONFIG_PERSIST_STATE) + return aspeed_sgpio_reset_tolerance(chip, offset, arg); + + return -ENOTSUPP; +} + +static const struct aspeed_sgpio_pdata ast2600_sgpiom_pdata = { + .pin_mask = GENMASK(10, 6), +}; + static const struct of_device_id aspeed_sgpio_of_table[] = { - { .compatible = "aspeed,ast2400-sgpio" }, - { .compatible = "aspeed,ast2500-sgpio" }, + { .compatible = "aspeed,ast2400-sgpio", .data = &ast2400_sgpio_pdata, }, + { .compatible = "aspeed,ast2500-sgpio", .data = &ast2400_sgpio_pdata, }, + { .compatible = "aspeed,ast2600-sgpiom", .data = &ast2600_sgpiom_pdata, }, {} }; @@ -476,10 +513,11 @@ MODULE_DEVICE_TABLE(of, aspeed_sgpio_of_table); static int __init aspeed_sgpio_probe(struct platform_device *pdev) { + u32 nr_gpios, sgpio_freq, sgpio_clk_div, gpio_cnt_regval, pin_mask; + const struct aspeed_sgpio_pdata *pdata; struct aspeed_sgpio *gpio; - u32 nr_gpios, sgpio_freq, sgpio_clk_div; - int rc; unsigned long apb_freq; + int rc; gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL); if (!gpio) @@ -489,18 +527,23 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) if (IS_ERR(gpio->base)) return PTR_ERR(gpio->base); - rc = of_property_read_u32(pdev->dev.of_node, "ngpios", &nr_gpios); + pdata = device_get_match_data(&pdev->dev); + if (!pdata) + return -EINVAL; + + pin_mask = pdata->pin_mask; + + rc = device_property_read_u32(&pdev->dev, "ngpios", &nr_gpios); if (rc < 0) { dev_err(&pdev->dev, "Could not read ngpios property\n"); return -EINVAL; - } else if (nr_gpios > MAX_NR_HW_SGPIO) { - dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n", - MAX_NR_HW_SGPIO, nr_gpios); + } else if (nr_gpios % 8) { + dev_err(&pdev->dev, "Number of GPIOs not multiple of 8: %d\n", + nr_gpios); return -EINVAL; } - gpio->n_sgpio = nr_gpios; - rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq); + rc = device_property_read_u32(&pdev->dev, "bus-frequency", &sgpio_freq); if (rc < 0) { dev_err(&pdev->dev, "Could not read bus-frequency property\n"); return -EINVAL; @@ -531,15 +574,14 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) if (sgpio_clk_div > (1 << 16) - 1) return -EINVAL; - iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | - FIELD_PREP(ASPEED_SGPIO_PINS_MASK, (nr_gpios / 8)) | - ASPEED_SGPIO_ENABLE, - gpio->base + ASPEED_SGPIO_CTRL); + gpio_cnt_regval = ((nr_gpios / 8) << ASPEED_SGPIO_PINS_SHIFT) & pin_mask; + iowrite32(FIELD_PREP(ASPEED_SGPIO_CLK_DIV_MASK, sgpio_clk_div) | gpio_cnt_regval | + ASPEED_SGPIO_ENABLE, gpio->base + ASPEED_SGPIO_CTRL); spin_lock_init(&gpio->lock); gpio->chip.parent = &pdev->dev; - gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2; + gpio->chip.ngpio = nr_gpios * 2; gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask; gpio->chip.direction_input = aspeed_sgpio_dir_in; gpio->chip.direction_output = aspeed_sgpio_dir_out; @@ -548,7 +590,7 @@ static int __init aspeed_sgpio_probe(struct platform_device *pdev) gpio->chip.free = NULL; gpio->chip.get = aspeed_sgpio_get; gpio->chip.set = aspeed_sgpio_set; - gpio->chip.set_config = NULL; + gpio->chip.set_config = aspeed_sgpio_set_config; gpio->chip.label = dev_name(&pdev->dev); gpio->chip.base = -1; diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index fcfc1a1f1a5c..a7275159052e 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -603,49 +603,6 @@ static const struct dev_pm_ops brcmstb_gpio_pm_ops = { .resume_noirq = brcmstb_gpio_resume, }; -static void brcmstb_gpio_set_names(struct device *dev, - struct brcmstb_gpio_bank *bank) -{ - struct device_node *np = dev->of_node; - const char **names; - int nstrings, base; - unsigned int i; - - base = bank->id * MAX_GPIO_PER_BANK; - - nstrings = of_property_count_strings(np, "gpio-line-names"); - if (nstrings <= base) - /* Line names not present */ - return; - - names = devm_kcalloc(dev, MAX_GPIO_PER_BANK, sizeof(*names), - GFP_KERNEL); - if (!names) - return; - - /* - * Make sure to not index beyond the end of the number of descriptors - * of the GPIO device. - */ - for (i = 0; i < bank->width; i++) { - const char *name; - int ret; - - ret = of_property_read_string_index(np, "gpio-line-names", - base + i, &name); - if (ret) { - if (ret != -ENODATA) - dev_err(dev, "unable to name line %d: %d\n", - base + i, ret); - break; - } - if (*name) - names[i] = name; - } - - bank->gc.names = names; -} - static int brcmstb_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -759,6 +716,7 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) gc->of_xlate = brcmstb_gpio_of_xlate; /* not all ngpio lines are valid, will use bank width later */ gc->ngpio = MAX_GPIO_PER_BANK; + gc->offset = bank->id * MAX_GPIO_PER_BANK; if (priv->parent_irq > 0) gc->to_irq = brcmstb_gpio_to_irq; @@ -769,7 +727,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) need_wakeup_event |= !!__brcmstb_gpio_get_active_irqs(bank); gc->write_reg(reg_base + GIO_MASK(bank->id), 0); - brcmstb_gpio_set_names(dev, bank); err = gpiochip_add_data(gc, bank); if (err) { dev_err(dev, "Could not add gpiochip for bank %d\n", diff --git a/drivers/gpio/gpio-mt7621.c b/drivers/gpio/gpio-mt7621.c index 82fb20dca53a..5854a9343491 100644 --- a/drivers/gpio/gpio-mt7621.c +++ b/drivers/gpio/gpio-mt7621.c @@ -241,6 +241,7 @@ mediatek_gpio_bank_probe(struct device *dev, if (!rg->chip.label) return -ENOMEM; + rg->chip.offset = bank * MTK_BANK_WIDTH; rg->irq_chip.name = dev_name(dev); rg->irq_chip.parent_device = dev; rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask; diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index e7092d5fe700..ae1ffb2b230d 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -564,9 +564,9 @@ static int gpio_rcar_probe(struct platform_device *pdev) } if (p->info.has_inen) { - pm_runtime_get_sync(p->dev); + pm_runtime_get_sync(dev); gpio_rcar_enable_inputs(p); - pm_runtime_put(p->dev); + pm_runtime_put(dev); } dev_info(dev, "driving %d GPIOs\n", npins); diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index d38980b9923a..046b7c8b15d1 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -610,15 +610,21 @@ static int tegra186_gpio_probe(struct platform_device *pdev) if (!gpio) return -ENOMEM; - gpio->soc = of_device_get_match_data(&pdev->dev); + gpio->soc = device_get_match_data(&pdev->dev); gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security"); - if (IS_ERR(gpio->secure)) - return PTR_ERR(gpio->secure); + if (IS_ERR(gpio->secure)) { + gpio->secure = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(gpio->secure)) + return PTR_ERR(gpio->secure); + } gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio"); - if (IS_ERR(gpio->base)) - return PTR_ERR(gpio->base); + if (IS_ERR(gpio->base)) { + gpio->base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(gpio->base)) + return PTR_ERR(gpio->base); + } err = platform_irq_count(pdev); if (err < 0) @@ -680,11 +686,13 @@ static int tegra186_gpio_probe(struct platform_device *pdev) gpio->gpio.names = (const char * const *)names; +#if defined(CONFIG_OF_GPIO) gpio->gpio.of_node = pdev->dev.of_node; gpio->gpio.of_gpio_n_cells = 2; gpio->gpio.of_xlate = tegra186_gpio_of_xlate; +#endif /* CONFIG_OF_GPIO */ - gpio->intc.name = pdev->dev.of_node->name; + gpio->intc.name = dev_name(&pdev->dev); gpio->intc.irq_ack = tegra186_irq_ack; gpio->intc.irq_mask = tegra186_irq_mask; gpio->intc.irq_unmask = tegra186_irq_unmask; @@ -896,10 +904,20 @@ static const struct of_device_id tegra186_gpio_of_match[] = { }; MODULE_DEVICE_TABLE(of, tegra186_gpio_of_match); +static const struct acpi_device_id tegra186_gpio_acpi_match[] = { + { .id = "NVDA0108", .driver_data = (kernel_ulong_t)&tegra186_main_soc }, + { .id = "NVDA0208", .driver_data = (kernel_ulong_t)&tegra186_aon_soc }, + { .id = "NVDA0308", .driver_data = (kernel_ulong_t)&tegra194_main_soc }, + { .id = "NVDA0408", .driver_data = (kernel_ulong_t)&tegra194_aon_soc }, + {} +}; +MODULE_DEVICE_TABLE(acpi, tegra186_gpio_acpi_match); + static struct platform_driver tegra186_gpio_driver = { .driver = { .name = "tegra186-gpio", .of_match_table = tegra186_gpio_of_match, + .acpi_match_table = tegra186_gpio_acpi_match, }, .probe = tegra186_gpio_probe, }; diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c index 4a517e5dedf0..79da85d17b71 100644 --- a/drivers/gpio/gpiolib-devres.c +++ b/drivers/gpio/gpiolib-devres.c @@ -145,7 +145,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_index); * In case of error an ERR_PTR() is returned. */ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, + const struct device_node *node, const char *propname, int index, enum gpiod_flags dflags, const char *label) diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index bbcc7c073f63..0ad288ab6262 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -122,7 +122,7 @@ static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, bool of_gpio_need_valid_mask(const struct gpio_chip *gc) { int size; - struct device_node *np = gc->of_node; + const struct device_node *np = gc->of_node; size = of_property_count_u32_elems(np, "gpio-reserved-ranges"); if (size > 0 && size % 2 == 0) @@ -130,7 +130,7 @@ bool of_gpio_need_valid_mask(const struct gpio_chip *gc) return false; } -static void of_gpio_flags_quirks(struct device_node *np, +static void of_gpio_flags_quirks(const struct device_node *np, const char *propname, enum of_gpio_flags *flags, int index) @@ -236,7 +236,7 @@ static void of_gpio_flags_quirks(struct device_node *np, * value on the error condition. If @flags is not NULL the function also fills * in flags for the GPIO. */ -static struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np, +static struct gpio_desc *of_get_named_gpiod_flags(const struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags) { struct of_phandle_args gpiospec; @@ -275,7 +275,7 @@ out: return desc; } -int of_get_named_gpio_flags(struct device_node *np, const char *list_name, +int of_get_named_gpio_flags(const struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags) { struct gpio_desc *desc; @@ -303,7 +303,7 @@ EXPORT_SYMBOL_GPL(of_get_named_gpio_flags); * * In case of error an ERR_PTR() is returned. */ -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, +struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node, const char *propname, int index, enum gpiod_flags dflags, const char *label) @@ -373,7 +373,7 @@ static struct gpio_desc *of_find_spi_gpio(struct device *dev, const char *con_id enum of_gpio_flags *of_flags) { char prop_name[32]; /* 32 is max size of property name */ - struct device_node *np = dev->of_node; + const struct device_node *np = dev->of_node; struct gpio_desc *desc; /* @@ -404,7 +404,7 @@ static struct gpio_desc *of_find_spi_cs_gpio(struct device *dev, unsigned int idx, unsigned long *flags) { - struct device_node *np = dev->of_node; + const struct device_node *np = dev->of_node; if (!IS_ENABLED(CONFIG_SPI_MASTER)) return ERR_PTR(-ENOENT); @@ -440,7 +440,7 @@ static struct gpio_desc *of_find_regulator_gpio(struct device *dev, const char * "wlf,ldo1ena", /* WM8994 */ "wlf,ldo2ena", /* WM8994 */ }; - struct device_node *np = dev->of_node; + const struct device_node *np = dev->of_node; struct gpio_desc *desc; int i; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 27c07108496d..d1b9b721218f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -382,10 +382,18 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip) if (count < 0) return 0; - 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; + /* + * When offset is set in the driver side we assume the driver internally + * is using more than one gpiochip per the same device. We have to stop + * setting friendly names if the specified ones with 'gpio-line-names' + * are less than the offset in the device itself. This means all the + * lines are not present for every single pin within all the internal + * gpiochips. + */ + if (count <= chip->offset) { + dev_warn(&gdev->dev, "gpio-line-names too short (length %d), cannot map names for the gpiochip at offset %u\n", + count, chip->offset); + return 0; } names = kcalloc(count, sizeof(*names), GFP_KERNEL); @@ -400,8 +408,22 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip) return ret; } + /* + * When more that one gpiochip per device is used, 'count' can + * contain at most number gpiochips x chip->ngpio. We have to + * correctly distribute all defined lines taking into account + * chip->offset as starting point from where we will assign + * the names to pins from the 'names' array. Since property + * 'gpio-line-names' cannot contains gaps, we have to be sure + * we only assign those pins that really exists since chip->ngpio + * can be different of the chip->offset. + */ + count = (count > chip->offset) ? count - chip->offset : count; + if (count > chip->ngpio) + count = chip->ngpio; + for (i = 0; i < count; i++) - gdev->descs[i].name = names[i]; + gdev->descs[i].name = names[chip->offset + i]; kfree(names); diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 414b8f98d70f..97a28ad3393b 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -609,7 +609,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev, #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO) struct device_node; -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, +struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node, const char *propname, int index, enum gpiod_flags dflags, const char *label); @@ -619,7 +619,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, struct device_node; static inline -struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, +struct gpio_desc *gpiod_get_from_of_node(const struct device_node *node, const char *propname, int index, enum gpiod_flags dflags, const char *label) @@ -633,7 +633,7 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, struct device_node; struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, + const struct device_node *node, const char *propname, int index, enum gpiod_flags dflags, const char *label); @@ -644,7 +644,7 @@ struct device_node; static inline struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, - struct device_node *node, + const struct device_node *node, const char *propname, int index, enum gpiod_flags dflags, const char *label) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index 3a268781fcec..a0f9901dcae6 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -312,6 +312,9 @@ struct gpio_irq_chip { * get rid of the static GPIO number space in the long run. * @ngpio: the number of GPIOs handled by this controller; the last GPIO * handled is (base + ngpio - 1). + * @offset: when multiple gpio chips belong to the same device this + * can be used as offset within the device so friendly names can + * be properly assigned. * @names: if set, must be an array of strings to use as alternative * names for the GPIOs in this chip. Any entry in the array * may be NULL if there is no alias for the GPIO, however the @@ -398,6 +401,7 @@ struct gpio_chip { int base; u16 ngpio; + u16 offset; const char *const *names; bool can_sleep; diff --git a/include/linux/of.h b/include/linux/of.h index 9c2e71e202d1..dfeb065c3fad 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -896,7 +896,7 @@ static inline int of_parse_phandle_with_fixed_args(const struct device_node *np, return -ENOSYS; } -static inline int of_count_phandle_with_args(struct device_node *np, +static inline int of_count_phandle_with_args(const struct device_node *np, const char *list_name, const char *cells_name) { diff --git a/include/linux/of_gpio.h b/include/linux/of_gpio.h index f821095218b0..8bf2ea859653 100644 --- a/include/linux/of_gpio.h +++ b/include/linux/of_gpio.h @@ -49,7 +49,7 @@ static inline struct of_mm_gpio_chip *to_of_mm_gpio_chip(struct gpio_chip *gc) return container_of(gc, struct of_mm_gpio_chip, gc); } -extern int of_get_named_gpio_flags(struct device_node *np, +extern int of_get_named_gpio_flags(const struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags); extern int of_mm_gpiochip_add_data(struct device_node *np, @@ -67,7 +67,7 @@ extern void of_mm_gpiochip_remove(struct of_mm_gpio_chip *mm_gc); #include <linux/errno.h> /* Drivers may not strictly depend on the GPIO support, so let them link. */ -static inline int of_get_named_gpio_flags(struct device_node *np, +static inline int of_get_named_gpio_flags(const struct device_node *np, const char *list_name, int index, enum of_gpio_flags *flags) { if (flags) @@ -98,7 +98,8 @@ static inline int of_get_named_gpio_flags(struct device_node *np, * The above example defines four GPIOs, two of which are not specified. * This function will return '4' */ -static inline int of_gpio_named_count(struct device_node *np, const char* propname) +static inline int of_gpio_named_count(const struct device_node *np, + const char *propname) { return of_count_phandle_with_args(np, propname, "#gpio-cells"); } @@ -109,12 +110,12 @@ static inline int of_gpio_named_count(struct device_node *np, const char* propna * * Same as of_gpio_named_count, but hard coded to use the 'gpios' property */ -static inline int of_gpio_count(struct device_node *np) +static inline int of_gpio_count(const struct device_node *np) { return of_gpio_named_count(np, "gpios"); } -static inline int of_get_gpio_flags(struct device_node *np, int index, +static inline int of_get_gpio_flags(const struct device_node *np, int index, enum of_gpio_flags *flags) { return of_get_named_gpio_flags(np, "gpios", index, flags); @@ -129,7 +130,7 @@ static inline int of_get_gpio_flags(struct device_node *np, int index, * Returns GPIO number to use with Linux generic GPIO API, or one of the errno * value on the error condition. */ -static inline int of_get_named_gpio(struct device_node *np, +static inline int of_get_named_gpio(const struct device_node *np, const char *propname, int index) { return of_get_named_gpio_flags(np, propname, index, NULL); @@ -143,7 +144,7 @@ static inline int of_get_named_gpio(struct device_node *np, * Returns GPIO number to use with Linux generic GPIO API, or one of the errno * value on the error condition. */ -static inline int of_get_gpio(struct device_node *np, int index) +static inline int of_get_gpio(const struct device_node *np, int index) { return of_get_gpio_flags(np, index, NULL); } |