162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * SuperH Pin Function Controller GPIO driver.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2008 Magnus Damm
662306a36Sopenharmony_ci * Copyright (C) 2009 - 2012 Paul Mundt
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/gpio/driver.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h>
1362306a36Sopenharmony_ci#include <linux/slab.h>
1462306a36Sopenharmony_ci#include <linux/spinlock.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "core.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct sh_pfc_gpio_data_reg {
1962306a36Sopenharmony_ci	const struct pinmux_data_reg *info;
2062306a36Sopenharmony_ci	u32 shadow;
2162306a36Sopenharmony_ci};
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistruct sh_pfc_gpio_pin {
2462306a36Sopenharmony_ci	u8 dbit;
2562306a36Sopenharmony_ci	u8 dreg;
2662306a36Sopenharmony_ci};
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistruct sh_pfc_chip {
2962306a36Sopenharmony_ci	struct sh_pfc			*pfc;
3062306a36Sopenharmony_ci	struct gpio_chip		gpio_chip;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	struct sh_pfc_window		*mem;
3362306a36Sopenharmony_ci	struct sh_pfc_gpio_data_reg	*regs;
3462306a36Sopenharmony_ci	struct sh_pfc_gpio_pin		*pins;
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	struct sh_pfc_chip *chip = gpiochip_get_data(gc);
4062306a36Sopenharmony_ci	return chip->pfc;
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic void gpio_get_data_reg(struct sh_pfc_chip *chip, unsigned int offset,
4462306a36Sopenharmony_ci			      struct sh_pfc_gpio_data_reg **reg,
4562306a36Sopenharmony_ci			      unsigned int *bit)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	int idx = sh_pfc_get_pin_index(chip->pfc, offset);
4862306a36Sopenharmony_ci	struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx];
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	*reg = &chip->regs[gpio_pin->dreg];
5162306a36Sopenharmony_ci	*bit = gpio_pin->dbit;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic u32 gpio_read_data_reg(struct sh_pfc_chip *chip,
5562306a36Sopenharmony_ci			      const struct pinmux_data_reg *dreg)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	phys_addr_t address = dreg->reg;
5862306a36Sopenharmony_ci	void __iomem *mem = address - chip->mem->phys + chip->mem->virt;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return sh_pfc_read_raw_reg(mem, dreg->reg_width);
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic void gpio_write_data_reg(struct sh_pfc_chip *chip,
6462306a36Sopenharmony_ci				const struct pinmux_data_reg *dreg, u32 value)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	phys_addr_t address = dreg->reg;
6762306a36Sopenharmony_ci	void __iomem *mem = address - chip->mem->phys + chip->mem->virt;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	sh_pfc_write_raw_reg(mem, dreg->reg_width, value);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic void gpio_setup_data_reg(struct sh_pfc_chip *chip, unsigned idx)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	struct sh_pfc *pfc = chip->pfc;
7562306a36Sopenharmony_ci	struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx];
7662306a36Sopenharmony_ci	const struct sh_pfc_pin *pin = &pfc->info->pins[idx];
7762306a36Sopenharmony_ci	const struct pinmux_data_reg *dreg;
7862306a36Sopenharmony_ci	unsigned int bit;
7962306a36Sopenharmony_ci	unsigned int i;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	for (i = 0, dreg = pfc->info->data_regs; dreg->reg_width; ++i, ++dreg) {
8262306a36Sopenharmony_ci		for (bit = 0; bit < dreg->reg_width; bit++) {
8362306a36Sopenharmony_ci			if (dreg->enum_ids[bit] == pin->enum_id) {
8462306a36Sopenharmony_ci				gpio_pin->dreg = i;
8562306a36Sopenharmony_ci				gpio_pin->dbit = bit;
8662306a36Sopenharmony_ci				return;
8762306a36Sopenharmony_ci			}
8862306a36Sopenharmony_ci		}
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	BUG();
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic int gpio_setup_data_regs(struct sh_pfc_chip *chip)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	struct sh_pfc *pfc = chip->pfc;
9762306a36Sopenharmony_ci	const struct pinmux_data_reg *dreg;
9862306a36Sopenharmony_ci	unsigned int i;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	/* Count the number of data registers, allocate memory and initialize
10162306a36Sopenharmony_ci	 * them.
10262306a36Sopenharmony_ci	 */
10362306a36Sopenharmony_ci	for (i = 0; pfc->info->data_regs[i].reg_width; ++i)
10462306a36Sopenharmony_ci		;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	chip->regs = devm_kcalloc(pfc->dev, i, sizeof(*chip->regs),
10762306a36Sopenharmony_ci				  GFP_KERNEL);
10862306a36Sopenharmony_ci	if (chip->regs == NULL)
10962306a36Sopenharmony_ci		return -ENOMEM;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	for (i = 0, dreg = pfc->info->data_regs; dreg->reg_width; ++i, ++dreg) {
11262306a36Sopenharmony_ci		chip->regs[i].info = dreg;
11362306a36Sopenharmony_ci		chip->regs[i].shadow = gpio_read_data_reg(chip, dreg);
11462306a36Sopenharmony_ci	}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	for (i = 0; i < pfc->info->nr_pins; i++) {
11762306a36Sopenharmony_ci		if (pfc->info->pins[i].enum_id == 0)
11862306a36Sopenharmony_ci			continue;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		gpio_setup_data_reg(chip, i);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return 0;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/* -----------------------------------------------------------------------------
12762306a36Sopenharmony_ci * Pin GPIOs
12862306a36Sopenharmony_ci */
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic int gpio_pin_request(struct gpio_chip *gc, unsigned offset)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct sh_pfc *pfc = gpio_to_pfc(gc);
13362306a36Sopenharmony_ci	int idx = sh_pfc_get_pin_index(pfc, offset);
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	if (idx < 0 || pfc->info->pins[idx].enum_id == 0)
13662306a36Sopenharmony_ci		return -EINVAL;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	return pinctrl_gpio_request(gc->base + offset);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic void gpio_pin_free(struct gpio_chip *gc, unsigned offset)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	return pinctrl_gpio_free(gc->base + offset);
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic void gpio_pin_set_value(struct sh_pfc_chip *chip, unsigned offset,
14762306a36Sopenharmony_ci			       int value)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	struct sh_pfc_gpio_data_reg *reg;
15062306a36Sopenharmony_ci	unsigned int bit;
15162306a36Sopenharmony_ci	unsigned int pos;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	gpio_get_data_reg(chip, offset, &reg, &bit);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	pos = reg->info->reg_width - (bit + 1);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	if (value)
15862306a36Sopenharmony_ci		reg->shadow |= BIT(pos);
15962306a36Sopenharmony_ci	else
16062306a36Sopenharmony_ci		reg->shadow &= ~BIT(pos);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	gpio_write_data_reg(chip, reg->info, reg->shadow);
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic int gpio_pin_direction_input(struct gpio_chip *gc, unsigned offset)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	return pinctrl_gpio_direction_input(gc->base + offset);
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic int gpio_pin_direction_output(struct gpio_chip *gc, unsigned offset,
17162306a36Sopenharmony_ci				    int value)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	gpio_pin_set_value(gpiochip_get_data(gc), offset, value);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return pinctrl_gpio_direction_output(gc->base + offset);
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic int gpio_pin_get(struct gpio_chip *gc, unsigned offset)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct sh_pfc_chip *chip = gpiochip_get_data(gc);
18162306a36Sopenharmony_ci	struct sh_pfc_gpio_data_reg *reg;
18262306a36Sopenharmony_ci	unsigned int bit;
18362306a36Sopenharmony_ci	unsigned int pos;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	gpio_get_data_reg(chip, offset, &reg, &bit);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	pos = reg->info->reg_width - (bit + 1);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	return (gpio_read_data_reg(chip, reg->info) >> pos) & 1;
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic void gpio_pin_set(struct gpio_chip *gc, unsigned offset, int value)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	gpio_pin_set_value(gpiochip_get_data(gc), offset, value);
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	struct sh_pfc *pfc = gpio_to_pfc(gc);
20062306a36Sopenharmony_ci	unsigned int i, k;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	for (i = 0; i < pfc->info->gpio_irq_size; i++) {
20362306a36Sopenharmony_ci		const short *gpios = pfc->info->gpio_irq[i].gpios;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci		for (k = 0; gpios[k] >= 0; k++) {
20662306a36Sopenharmony_ci			if (gpios[k] == offset)
20762306a36Sopenharmony_ci				return pfc->irqs[i];
20862306a36Sopenharmony_ci		}
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	return 0;
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_cistatic int gpio_pin_setup(struct sh_pfc_chip *chip)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	struct sh_pfc *pfc = chip->pfc;
21762306a36Sopenharmony_ci	struct gpio_chip *gc = &chip->gpio_chip;
21862306a36Sopenharmony_ci	int ret;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	chip->pins = devm_kcalloc(pfc->dev,
22162306a36Sopenharmony_ci				  pfc->info->nr_pins, sizeof(*chip->pins),
22262306a36Sopenharmony_ci				  GFP_KERNEL);
22362306a36Sopenharmony_ci	if (chip->pins == NULL)
22462306a36Sopenharmony_ci		return -ENOMEM;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	ret = gpio_setup_data_regs(chip);
22762306a36Sopenharmony_ci	if (ret < 0)
22862306a36Sopenharmony_ci		return ret;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	gc->request = gpio_pin_request;
23162306a36Sopenharmony_ci	gc->free = gpio_pin_free;
23262306a36Sopenharmony_ci	gc->direction_input = gpio_pin_direction_input;
23362306a36Sopenharmony_ci	gc->get = gpio_pin_get;
23462306a36Sopenharmony_ci	gc->direction_output = gpio_pin_direction_output;
23562306a36Sopenharmony_ci	gc->set = gpio_pin_set;
23662306a36Sopenharmony_ci	gc->to_irq = gpio_pin_to_irq;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	gc->label = pfc->info->name;
23962306a36Sopenharmony_ci	gc->parent = pfc->dev;
24062306a36Sopenharmony_ci	gc->owner = THIS_MODULE;
24162306a36Sopenharmony_ci	gc->base = IS_ENABLED(CONFIG_PINCTRL_SH_FUNC_GPIO) ? 0 : -1;
24262306a36Sopenharmony_ci	gc->ngpio = pfc->nr_gpio_pins;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	return 0;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci/* -----------------------------------------------------------------------------
24862306a36Sopenharmony_ci * Function GPIOs
24962306a36Sopenharmony_ci */
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci#ifdef CONFIG_PINCTRL_SH_FUNC_GPIO
25262306a36Sopenharmony_cistatic int gpio_function_request(struct gpio_chip *gc, unsigned offset)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	struct sh_pfc *pfc = gpio_to_pfc(gc);
25562306a36Sopenharmony_ci	unsigned int mark = pfc->info->func_gpios[offset].enum_id;
25662306a36Sopenharmony_ci	unsigned long flags;
25762306a36Sopenharmony_ci	int ret;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	dev_notice_once(pfc->dev,
26062306a36Sopenharmony_ci			"Use of GPIO API for function requests is deprecated, convert to pinctrl\n");
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	if (mark == 0)
26362306a36Sopenharmony_ci		return -EINVAL;
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	spin_lock_irqsave(&pfc->lock, flags);
26662306a36Sopenharmony_ci	ret = sh_pfc_config_mux(pfc, mark, PINMUX_TYPE_FUNCTION);
26762306a36Sopenharmony_ci	spin_unlock_irqrestore(&pfc->lock, flags);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	return ret;
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistatic int gpio_function_setup(struct sh_pfc_chip *chip)
27362306a36Sopenharmony_ci{
27462306a36Sopenharmony_ci	struct sh_pfc *pfc = chip->pfc;
27562306a36Sopenharmony_ci	struct gpio_chip *gc = &chip->gpio_chip;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	gc->request = gpio_function_request;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	gc->label = pfc->info->name;
28062306a36Sopenharmony_ci	gc->owner = THIS_MODULE;
28162306a36Sopenharmony_ci	gc->base = pfc->nr_gpio_pins;
28262306a36Sopenharmony_ci	gc->ngpio = pfc->info->nr_func_gpios;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	return 0;
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci#endif /* CONFIG_PINCTRL_SH_FUNC_GPIO */
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci/* -----------------------------------------------------------------------------
28962306a36Sopenharmony_ci * Register/unregister
29062306a36Sopenharmony_ci */
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_cistatic struct sh_pfc_chip *
29362306a36Sopenharmony_cish_pfc_add_gpiochip(struct sh_pfc *pfc, int(*setup)(struct sh_pfc_chip *),
29462306a36Sopenharmony_ci		    struct sh_pfc_window *mem)
29562306a36Sopenharmony_ci{
29662306a36Sopenharmony_ci	struct sh_pfc_chip *chip;
29762306a36Sopenharmony_ci	int ret;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	chip = devm_kzalloc(pfc->dev, sizeof(*chip), GFP_KERNEL);
30062306a36Sopenharmony_ci	if (unlikely(!chip))
30162306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	chip->mem = mem;
30462306a36Sopenharmony_ci	chip->pfc = pfc;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	ret = setup(chip);
30762306a36Sopenharmony_ci	if (ret < 0)
30862306a36Sopenharmony_ci		return ERR_PTR(ret);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	ret = devm_gpiochip_add_data(pfc->dev, &chip->gpio_chip, chip);
31162306a36Sopenharmony_ci	if (unlikely(ret < 0))
31262306a36Sopenharmony_ci		return ERR_PTR(ret);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	dev_info(pfc->dev, "%s handling gpio %u -> %u\n",
31562306a36Sopenharmony_ci		 chip->gpio_chip.label, chip->gpio_chip.base,
31662306a36Sopenharmony_ci		 chip->gpio_chip.base + chip->gpio_chip.ngpio - 1);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	return chip;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ciint sh_pfc_register_gpiochip(struct sh_pfc *pfc)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	struct sh_pfc_chip *chip;
32462306a36Sopenharmony_ci	phys_addr_t address;
32562306a36Sopenharmony_ci	unsigned int i;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	if (pfc->info->data_regs == NULL)
32862306a36Sopenharmony_ci		return 0;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	/* Find the memory window that contains the GPIO registers. Boards that
33162306a36Sopenharmony_ci	 * register a separate GPIO device will not supply a memory resource
33262306a36Sopenharmony_ci	 * that covers the data registers. In that case don't try to handle
33362306a36Sopenharmony_ci	 * GPIOs.
33462306a36Sopenharmony_ci	 */
33562306a36Sopenharmony_ci	address = pfc->info->data_regs[0].reg;
33662306a36Sopenharmony_ci	for (i = 0; i < pfc->num_windows; ++i) {
33762306a36Sopenharmony_ci		struct sh_pfc_window *window = &pfc->windows[i];
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci		if (address >= window->phys &&
34062306a36Sopenharmony_ci		    address < window->phys + window->size)
34162306a36Sopenharmony_ci			break;
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (i == pfc->num_windows)
34562306a36Sopenharmony_ci		return 0;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	/* If we have IRQ resources make sure their number is correct. */
34862306a36Sopenharmony_ci	if (pfc->num_irqs != pfc->info->gpio_irq_size) {
34962306a36Sopenharmony_ci		dev_err(pfc->dev, "invalid number of IRQ resources\n");
35062306a36Sopenharmony_ci		return -EINVAL;
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	/* Register the real GPIOs chip. */
35462306a36Sopenharmony_ci	chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]);
35562306a36Sopenharmony_ci	if (IS_ERR(chip))
35662306a36Sopenharmony_ci		return PTR_ERR(chip);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	pfc->gpio = chip;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_OF) && pfc->dev->of_node)
36162306a36Sopenharmony_ci		return 0;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci#ifdef CONFIG_PINCTRL_SH_FUNC_GPIO
36462306a36Sopenharmony_ci	/*
36562306a36Sopenharmony_ci	 * Register the GPIO to pin mappings. As pins with GPIO ports
36662306a36Sopenharmony_ci	 * must come first in the ranges, skip the pins without GPIO
36762306a36Sopenharmony_ci	 * ports by stopping at the first range that contains such a
36862306a36Sopenharmony_ci	 * pin.
36962306a36Sopenharmony_ci	 */
37062306a36Sopenharmony_ci	for (i = 0; i < pfc->nr_ranges; ++i) {
37162306a36Sopenharmony_ci		const struct sh_pfc_pin_range *range = &pfc->ranges[i];
37262306a36Sopenharmony_ci		int ret;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci		if (range->start >= pfc->nr_gpio_pins)
37562306a36Sopenharmony_ci			break;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci		ret = gpiochip_add_pin_range(&chip->gpio_chip,
37862306a36Sopenharmony_ci			dev_name(pfc->dev), range->start, range->start,
37962306a36Sopenharmony_ci			range->end - range->start + 1);
38062306a36Sopenharmony_ci		if (ret < 0)
38162306a36Sopenharmony_ci			return ret;
38262306a36Sopenharmony_ci	}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	/* Register the function GPIOs chip. */
38562306a36Sopenharmony_ci	if (pfc->info->nr_func_gpios) {
38662306a36Sopenharmony_ci		chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup, NULL);
38762306a36Sopenharmony_ci		if (IS_ERR(chip))
38862306a36Sopenharmony_ci			return PTR_ERR(chip);
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci#endif /* CONFIG_PINCTRL_SH_FUNC_GPIO */
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	return 0;
39362306a36Sopenharmony_ci}
394