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