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 *gpio_alias[GPIO_BANK_NUM]; 46 47 static int gpio_is_valid(u32 gpio) 48 { 49 if ((gpio == EINVAL_GPIO) || 50 !GPIO_BANK_VALID(gpio) || 51 !GPIO_PIN_VALID(gpio)) { 52 IRQ_E("gpio-%d(bank-%d, pin-%d) is invalid!\n", 53 gpio, GPIO_BANK(gpio), GPIO_PIN(gpio)); 54 return 0; 55 } 56 57 return 1; 58 } 59 60 static int __hard_gpio_to_irq(u32 gpio) 61 { 62 int idx, bank = 0, pin = 0; 63 int irq; 64 65 if (!gpio_is_valid(gpio)) 66 return -EINVAL; 67 68 bank = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET; 69 pin = (gpio & GPIO_PIN_MASK) >> GPIO_PIN_OFFSET; 70 71 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 72 if (gpio_banks[idx].id == bank) { 73 irq = (gpio_banks[idx].irq_base + pin); 74 if (irq_is_busy(irq)) 75 return -EBUSY; 76 return irq; 77 } 78 } 79 80 return -EINVAL; 81 } 82 83 static int __phandle_gpio_to_irq(u32 gpio_phandle, u32 offset) 84 { 85 const void *blob = gd->fdt_blob; 86 const char *gpio_name; 87 char alias_name[6]; 88 int irq, node; 89 int i, bank; 90 bool found = false; 91 92 node = fdt_node_offset_by_phandle(blob, gpio_phandle); 93 if (node < 0) { 94 IRQ_E("No gpio node by phandle(0x%x), ret=%d\n", gpio_phandle, node); 95 return EINVAL_GPIO; 96 } 97 98 gpio_name = fdt_get_name(blob, node, NULL); 99 if (!gpio_name) 100 return EINVAL_GPIO; 101 102 for (bank = 0; bank < GPIO_BANK_NUM; bank++) { 103 if (strstr(gpio_name, gpio_banks[bank].name)) { 104 found = true; 105 break; 106 } 107 } 108 109 if (!found) { 110 /* initial getting all gpio alias */ 111 if (!gpio_alias[0]) { 112 for (i = 0; i < GPIO_BANK_NUM; i++) { 113 snprintf(alias_name, 6, "gpio%d", i); 114 gpio_alias[i] = fdt_get_alias(blob, alias_name); 115 if (!gpio_alias[i]) { 116 IRQ_D("No gpio alias %s\n", alias_name); 117 return EINVAL_GPIO; 118 } 119 } 120 } 121 122 /* match alias ? */ 123 for (bank = 0; bank < ARRAY_SIZE(gpio_banks); bank++) { 124 if (strstr(gpio_alias[bank], gpio_name)) { 125 found = true; 126 break; 127 } 128 } 129 } 130 131 if (!found) { 132 IRQ_E("IRQ Framework can't find: %s\n", gpio_name); 133 return EINVAL_GPIO; 134 } 135 136 IRQ_D("%s: gpio%d-%d\n", __func__, bank, offset); 137 138 irq = RK_IRQ_GPIO(bank, offset); 139 if (!gpio_is_valid(irq)) 140 return EINVAL_GPIO; 141 142 return __hard_gpio_to_irq(irq); 143 } 144 145 static int __irq_to_gpio(int irq) 146 { 147 int bank, pin, idx; 148 149 bank = (irq - PIN_BASE) / GPIO_BANK_PINS; 150 pin = (irq - PIN_BASE) % GPIO_BANK_PINS; 151 152 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 153 if (gpio_banks[idx].id == bank) { 154 return (bank << GPIO_BANK_OFFSET) | 155 (pin << GPIO_PIN_OFFSET); 156 } 157 } 158 159 return -EINVAL; 160 } 161 162 int gpio_to_irq(struct gpio_desc *gpio) 163 { 164 int irq_gpio, bank, ret = EINVAL_GPIO; 165 char *name, *name_tok; 166 bool found; 167 168 if (!gpio->dev->name) { 169 IRQ_E("Can't find dev name for gpio bank\n"); 170 return EINVAL_GPIO; 171 } 172 173 name_tok = strdup(gpio->dev->name); 174 if (!name_tok) { 175 IRQ_E("Strdup '%s' failed!\n", gpio->dev->name); 176 return -ENOMEM; 177 } 178 179 name = strtok(name_tok, "@"); 180 if (!name) { 181 IRQ_E("Can't strtok '@' for '%s'\n", name_tok); 182 goto out; 183 } 184 185 for (bank = 0; bank < ARRAY_SIZE(gpio_banks); bank++) { 186 if (!strcmp(gpio_banks[bank].name, name)) { 187 found = true; 188 break; 189 } 190 } 191 192 if (!found) { 193 IRQ_E("GPIO irq framework can't find '%s'\n", name); 194 goto out; 195 } 196 197 irq_gpio = RK_IRQ_GPIO(bank, gpio->offset); 198 if (!gpio_is_valid(irq_gpio)) 199 goto out; 200 201 free(name_tok); 202 return __hard_gpio_to_irq(irq_gpio); 203 204 out: 205 free(name_tok); 206 return ret; 207 } 208 209 int hard_gpio_to_irq(u32 gpio) 210 { 211 if (!gpio_is_valid(gpio)) 212 return EINVAL_GPIO; 213 214 return __hard_gpio_to_irq(gpio); 215 } 216 217 int phandle_gpio_to_irq(u32 gpio_phandle, u32 pin) 218 { 219 if (gpio_phandle < 0) 220 return EINVAL_GPIO; 221 222 return __phandle_gpio_to_irq(gpio_phandle, pin); 223 } 224 225 int irq_to_gpio(int irq) 226 { 227 return __irq_to_gpio(irq); 228 } 229 230 struct gpio_bank *gpio_id_to_bank(u32 id) 231 { 232 int idx; 233 234 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 235 if (gpio_banks[idx].id == id) 236 return &gpio_banks[idx]; 237 } 238 239 return NULL; 240 } 241 242 struct gpio_bank *gpio_to_bank(u32 gpio) 243 { 244 int id; 245 246 if (!gpio_is_valid(gpio)) 247 return NULL; 248 249 id = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET; 250 251 return gpio_id_to_bank(id); 252 } 253