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, ®, &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, ®, &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