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