xref: /rk3399_rockchip-uboot/drivers/irq/irq-gpio-switch.c (revision befbd723c2c9eadcfa6e9ae1dca845f05d3c29c8)
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