1 /*
2 * Copyright (C) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/printk.h>
22 #include <linux/interrupt.h>
23 #include <linux/gpio.h>
24 #include "hi_osal.h"
25
26 #define MAX_GPIO_NUM (28 * 8) /* The max gpio number in 96cv 900/300 */
27 static unsigned int g_gpio_to_irq[MAX_GPIO_NUM] = {0};
28
osal_gpio_get_direction(unsigned int gpio)29 int osal_gpio_get_direction(unsigned int gpio)
30 {
31 int ret_val;
32 struct gpio_desc *desc = NULL;
33
34 ret_val = gpio_request(gpio, NULL);
35 if (ret_val != 0) {
36 osal_printk("[%s]:request gpio[No:%u] failed.\n", __FUNCTION__, gpio);
37 return -1;
38 }
39
40 desc = gpio_to_desc(gpio);
41 if (desc == NULL) {
42 osal_printk("[%s]:gpio_to_desc failed.\n", __FUNCTION__);
43 gpio_free(gpio);
44 return -1;
45 }
46
47 ret_val = gpiod_get_direction(desc);
48 if (ret_val != 0 && ret_val != 1) {
49 osal_printk("[%s]:gpiod_get_direction failed. return %d\n", __FUNCTION__, ret_val);
50 gpio_free(gpio);
51 return -1;
52 }
53
54 gpio_free(gpio);
55
56 return ret_val;
57 }
58 EXPORT_SYMBOL(osal_gpio_get_direction);
59
osal_gpio_set_direction(unsigned int gpio,unsigned int dir)60 int osal_gpio_set_direction(unsigned int gpio, unsigned int dir)
61 {
62 int ret;
63
64 if (dir != 1 && dir != 0) {
65 osal_printk("set direction failed. invalid dir\n");
66 return -1;
67 }
68
69 ret = gpio_request(gpio, NULL);
70 if (ret != 0) {
71 osal_printk("[%s]:request gpio[No:%d] failed.\n", __FUNCTION__, gpio);
72 return -1;
73 }
74
75 if (dir == 1) { /* set input */
76 ret = gpio_direction_input(gpio);
77 if (ret != 0) {
78 osal_printk("set direction input failed. gpio[No:%d], return %d\n", gpio, ret);
79 goto out;
80 }
81 } else { /* set output */
82 ret = gpio_direction_output(gpio, 0); /* default output low level */
83 if (ret != 0) {
84 osal_printk("set direction output failed, gpio[No:%u], return %d\n", gpio, ret);
85 goto out;
86 }
87 }
88
89 out:
90 gpio_free(gpio);
91
92 return ret;
93 }
94 EXPORT_SYMBOL(osal_gpio_set_direction);
95
osal_gpio_set_value(unsigned int gpio,int value)96 void osal_gpio_set_value(unsigned int gpio, int value)
97 {
98 int ret_val;
99
100 ret_val = gpio_request(gpio, NULL);
101 if (ret_val != 0) {
102 osal_printk("[%s]:request gpio[No:%d] failed.\n", __FUNCTION__, gpio);
103 gpio_free(gpio);
104 return;
105 }
106 gpio_set_value(gpio, value);
107 gpio_free(gpio);
108
109 return;
110 }
111 EXPORT_SYMBOL(osal_gpio_set_value);
112
osal_gpio_get_value(unsigned int gpio)113 int osal_gpio_get_value(unsigned int gpio)
114 {
115 int ret_val;
116
117 ret_val = gpio_request(gpio, NULL);
118 if (ret_val != 0) {
119 osal_printk("[%s]:request gpio[No:%d] failed.\n", __FUNCTION__, gpio);
120 gpio_free(gpio);
121 return -1;
122 }
123 ret_val = gpio_get_value(gpio);
124 gpio_free(gpio);
125
126 return ret_val;
127 }
128 EXPORT_SYMBOL(osal_gpio_get_value);
129
osal_gpio_irq_request(unsigned int gpio,osal_irq_handler handler,unsigned long flags,const char * name,void * dev)130 int osal_gpio_irq_request(unsigned int gpio, osal_irq_handler handler,
131 unsigned long flags, const char *name, void *dev)
132 {
133 int ret, irq;
134
135 if (name == NULL || gpio >= MAX_GPIO_NUM) {
136 printk("%s - param invalid ! \n", __FUNCTION__);
137 return -1;
138 }
139
140 ret = gpio_request(gpio, NULL);
141 if (ret != 0) {
142 osal_printk("[%s]:request gpio[No:%d] failed.\n", __FUNCTION__, gpio);
143 return -1;
144 }
145
146 irq = gpio_to_irq(gpio);
147 if (irq < 0) {
148 osal_printk("call gpio_to_irq failed. gpio[No:%d], return %d\n", gpio, ret);
149 gpio_free(gpio);
150 return -1;
151 }
152 g_gpio_to_irq[gpio] = irq;
153 ret = request_threaded_irq(irq, (irq_handler_t)handler, NULL, flags, name, dev);
154 if (ret != 0) {
155 osal_printk("call request_threaded_irq failed. gpio[No:%d], return %d\n", gpio, ret);
156 gpio_free(gpio);
157 return -1;
158 }
159 gpio_free(gpio);
160
161 return irq;
162 }
163 EXPORT_SYMBOL(osal_gpio_irq_request);
164
osal_gpio_irq_free(unsigned int gpio,void * dev)165 void osal_gpio_irq_free(unsigned int gpio, void *dev)
166 {
167 unsigned int irq;
168
169 if (gpio >= MAX_GPIO_NUM) {
170 osal_printk("[%s]:invalid gpio num.\n", __FUNCTION__);
171 return;
172 }
173
174 if (g_gpio_to_irq[gpio] == 0) {
175 osal_printk("[%s]:this gpio had not requested irq before.[GPIO:%d]\n", __FUNCTION__, gpio);
176 return;
177 }
178
179 irq = g_gpio_to_irq[gpio];
180 free_irq(irq, dev);
181 g_gpio_to_irq[gpio] = 0;
182
183 return;
184 }
185 EXPORT_SYMBOL(osal_gpio_irq_free);
186
187