gpio.c revision 0b73ee5d534cc6dcb96efb9eac4cf96b40910911
1/* 2 * SuperH Pin Function Controller GPIO driver. 3 * 4 * Copyright (C) 2008 Magnus Damm 5 * Copyright (C) 2009 - 2012 Paul Mundt 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file "COPYING" in the main directory of this archive 9 * for more details. 10 */ 11 12#define pr_fmt(fmt) KBUILD_MODNAME " gpio: " fmt 13 14#include <linux/device.h> 15#include <linux/gpio.h> 16#include <linux/init.h> 17#include <linux/module.h> 18#include <linux/pinctrl/consumer.h> 19#include <linux/slab.h> 20#include <linux/spinlock.h> 21 22#include "core.h" 23 24struct sh_pfc_chip { 25 struct sh_pfc *pfc; 26 struct gpio_chip gpio_chip; 27}; 28 29static struct sh_pfc_chip *gpio_to_pfc_chip(struct gpio_chip *gc) 30{ 31 return container_of(gc, struct sh_pfc_chip, gpio_chip); 32} 33 34static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc) 35{ 36 return gpio_to_pfc_chip(gc)->pfc; 37} 38 39/* ----------------------------------------------------------------------------- 40 * Pin GPIOs 41 */ 42 43static int gpio_pin_request(struct gpio_chip *gc, unsigned offset) 44{ 45 struct sh_pfc *pfc = gpio_to_pfc(gc); 46 47 if (pfc->info->pins[offset].enum_id == 0) 48 return -EINVAL; 49 50 return pinctrl_request_gpio(offset); 51} 52 53static void gpio_pin_free(struct gpio_chip *gc, unsigned offset) 54{ 55 return pinctrl_free_gpio(offset); 56} 57 58static void gpio_pin_set_value(struct sh_pfc *pfc, unsigned offset, int value) 59{ 60 struct pinmux_data_reg *dr; 61 int bit; 62 63 sh_pfc_get_data_reg(pfc, offset, &dr, &bit); 64 sh_pfc_write_bit(dr, bit, value); 65} 66 67static int gpio_pin_direction_input(struct gpio_chip *gc, unsigned offset) 68{ 69 return pinctrl_gpio_direction_input(offset); 70} 71 72static int gpio_pin_direction_output(struct gpio_chip *gc, unsigned offset, 73 int value) 74{ 75 gpio_pin_set_value(gpio_to_pfc(gc), offset, value); 76 77 return pinctrl_gpio_direction_output(offset); 78} 79 80static int gpio_pin_get(struct gpio_chip *gc, unsigned offset) 81{ 82 struct sh_pfc *pfc = gpio_to_pfc(gc); 83 struct pinmux_data_reg *dr; 84 int bit; 85 86 sh_pfc_get_data_reg(pfc, offset, &dr, &bit); 87 return sh_pfc_read_bit(dr, bit); 88} 89 90static void gpio_pin_set(struct gpio_chip *gc, unsigned offset, int value) 91{ 92 gpio_pin_set_value(gpio_to_pfc(gc), offset, value); 93} 94 95static int gpio_pin_to_irq(struct gpio_chip *gc, unsigned offset) 96{ 97 struct sh_pfc *pfc = gpio_to_pfc(gc); 98 int i, k; 99 100 for (i = 0; i < pfc->info->gpio_irq_size; i++) { 101 unsigned short *gpios = pfc->info->gpio_irq[i].gpios; 102 103 for (k = 0; gpios[k]; k++) { 104 if (gpios[k] == offset) 105 return pfc->info->gpio_irq[i].irq; 106 } 107 } 108 109 return -ENOSYS; 110} 111 112static void gpio_pin_setup(struct sh_pfc_chip *chip) 113{ 114 struct sh_pfc *pfc = chip->pfc; 115 struct gpio_chip *gc = &chip->gpio_chip; 116 117 gc->request = gpio_pin_request; 118 gc->free = gpio_pin_free; 119 gc->direction_input = gpio_pin_direction_input; 120 gc->get = gpio_pin_get; 121 gc->direction_output = gpio_pin_direction_output; 122 gc->set = gpio_pin_set; 123 gc->to_irq = gpio_pin_to_irq; 124 125 gc->label = pfc->info->name; 126 gc->dev = pfc->dev; 127 gc->owner = THIS_MODULE; 128 gc->base = 0; 129 gc->ngpio = pfc->info->nr_pins; 130} 131 132/* ----------------------------------------------------------------------------- 133 * Function GPIOs 134 */ 135 136static int gpio_function_request(struct gpio_chip *gc, unsigned offset) 137{ 138 struct sh_pfc *pfc = gpio_to_pfc(gc); 139 unsigned int mark = pfc->info->func_gpios[offset].enum_id; 140 unsigned long flags; 141 int ret = -EINVAL; 142 143 pr_notice_once("Use of GPIO API for function requests is deprecated, convert to pinctrl\n"); 144 145 if (mark == 0) 146 return ret; 147 148 spin_lock_irqsave(&pfc->lock, flags); 149 150 if (sh_pfc_config_mux(pfc, mark, PINMUX_TYPE_FUNCTION, GPIO_CFG_DRYRUN)) 151 goto done; 152 153 if (sh_pfc_config_mux(pfc, mark, PINMUX_TYPE_FUNCTION, GPIO_CFG_REQ)) 154 goto done; 155 156 ret = 0; 157 158done: 159 spin_unlock_irqrestore(&pfc->lock, flags); 160 return ret; 161} 162 163static void gpio_function_free(struct gpio_chip *gc, unsigned offset) 164{ 165 struct sh_pfc *pfc = gpio_to_pfc(gc); 166 unsigned int mark = pfc->info->func_gpios[offset].enum_id; 167 unsigned long flags; 168 169 spin_lock_irqsave(&pfc->lock, flags); 170 171 sh_pfc_config_mux(pfc, mark, PINMUX_TYPE_FUNCTION, GPIO_CFG_FREE); 172 173 spin_unlock_irqrestore(&pfc->lock, flags); 174} 175 176static void gpio_function_setup(struct sh_pfc_chip *chip) 177{ 178 struct sh_pfc *pfc = chip->pfc; 179 struct gpio_chip *gc = &chip->gpio_chip; 180 181 gc->request = gpio_function_request; 182 gc->free = gpio_function_free; 183 184 gc->label = pfc->info->name; 185 gc->owner = THIS_MODULE; 186 gc->base = pfc->info->nr_pins; 187 gc->ngpio = pfc->info->nr_func_gpios; 188} 189 190/* ----------------------------------------------------------------------------- 191 * Register/unregister 192 */ 193 194static struct sh_pfc_chip * 195sh_pfc_add_gpiochip(struct sh_pfc *pfc, void(*setup)(struct sh_pfc_chip *)) 196{ 197 struct sh_pfc_chip *chip; 198 int ret; 199 200 chip = devm_kzalloc(pfc->dev, sizeof(*chip), GFP_KERNEL); 201 if (unlikely(!chip)) 202 return ERR_PTR(-ENOMEM); 203 204 chip->pfc = pfc; 205 206 setup(chip); 207 208 ret = gpiochip_add(&chip->gpio_chip); 209 if (unlikely(ret < 0)) 210 return ERR_PTR(ret); 211 212 pr_info("%s handling gpio %u -> %u\n", 213 chip->gpio_chip.label, chip->gpio_chip.base, 214 chip->gpio_chip.base + chip->gpio_chip.ngpio - 1); 215 216 return chip; 217} 218 219int sh_pfc_register_gpiochip(struct sh_pfc *pfc) 220{ 221 struct sh_pfc_chip *chip; 222 223 chip = sh_pfc_add_gpiochip(pfc, gpio_pin_setup); 224 if (IS_ERR(chip)) 225 return PTR_ERR(chip); 226 227 pfc->gpio = chip; 228 229 chip = sh_pfc_add_gpiochip(pfc, gpio_function_setup); 230 if (IS_ERR(chip)) 231 return PTR_ERR(chip); 232 233 pfc->func = chip; 234 235 return 0; 236} 237 238int sh_pfc_unregister_gpiochip(struct sh_pfc *pfc) 239{ 240 int err; 241 int ret; 242 243 ret = gpiochip_remove(&pfc->gpio->gpio_chip); 244 err = gpiochip_remove(&pfc->func->gpio_chip); 245 246 return ret < 0 ? ret : err; 247} 248