1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <dm.h> 8 #include "irq-internal.h" 9 10 DECLARE_GLOBAL_DATA_PTR; 11 12 static struct gpio_bank gpio_banks[GPIO_BANK_NUM] = { 13 #if GPIO_BANK_NUM >= 1 14 GPIO_BANK_REGISTER(0, GPIO_BANK_PINS), 15 #endif 16 #if GPIO_BANK_NUM >= 2 17 GPIO_BANK_REGISTER(1, GPIO_BANK_PINS), 18 #endif 19 #if GPIO_BANK_NUM >= 3 20 GPIO_BANK_REGISTER(2, GPIO_BANK_PINS), 21 #endif 22 #if GPIO_BANK_NUM >= 4 23 GPIO_BANK_REGISTER(3, GPIO_BANK_PINS), 24 #endif 25 #if GPIO_BANK_NUM >= 5 26 GPIO_BANK_REGISTER(4, GPIO_BANK_PINS), 27 #endif 28 #if GPIO_BANK_NUM >= 6 29 GPIO_BANK_REGISTER(5, GPIO_BANK_PINS), 30 #endif 31 #if GPIO_BANK_NUM >= 7 32 GPIO_BANK_REGISTER(6, GPIO_BANK_PINS), 33 #endif 34 #if GPIO_BANK_NUM >= 8 35 GPIO_BANK_REGISTER(7, GPIO_BANK_PINS), 36 #endif 37 #if GPIO_BANK_NUM >= 9 38 GPIO_BANK_REGISTER(8, GPIO_BANK_PINS), 39 #endif 40 #if GPIO_BANK_NUM >= 10 41 GPIO_BANK_REGISTER(9, GPIO_BANK_PINS), 42 #endif 43 }; 44 45 static const char *aliases_gpios[GPIO_BANK_NUM]; 46 static const char *order_gpios[GPIO_BANK_NUM]; 47 48 static int gpio_is_valid(u32 gpio) 49 { 50 if ((gpio == EINVAL_GPIO) || 51 !GPIO_BANK_VALID(gpio) || 52 !GPIO_PIN_VALID(gpio)) { 53 IRQ_E("gpio-%d(bank-%d, pin-%d) is invalid!\n", 54 gpio, GPIO_BANK(gpio), GPIO_PIN(gpio)); 55 return 0; 56 } 57 58 return 1; 59 } 60 61 static int __hard_gpio_to_irq(u32 gpio) 62 { 63 int idx, bank = 0, pin = 0; 64 int irq; 65 66 if (!gpio_is_valid(gpio)) 67 return -EINVAL; 68 69 bank = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET; 70 pin = (gpio & GPIO_PIN_MASK) >> GPIO_PIN_OFFSET; 71 72 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 73 if (gpio_banks[idx].id == bank) { 74 irq = (gpio_banks[idx].irq_base + pin); 75 if (irq_is_busy(irq)) 76 return -EBUSY; 77 return irq; 78 } 79 } 80 81 return -EINVAL; 82 } 83 84 static int init_order_gpios(void) 85 { 86 const void *fdt = gd->fdt_blob; 87 static int initialized; 88 int node, offset; 89 int i = 0; 90 91 if (initialized) 92 return 0; 93 94 node = fdt_path_offset(fdt, "/pinctrl"); 95 if (node < 0) 96 return -EINVAL; 97 98 for (offset = fdt_first_subnode(fdt, node); 99 offset >= 0 && i < GPIO_BANK_NUM; 100 offset = fdt_next_subnode(fdt, offset)) { 101 if (i >= GPIO_BANK_NUM) 102 break; 103 104 order_gpios[i++] = fdt_get_name(fdt, offset, NULL); 105 IRQ_D("order gpio: %s\n", order_gpios[i - 1]); 106 } 107 108 initialized = 1; 109 110 return 0; 111 } 112 113 static int init_aliases_gpios(void) 114 { 115 static int initialized; 116 char alias_name[6]; 117 int i; 118 119 if (initialized) 120 return 0; 121 122 for (i = 0; i < GPIO_BANK_NUM; i++) { 123 snprintf(alias_name, 6, "gpio%d", i); 124 aliases_gpios[i] = fdt_get_alias(gd->fdt_blob, alias_name); 125 if (!aliases_gpios[i]) 126 return -EINVAL; 127 128 IRQ_D("aliases gpio: %s\n", aliases_gpios[i]); 129 } 130 131 initialized = 1; 132 133 return 0; 134 } 135 136 static int lookup_gpio_bank(const char *name) 137 { 138 int bank, ret; 139 140 for (bank = 0; bank < GPIO_BANK_NUM; bank++) { 141 if (strstr(name, gpio_banks[bank].name)) 142 return bank; 143 } 144 145 ret = init_aliases_gpios(); 146 for (bank = 0; !ret && bank < GPIO_BANK_NUM; bank++) { 147 /* 148 * @name pattern can be: 149 * /pinctrl/gpio@fd8a0000 or gpio@fd8a0000 150 */ 151 if (strstr(aliases_gpios[bank], name)) 152 return bank; 153 } 154 155 ret = init_order_gpios(); 156 for (bank = 0; !ret && bank < GPIO_BANK_NUM; bank++) { 157 if (!strcmp(name, order_gpios[bank])) 158 return bank; 159 } 160 161 return -ENOENT; 162 } 163 164 static int __phandle_gpio_to_irq(u32 gpio_phandle, u32 offset) 165 { 166 const void *blob = gd->fdt_blob; 167 const char *gpio_name; 168 int irq, node; 169 int bank; 170 171 node = fdt_node_offset_by_phandle(blob, gpio_phandle); 172 if (node < 0) { 173 IRQ_E("No gpio node by phandle(0x%x), ret=%d\n", gpio_phandle, node); 174 return EINVAL_GPIO; 175 } 176 177 gpio_name = fdt_get_name(blob, node, NULL); 178 if (!gpio_name) 179 return EINVAL_GPIO; 180 181 bank = lookup_gpio_bank(gpio_name); 182 if (bank < 0) { 183 IRQ_E("IRQ Framework can't find: %s\n", gpio_name); 184 return EINVAL_GPIO; 185 } 186 187 IRQ_D("%s: gpio%d-%d\n", __func__, bank, offset); 188 189 irq = RK_IRQ_GPIO(bank, offset); 190 if (!gpio_is_valid(irq)) 191 return EINVAL_GPIO; 192 193 return __hard_gpio_to_irq(irq); 194 } 195 196 static int __irq_to_gpio(int irq) 197 { 198 int bank, pin, idx; 199 200 bank = (irq - PIN_BASE) / GPIO_BANK_PINS; 201 pin = (irq - PIN_BASE) % GPIO_BANK_PINS; 202 203 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 204 if (gpio_banks[idx].id == bank) { 205 return (bank << GPIO_BANK_OFFSET) | 206 (pin << GPIO_PIN_OFFSET); 207 } 208 } 209 210 return -EINVAL; 211 } 212 213 int gpio_to_irq(struct gpio_desc *gpio) 214 { 215 int irq_gpio, bank, ret = EINVAL_GPIO; 216 char *name, *name_tok; 217 bool found; 218 219 if (!gpio->dev->name) { 220 IRQ_E("Can't find dev name for gpio bank\n"); 221 return EINVAL_GPIO; 222 } 223 224 name_tok = strdup(gpio->dev->name); 225 if (!name_tok) { 226 IRQ_E("Strdup '%s' failed!\n", gpio->dev->name); 227 return -ENOMEM; 228 } 229 230 name = strtok(name_tok, "@"); 231 if (!name) { 232 IRQ_E("Can't strtok '@' for '%s'\n", name_tok); 233 goto out; 234 } 235 236 for (bank = 0; bank < ARRAY_SIZE(gpio_banks); bank++) { 237 if (!strcmp(gpio_banks[bank].name, name)) { 238 found = true; 239 break; 240 } 241 } 242 243 if (!found) { 244 IRQ_E("GPIO irq framework can't find '%s'\n", name); 245 goto out; 246 } 247 248 irq_gpio = RK_IRQ_GPIO(bank, gpio->offset); 249 if (!gpio_is_valid(irq_gpio)) 250 goto out; 251 252 free(name_tok); 253 return __hard_gpio_to_irq(irq_gpio); 254 255 out: 256 free(name_tok); 257 return ret; 258 } 259 260 int hard_gpio_to_irq(u32 gpio) 261 { 262 if (!gpio_is_valid(gpio)) 263 return EINVAL_GPIO; 264 265 return __hard_gpio_to_irq(gpio); 266 } 267 268 int phandle_gpio_to_irq(u32 gpio_phandle, u32 pin) 269 { 270 if (gpio_phandle < 0) 271 return EINVAL_GPIO; 272 273 return __phandle_gpio_to_irq(gpio_phandle, pin); 274 } 275 276 int irq_to_gpio(int irq) 277 { 278 return __irq_to_gpio(irq); 279 } 280 281 struct gpio_bank *gpio_id_to_bank(u32 id) 282 { 283 int idx; 284 285 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 286 if (gpio_banks[idx].id == id) 287 return &gpio_banks[idx]; 288 } 289 290 return NULL; 291 } 292 293 struct gpio_bank *gpio_to_bank(u32 gpio) 294 { 295 int id; 296 297 if (!gpio_is_valid(gpio)) 298 return NULL; 299 300 id = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET; 301 302 return gpio_id_to_bank(id); 303 } 304