18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SuperH Pin Function Controller GPIO driver. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2008 Magnus Damm 68c2ecf20Sopenharmony_ci * Copyright (C) 2009 - 2012 Paul Mundt 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/device.h> 108c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "core.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct sh_pfc_gpio_data_reg { 208c2ecf20Sopenharmony_ci const struct pinmux_data_reg *info; 218c2ecf20Sopenharmony_ci u32 shadow; 228c2ecf20Sopenharmony_ci}; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct sh_pfc_gpio_pin { 258c2ecf20Sopenharmony_ci u8 dbit; 268c2ecf20Sopenharmony_ci u8 dreg; 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistruct sh_pfc_chip { 308c2ecf20Sopenharmony_ci struct sh_pfc *pfc; 318c2ecf20Sopenharmony_ci struct gpio_chip gpio_chip; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci struct sh_pfc_window *mem; 348c2ecf20Sopenharmony_ci struct sh_pfc_gpio_data_reg *regs; 358c2ecf20Sopenharmony_ci struct sh_pfc_gpio_pin *pins; 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci struct sh_pfc_chip *chip = gpiochip_get_data(gc); 418c2ecf20Sopenharmony_ci return chip->pfc; 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic void gpio_get_data_reg(struct sh_pfc_chip *chip, unsigned int offset, 458c2ecf20Sopenharmony_ci struct sh_pfc_gpio_data_reg **reg, 468c2ecf20Sopenharmony_ci unsigned int *bit) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci int idx = sh_pfc_get_pin_index(chip->pfc, offset); 498c2ecf20Sopenharmony_ci struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx]; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci *reg = &chip->regs[gpio_pin->dreg]; 528c2ecf20Sopenharmony_ci *bit = gpio_pin->dbit; 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic u32 gpio_read_data_reg(struct sh_pfc_chip *chip, 568c2ecf20Sopenharmony_ci const struct pinmux_data_reg *dreg) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci phys_addr_t address = dreg->reg; 598c2ecf20Sopenharmony_ci void __iomem *mem = address - chip->mem->phys + chip->mem->virt; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return sh_pfc_read_raw_reg(mem, dreg->reg_width); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic void gpio_write_data_reg(struct sh_pfc_chip *chip, 658c2ecf20Sopenharmony_ci const struct pinmux_data_reg *dreg, u32 value) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci phys_addr_t address = dreg->reg; 688c2ecf20Sopenharmony_ci void __iomem *mem = address - chip->mem->phys + chip->mem->virt; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci sh_pfc_write_raw_reg(mem, dreg->reg_width, value); 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic void gpio_setup_data_reg(struct sh_pfc_chip *chip, unsigned idx) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct sh_pfc *pfc = chip->pfc; 768c2ecf20Sopenharmony_ci struct sh_pfc_gpio_pin *gpio_pin = &chip->pins[idx]; 778c2ecf20Sopenharmony_ci const struct sh_pfc_pin *pin = &pfc->info->pins[idx]; 788c2ecf20Sopenharmony_ci const struct pinmux_data_reg *dreg; 798c2ecf20Sopenharmony_ci unsigned int bit; 808c2ecf20Sopenharmony_ci unsigned int i; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci for (i = 0, dreg = pfc->info->data_regs; dreg->reg_width; ++i, ++dreg) { 838c2ecf20Sopenharmony_ci for (bit = 0; bit < dreg->reg_width; bit++) { 848c2ecf20Sopenharmony_ci if (dreg->enum_ids[bit] == pin->enum_id) { 858c2ecf20Sopenharmony_ci gpio_pin->dreg = i; 868c2ecf20Sopenharmony_ci gpio_pin->dbit = bit; 878c2ecf20Sopenharmony_ci return; 888c2ecf20Sopenharmony_ci } 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci BUG(); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int gpio_setup_data_regs(struct sh_pfc_chip *chip) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct sh_pfc *pfc = chip->pfc; 988c2ecf20Sopenharmony_ci const struct pinmux_data_reg *dreg; 998c2ecf20Sopenharmony_ci unsigned int i; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* Count the number of data registers, allocate memory and initialize 1028c2ecf20Sopenharmony_ci * them. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ci for (i = 0; pfc->info->data_regs[i].reg_width; ++i) 1058c2ecf20Sopenharmony_ci ; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci chip->regs = devm_kcalloc(pfc->dev, i, sizeof(*chip->regs), 1088c2ecf20Sopenharmony_ci GFP_KERNEL); 1098c2ecf20Sopenharmony_ci if (chip->regs == NULL) 1108c2ecf20Sopenharmony_ci return -ENOMEM; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci for (i = 0, dreg = pfc->info->data_regs; dreg->reg_width; ++i, ++dreg) { 1138c2ecf20Sopenharmony_ci chip->regs[i].info = dreg; 1148c2ecf20Sopenharmony_ci chip->regs[i].shadow = gpio_read_data_reg(chip, dreg); 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci for (i = 0; i < pfc->info->nr_pins; i++) { 1188c2ecf20Sopenharmony_ci if (pfc->info->pins[i].enum_id == 0) 1198c2ecf20Sopenharmony_ci continue; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci gpio_setup_data_reg(chip, i); 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci return 0; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 1288c2ecf20Sopenharmony_ci * Pin GPIOs 1298c2ecf20Sopenharmony_ci */ 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic int gpio_pin_request(struct gpio_chip *gc, unsigned offset) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct sh_pfc *pfc = gpio_to_pfc(gc); 1348c2ecf20Sopenharmony_ci int idx = sh_pfc_get_pin_index(pfc, offset); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (idx < 0 || pfc->info->pins[idx].enum_id == 0) 1378c2ecf20Sopenharmony_ci return -EINVAL; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci return pinctrl_gpio_request(offset); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void gpio_pin_free(struct gpio_chip *gc, unsigned offset) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci return pinctrl_gpio_free(offset); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic void gpio_pin_set_value(struct sh_pfc_chip *chip, unsigned offset, 1488c2ecf20Sopenharmony_ci int value) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci struct sh_pfc_gpio_data_reg *reg; 1518c2ecf20Sopenharmony_ci unsigned int bit; 1528c2ecf20Sopenharmony_ci unsigned int pos; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci gpio_get_data_reg(chip, offset, ®, &bit); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci pos = reg->info->reg_width - (bit + 1); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (value) 1598c2ecf20Sopenharmony_ci reg->shadow |= BIT(pos); 1608c2ecf20Sopenharmony_ci else 1618c2ecf20Sopenharmony_ci reg->shadow &= ~BIT(pos); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci gpio_write_data_reg(chip, reg->info, reg->shadow); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic int gpio_pin_direction_input(struct gpio_chip *gc, unsigned offset) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_input(offset); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic int gpio_pin_direction_output(struct gpio_chip *gc, unsigned offset, 1728c2ecf20Sopenharmony_ci int value) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci gpio_pin_set_value(gpiochip_get_data(gc), offset, value); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_output(offset); 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic int gpio_pin_get(struct gpio_chip *gc, unsigned offset) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct sh_pfc_chip *chip = gpiochip_get_data(gc); 1828c2ecf20Sopenharmony_ci struct sh_pfc_gpio_data_reg *reg; 1838c2ecf20Sopenharmony_ci unsigned int bit; 1848c2ecf20Sopenharmony_ci unsigned int pos; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci gpio_get_data_reg(chip, offset, ®, &bit); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci pos = reg->info->reg_width - (bit + 1); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return (gpio_read_data_reg(chip, reg->info) >> pos) & 1; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic void gpio_pin_set(struct gpio_chip *gc, unsigned offset, int value) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci gpio_pin_set_value(gpiochip_get_data(gc), offset, value); 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci struct sh_pfc *pfc = gpio_to_pfc(gc); 2018c2ecf20Sopenharmony_ci unsigned int i, k; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci for (i = 0; i < pfc->info->gpio_irq_size; i++) { 2048c2ecf20Sopenharmony_ci const short *gpios = pfc->info->gpio_irq[i].gpios; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci for (k = 0; gpios[k] >= 0; k++) { 2078c2ecf20Sopenharmony_ci if (gpios[k] == offset) 2088c2ecf20Sopenharmony_ci return pfc->irqs[i]; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int gpio_pin_setup(struct sh_pfc_chip *chip) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct sh_pfc *pfc = chip->pfc; 2188c2ecf20Sopenharmony_ci struct gpio_chip *gc = &chip->gpio_chip; 2198c2ecf20Sopenharmony_ci int ret; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci chip->pins = devm_kcalloc(pfc->dev, 2228c2ecf20Sopenharmony_ci pfc->info->nr_pins, sizeof(*chip->pins), 2238c2ecf20Sopenharmony_ci GFP_KERNEL); 2248c2ecf20Sopenharmony_ci if (chip->pins == NULL) 2258c2ecf20Sopenharmony_ci return -ENOMEM; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci ret = gpio_setup_data_regs(chip); 2288c2ecf20Sopenharmony_ci if (ret < 0) 2298c2ecf20Sopenharmony_ci return ret; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci gc->request = gpio_pin_request; 2328c2ecf20Sopenharmony_ci gc->free = gpio_pin_free; 2338c2ecf20Sopenharmony_ci gc->direction_input = gpio_pin_direction_input; 2348c2ecf20Sopenharmony_ci gc->get = gpio_pin_get; 2358c2ecf20Sopenharmony_ci gc->direction_output = gpio_pin_direction_output; 2368c2ecf20Sopenharmony_ci gc->set = gpio_pin_set; 2378c2ecf20Sopenharmony_ci gc->to_irq = gpio_pin_to_irq; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci gc->label = pfc->info->name; 2408c2ecf20Sopenharmony_ci gc->parent = pfc->dev; 2418c2ecf20Sopenharmony_ci gc->owner = THIS_MODULE; 2428c2ecf20Sopenharmony_ci gc->base = 0; 2438c2ecf20Sopenharmony_ci gc->ngpio = pfc->nr_gpio_pins; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci return 0; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 2498c2ecf20Sopenharmony_ci * Function GPIOs 2508c2ecf20Sopenharmony_ci */ 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci#ifdef CONFIG_PINCTRL_SH_FUNC_GPIO 2538c2ecf20Sopenharmony_cistatic int gpio_function_request(struct gpio_chip *gc, unsigned offset) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct sh_pfc *pfc = gpio_to_pfc(gc); 2568c2ecf20Sopenharmony_ci unsigned int mark = pfc->info->func_gpios[offset].enum_id; 2578c2ecf20Sopenharmony_ci unsigned long flags; 2588c2ecf20Sopenharmony_ci int ret; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci dev_notice_once(pfc->dev, 2618c2ecf20Sopenharmony_ci "Use of GPIO API for function requests is deprecated, convert to pinctrl\n"); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (mark == 0) 2648c2ecf20Sopenharmony_ci return -EINVAL; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci spin_lock_irqsave(&pfc->lock, flags); 2678c2ecf20Sopenharmony_ci ret = sh_pfc_config_mux(pfc, mark, PINMUX_TYPE_FUNCTION); 2688c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&pfc->lock, flags); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci return ret; 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic int gpio_function_setup(struct sh_pfc_chip *chip) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci struct sh_pfc *pfc = chip->pfc; 2768c2ecf20Sopenharmony_ci struct gpio_chip *gc = &chip->gpio_chip; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci gc->request = gpio_function_request; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci gc->label = pfc->info->name; 2818c2ecf20Sopenharmony_ci gc->owner = THIS_MODULE; 2828c2ecf20Sopenharmony_ci gc->base = pfc->nr_gpio_pins; 2838c2ecf20Sopenharmony_ci gc->ngpio = pfc->info->nr_func_gpios; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci return 0; 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci#endif /* CONFIG_PINCTRL_SH_FUNC_GPIO */ 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/* ----------------------------------------------------------------------------- 2908c2ecf20Sopenharmony_ci * Register/unregister 2918c2ecf20Sopenharmony_ci */ 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic struct sh_pfc_chip * 2948c2ecf20Sopenharmony_cish_pfc_add_gpiochip(struct sh_pfc *pfc, int(*setup)(struct sh_pfc_chip *), 2958c2ecf20Sopenharmony_ci struct sh_pfc_window *mem) 2968c2ecf20Sopenharmony_ci{ 2978c2ecf20Sopenharmony_ci struct sh_pfc_chip *chip; 2988c2ecf20Sopenharmony_ci int ret; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci chip = devm_kzalloc(pfc->dev, sizeof(*chip), GFP_KERNEL); 3018c2ecf20Sopenharmony_ci if (unlikely(!chip)) 3028c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci chip->mem = mem; 3058c2ecf20Sopenharmony_ci chip->pfc = pfc; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci ret = setup(chip); 3088c2ecf20Sopenharmony_ci if (ret < 0) 3098c2ecf20Sopenharmony_ci return ERR_PTR(ret); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci ret = devm_gpiochip_add_data(pfc->dev, &chip->gpio_chip, chip); 3128c2ecf20Sopenharmony_ci if (unlikely(ret < 0)) 3138c2ecf20Sopenharmony_ci return ERR_PTR(ret); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci dev_info(pfc->dev, "%s handling gpio %u -> %u\n", 3168c2ecf20Sopenharmony_ci chip->gpio_chip.label, chip->gpio_chip.base, 3178c2ecf20Sopenharmony_ci chip->gpio_chip.base + chip->gpio_chip.ngpio - 1); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci return chip; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ciint sh_pfc_register_gpiochip(struct sh_pfc *pfc) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct sh_pfc_chip *chip; 3258c2ecf20Sopenharmony_ci phys_addr_t address; 3268c2ecf20Sopenharmony_ci unsigned int i; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci if (pfc->info->data_regs == NULL) 3298c2ecf20Sopenharmony_ci return 0; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* Find the memory window that contain the GPIO registers. Boards that 3328c2ecf20Sopenharmony_ci * register a separate GPIO device will not supply a memory resource 3338c2ecf20Sopenharmony_ci * that covers the data registers. In that case don't try to handle 3348c2ecf20Sopenharmony_ci * GPIOs. 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_ci address = pfc->info->data_regs[0].reg; 3378c2ecf20Sopenharmony_ci for (i = 0; i < pfc->num_windows; ++i) { 3388c2ecf20Sopenharmony_ci struct sh_pfc_window *window = &pfc->windows[i]; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci if (address >= window->phys && 3418c2ecf20Sopenharmony_ci address < window->phys + window->size) 3428c2ecf20Sopenharmony_ci break; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci if (i == pfc->num_windows) 3468c2ecf20Sopenharmony_ci return 0; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /* If we have IRQ resources make sure their number is correct. */ 3498c2ecf20Sopenharmony_ci if (pfc->num_irqs != pfc->info->gpio_irq_size) { 3508c2ecf20Sopenharmony_ci dev_err(pfc->dev, "invalid number of IRQ resources\n"); 3518c2ecf20Sopenharmony_ci return -EINVAL; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci /* Register the real GPIOs chip. */ 3558c2ecf20Sopenharmony_ci chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup, &pfc->windows[i]); 3568c2ecf20Sopenharmony_ci if (IS_ERR(chip)) 3578c2ecf20Sopenharmony_ci return PTR_ERR(chip); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci pfc->gpio = chip; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_OF) && pfc->dev->of_node) 3628c2ecf20Sopenharmony_ci return 0; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci#ifdef CONFIG_PINCTRL_SH_FUNC_GPIO 3658c2ecf20Sopenharmony_ci /* 3668c2ecf20Sopenharmony_ci * Register the GPIO to pin mappings. As pins with GPIO ports 3678c2ecf20Sopenharmony_ci * must come first in the ranges, skip the pins without GPIO 3688c2ecf20Sopenharmony_ci * ports by stopping at the first range that contains such a 3698c2ecf20Sopenharmony_ci * pin. 3708c2ecf20Sopenharmony_ci */ 3718c2ecf20Sopenharmony_ci for (i = 0; i < pfc->nr_ranges; ++i) { 3728c2ecf20Sopenharmony_ci const struct sh_pfc_pin_range *range = &pfc->ranges[i]; 3738c2ecf20Sopenharmony_ci int ret; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci if (range->start >= pfc->nr_gpio_pins) 3768c2ecf20Sopenharmony_ci break; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci ret = gpiochip_add_pin_range(&chip->gpio_chip, 3798c2ecf20Sopenharmony_ci dev_name(pfc->dev), range->start, range->start, 3808c2ecf20Sopenharmony_ci range->end - range->start + 1); 3818c2ecf20Sopenharmony_ci if (ret < 0) 3828c2ecf20Sopenharmony_ci return ret; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* Register the function GPIOs chip. */ 3868c2ecf20Sopenharmony_ci if (pfc->info->nr_func_gpios) { 3878c2ecf20Sopenharmony_ci chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup, NULL); 3888c2ecf20Sopenharmony_ci if (IS_ERR(chip)) 3898c2ecf20Sopenharmony_ci return PTR_ERR(chip); 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci#endif /* CONFIG_PINCTRL_SH_FUNC_GPIO */ 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci return 0; 3948c2ecf20Sopenharmony_ci} 395