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