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