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 static struct gpio_bank gpio_banks[GPIO_BANK_NUM] = { 12 #if GPIO_BANK_NUM >= 1 13 GPIO_BANK_REGISTER(0, GPIO_BANK_PINS), 14 #endif 15 #if GPIO_BANK_NUM >= 2 16 GPIO_BANK_REGISTER(1, GPIO_BANK_PINS), 17 #endif 18 #if GPIO_BANK_NUM >= 3 19 GPIO_BANK_REGISTER(2, GPIO_BANK_PINS), 20 #endif 21 #if GPIO_BANK_NUM >= 4 22 GPIO_BANK_REGISTER(3, GPIO_BANK_PINS), 23 #endif 24 #if GPIO_BANK_NUM >= 5 25 GPIO_BANK_REGISTER(4, GPIO_BANK_PINS), 26 #endif 27 #if GPIO_BANK_NUM >= 6 28 GPIO_BANK_REGISTER(5, GPIO_BANK_PINS), 29 #endif 30 #if GPIO_BANK_NUM >= 7 31 GPIO_BANK_REGISTER(6, GPIO_BANK_PINS), 32 #endif 33 #if GPIO_BANK_NUM >= 8 34 GPIO_BANK_REGISTER(7, GPIO_BANK_PINS), 35 #endif 36 #if GPIO_BANK_NUM >= 9 37 GPIO_BANK_REGISTER(8, GPIO_BANK_PINS), 38 #endif 39 #if GPIO_BANK_NUM >= 10 40 GPIO_BANK_REGISTER(9, GPIO_BANK_PINS), 41 #endif 42 }; 43 44 static int gpio_is_valid(u32 gpio) 45 { 46 if ((gpio == EINVAL_GPIO) || !GPIO_BANK_VALID(gpio) || 47 !GPIO_PIN_VALID(gpio)) { 48 printf("gpio = 0x%x is not valid!\n", gpio); 49 return 0; 50 } 51 52 return 1; 53 } 54 55 static int _hard_gpio_to_irq(u32 gpio) 56 { 57 int idx, bank = 0, pin = 0; 58 59 if (!gpio_is_valid(gpio)) 60 return -EINVAL; 61 62 bank = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET; 63 pin = (gpio & GPIO_PIN_MASK) >> GPIO_PIN_OFFSET; 64 65 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 66 if (gpio_banks[idx].id == bank) 67 return (gpio_banks[idx].irq_base + pin); 68 } 69 70 return -EINVAL; 71 } 72 73 static int _irq_to_gpio(int irq) 74 { 75 int bank, pin, idx; 76 77 bank = (irq - PIN_BASE) / GPIO_BANK_PINS; 78 pin = (irq - PIN_BASE) % GPIO_BANK_PINS; 79 80 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 81 if (gpio_banks[idx].id == bank) { 82 return (bank << GPIO_BANK_OFFSET) | 83 (pin << GPIO_PIN_OFFSET); 84 } 85 } 86 87 return -EINVAL; 88 } 89 90 int gpio_to_irq(struct gpio_desc *gpio) 91 { 92 int irq_gpio, bank, ret = EINVAL_GPIO; 93 bool found; 94 char *name, *name_tok; 95 96 if (!gpio->dev->name) { 97 printf("can't find device name for the gpio bank\n"); 98 return EINVAL_GPIO; 99 } 100 101 name_tok = strdup(gpio->dev->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 irq_gpio = RK_IRQ_GPIO(bank, gpio->offset); 126 if (!gpio_is_valid(irq_gpio)) 127 goto out; 128 129 free(name_tok); 130 return _hard_gpio_to_irq(irq_gpio); 131 132 out: 133 free(name_tok); 134 return ret; 135 } 136 137 int hard_gpio_to_irq(u32 gpio) 138 { 139 if (!gpio_is_valid(gpio)) 140 return EINVAL_GPIO; 141 142 return _hard_gpio_to_irq(gpio); 143 } 144 145 int irq_to_gpio(int irq) 146 { 147 return _irq_to_gpio(irq); 148 } 149 150 struct gpio_bank *gpio_id_to_bank(u32 id) 151 { 152 int idx; 153 154 for (idx = 0; idx < ARRAY_SIZE(gpio_banks); idx++) { 155 if (gpio_banks[idx].id == id) 156 return &gpio_banks[idx]; 157 } 158 159 return NULL; 160 } 161 162 struct gpio_bank *gpio_to_bank(u32 gpio) 163 { 164 int id; 165 166 if (!gpio_is_valid(gpio)) 167 return NULL; 168 169 id = (gpio & GPIO_BANK_MASK) >> GPIO_BANK_OFFSET; 170 171 return gpio_id_to_bank(id); 172 } 173