Merge branch 'CR_2868_515_evb_rgb2hdmi_shengyang.chen' into 'jh7110-5.15.y-devel'
[platform/kernel/linux-starfive.git] / drivers / gpio / gpio-starfive-jh7110.c
1 /*
2  ******************************************************************************
3  * @file  gpio-starfive-vic7110.c
4  * @author  StarFive Technology
5  * @version  V1.0
6  * @date  08/13/2020
7  * @brief
8  ******************************************************************************
9  * @copy
10  *
11  * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
12  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
13  * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
14  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
15  * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
16  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
17  *
18  * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
19  */
20
21 #include <linux/bitops.h>
22 #include <linux/device.h>
23 #include <linux/module.h>
24 #include <linux/errno.h>
25 #include <linux/of_irq.h>
26 #include <linux/gpio/driver.h>
27 #include <linux/interrupt.h>
28 #include <linux/irqchip/chained_irq.h>
29 #include <linux/init.h>
30 #include <linux/of.h>
31 #include <linux/pinctrl/consumer.h>
32 #include <linux/platform_device.h>
33 #include <linux/pm.h>
34 #include <linux/slab.h>
35 #include <linux/proc_fs.h>
36 #include <linux/mutex.h>
37 #include <linux/uaccess.h>
38 #include <linux/spinlock.h>
39
40 #define GPIO_EN         0xdc
41 #define GPIO_IS_LOW     0xe0
42 #define GPIO_IS_HIGH    0xe4
43 #define GPIO_IC_LOW     0xe8
44 #define GPIO_IC_HIGH    0xec
45 #define GPIO_IBE_LOW    0xf0
46 #define GPIO_IBE_HIGH   0xf4
47 #define GPIO_IEV_LOW    0xf8
48 #define GPIO_IEV_HIGH   0xfc
49 #define GPIO_IE_LOW     0x100
50 #define GPIO_IE_HIGH    0x104
51
52 //read only
53 #define GPIO_RIS_LOW    0x108
54 #define GPIO_RIS_HIGH   0x10c
55 #define GPIO_MIS_LOW    0x110
56 #define GPIO_MIS_HIGH   0x114
57 #define GPIO_DIN_LOW    0x118
58 #define GPIO_DIN_HIGH   0x11c
59
60 #define GPIO_DOEN_X_REG 0x0
61 #define GPIO_DOUT_X_REG 0x40
62
63 #define GPIO_INPUT_ENABLE_X_REG 0x120
64
65 #define MAX_GPIO         64
66
67 #define PROC_VIC "vic_gpio7110"
68
69 struct sfvic7110_gpio {
70         raw_spinlock_t          lock;
71         void __iomem            *base;
72         struct gpio_chip        gc;
73         unsigned long           enabled;
74         unsigned                trigger[MAX_GPIO];
75         unsigned int            irq_parent[MAX_GPIO];
76         struct sfvic7110_gpio   *self_ptr[MAX_GPIO];
77 };
78
79 /* lock for procfs read access */
80 static DEFINE_MUTEX(read_lock);
81
82 /* lock for procfs write access */
83 static DEFINE_MUTEX(write_lock);
84
85 static DEFINE_SPINLOCK(sfg_lock);
86
87 static void __iomem *gpio_base = NULL;
88
89 static int sfvic7110_direction_input(struct gpio_chip *gc, unsigned offset)
90 {
91         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
92         unsigned long flags;
93         unsigned int v;
94
95         if (offset >= gc->ngpio)
96                 return -EINVAL;
97
98         raw_spin_lock_irqsave(&chip->lock, flags);
99         v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
100         v &= ~(0x3f << ((offset & 0x3) * 8));
101         v |= 1 << ((offset & 0x3) * 8);
102         writel_relaxed(v, chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
103         raw_spin_unlock_irqrestore(&chip->lock, flags);
104
105         return 0;
106 }
107
108 static int sfvic7110_direction_output(struct gpio_chip *gc, unsigned offset, int value)
109 {
110         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
111         unsigned long flags;
112         unsigned int v;
113
114         if (offset >= gc->ngpio)
115                 return -EINVAL;
116
117         raw_spin_lock_irqsave(&chip->lock, flags);
118         v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
119         v &= ~(0x3f << ((offset & 0x3) * 8));
120         writel_relaxed(v, chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
121
122         v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
123         v &= ~(0x7f << ((offset & 0x3) * 8));
124         v |= value << ((offset & 0x3) * 8);
125         writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
126         raw_spin_unlock_irqrestore(&chip->lock, flags);
127
128         return 0;
129 }
130
131 static int sfvic7110_get_direction(struct gpio_chip *gc, unsigned offset)
132 {
133         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
134         unsigned int v;
135
136         if (offset >= gc->ngpio)
137                 return -EINVAL;
138
139         v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
140         return !!(v & (0x3f << ((offset & 0x3) * 8)));
141 }
142
143 static int sfvic7110_get_value(struct gpio_chip *gc, unsigned offset)
144 {
145         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
146         int value;
147
148         if (offset >= gc->ngpio)
149                 return -EINVAL;
150
151         if(offset < 32){
152                 value = readl_relaxed(chip->base + GPIO_DIN_LOW);
153                 return (value >> offset) & 0x1;
154         } else {
155                 value = readl_relaxed(chip->base + GPIO_DIN_HIGH);
156                 return (value >> (offset - 32)) & 0x1;
157         }
158 }
159
160 static void sfvic7110_set_value(struct gpio_chip *gc, unsigned offset, int value)
161 {
162         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
163         unsigned long flags;
164         unsigned int v;
165
166         if (offset >= gc->ngpio)
167                 return;
168
169         raw_spin_lock_irqsave(&chip->lock, flags);
170         v = readl_relaxed(chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
171         v &= ~(0x7f << ((offset & 0x3) * 8));
172         v |= value << ((offset & 0x3) * 8);
173         writel_relaxed(v, chip->base + GPIO_DOUT_X_REG + (offset & ~0x3));
174         raw_spin_unlock_irqrestore(&chip->lock, flags);
175 }
176
177 static void sfvic7110_set_ie(struct sfvic7110_gpio *chip, int offset)
178 {
179         unsigned long flags;
180         int old_value, new_value;
181         int reg_offset, index;
182
183         if(offset < 32) {
184                 reg_offset = 0;
185                 index = offset;
186         } else {
187                 reg_offset = 4;
188                 index = offset - 32;
189         }
190         raw_spin_lock_irqsave(&chip->lock, flags);
191         old_value = readl_relaxed(chip->base + GPIO_IE_LOW + reg_offset);
192         new_value = old_value | ( 1 << index);
193         writel_relaxed(new_value, chip->base + GPIO_IE_LOW + reg_offset);
194         raw_spin_unlock_irqrestore(&chip->lock, flags);
195 }
196
197 static int sfvic7110_irq_set_type(struct irq_data *d, unsigned trigger)
198 {
199         struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
200         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
201         int offset = irqd_to_hwirq(d);
202         unsigned int reg_is, reg_ibe, reg_iev;
203         int reg_offset, index;
204
205         if (offset < 0 || offset >= gc->ngpio)
206                 return -EINVAL;
207
208         if(offset < 32) {
209                 reg_offset = 0;
210                 index = offset;
211         } else {
212                 reg_offset = 4;
213                 index = offset - 32;
214         }
215         switch(trigger) {
216         case IRQ_TYPE_LEVEL_HIGH:
217                 reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
218                 reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
219                 reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
220                 reg_is  &= (~(0x1<< index));
221                 reg_ibe &= (~(0x1<< index));
222                 reg_iev |= (~(0x1<< index));
223                 writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
224                 writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
225                 writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
226                 break;
227         case IRQ_TYPE_LEVEL_LOW:
228                 reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
229                 reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
230                 reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
231                 reg_is  &= (~(0x1<< index));
232                 reg_ibe &= (~(0x1<< index));
233                 reg_iev &= (0x1<< index);
234                 writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
235                 writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
236                 writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
237                 break;
238         case IRQ_TYPE_EDGE_BOTH:
239                 reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
240                 reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
241                 reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
242                 reg_is  |= (0x1<< index);
243                 reg_ibe |= (0x1<< index);
244                 reg_iev |= (~(0x1<< index));
245                 writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
246                 writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
247                 writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
248                 break;
249         case IRQ_TYPE_EDGE_RISING:
250                 reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
251                 reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
252                 reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
253                 reg_is  |= (0x1<< index);
254                 reg_ibe &= (~(0x1<< index));
255                 reg_iev |= (0x1<< index);
256                 writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
257                 writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
258                 writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
259                 break;
260         case IRQ_TYPE_EDGE_FALLING:
261                 reg_is = readl_relaxed(chip->base + GPIO_IS_LOW + reg_offset);
262                 reg_ibe = readl_relaxed(chip->base + GPIO_IBE_LOW + reg_offset);
263                 reg_iev = readl_relaxed(chip->base + GPIO_IEV_LOW + reg_offset);
264                 reg_is  |= (0x1<< index);
265                 reg_ibe &= (~(0x1<< index));
266                 reg_iev &= (~(0x1<< index));
267                 writel_relaxed(reg_is, chip->base + GPIO_IS_LOW + reg_offset);
268                 writel_relaxed(reg_ibe, chip->base + GPIO_IBE_LOW + reg_offset);
269                 writel_relaxed(reg_iev, chip->base + GPIO_IEV_LOW + reg_offset);
270                 break;
271         }
272
273         chip->trigger[offset] = trigger;
274         sfvic7110_set_ie(chip, offset);
275         return 0;
276 }
277
278 /* chained_irq_{enter,exit} already mask the parent */
279 static void sfvic7110_irq_mask(struct irq_data *d)
280 {
281         struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
282         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
283         unsigned int value;
284         int offset = irqd_to_hwirq(d);
285         int reg_offset, index;
286
287         if (offset < 0 || offset >= gc->ngpio)
288                 return;
289
290         if(offset < 32) {
291                 reg_offset = 0;
292                 index = offset;
293         } else {
294                 reg_offset = 4;
295                 index = offset - 32;
296         }
297
298         value = readl_relaxed(chip->base + GPIO_IE_LOW + reg_offset);
299         value &= ~(0x1 << index);
300         writel_relaxed(value,chip->base + GPIO_IE_LOW + reg_offset);
301 }
302
303 static void sfvic7110_irq_unmask(struct irq_data *d)
304 {
305         struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
306         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
307         unsigned int value;
308         int offset = irqd_to_hwirq(d);
309         int reg_offset, index;
310
311         if (offset < 0 || offset >= gc->ngpio)
312                 return;
313
314         if(offset < 32) {
315                 reg_offset = 0;
316                 index = offset;
317         } else {
318                 reg_offset = 4;
319                 index = offset - 32;
320         }
321
322         value = readl_relaxed(chip->base + GPIO_IE_LOW + reg_offset);
323         value |= (0x1 << index);
324         writel_relaxed(value,chip->base + GPIO_IE_LOW + reg_offset);
325 }
326
327 static void sfvic7110_irq_enable(struct irq_data *d)
328 {
329         struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
330         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
331         int offset = irqd_to_hwirq(d);
332
333         sfvic7110_irq_unmask(d);
334         assign_bit(offset, &chip->enabled, 1);
335 }
336
337 static void sfvic7110_irq_disable(struct irq_data *d)
338 {
339         struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
340         struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
341         int offset = irqd_to_hwirq(d) % MAX_GPIO; // must not fail
342
343         assign_bit(offset, &chip->enabled, 0);
344         sfvic7110_set_ie(chip, offset);
345 }
346
347 static struct irq_chip sfvic7110_irqchip = {
348         .name           = "sfvic7110-gpio",
349         .irq_set_type   = sfvic7110_irq_set_type,
350         .irq_mask       = sfvic7110_irq_mask,
351         .irq_unmask     = sfvic7110_irq_unmask,
352         .irq_enable     = sfvic7110_irq_enable,
353         .irq_disable    = sfvic7110_irq_disable,
354 };
355
356
357 static int starfive_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
358                                              unsigned int child,
359                                              unsigned int child_type,
360                                              unsigned int *parent,
361                                              unsigned int *parent_type)
362 {
363         struct sfvic7110_gpio *chip;// = gpiochip_get_data(gc);
364         struct irq_data *d;// = irq_get_irq_data(chip->irq_parent[child]);
365
366 #if 0
367         chip = gpiochip_get_data(gc);
368         d = irq_get_irq_data(chip->irq_parent[child]);
369         *parent_type = IRQ_TYPE_NONE;
370         *parent = irqd_to_hwirq(d);
371 #endif
372         return 0;
373 }
374
375 static irqreturn_t sfvic7110_irq_handler(int irq, void *gc)
376 {
377         int offset;
378         // = self_ptr - &chip->self_ptr[0];
379         int reg_offset, index;
380         unsigned int value;
381         unsigned long flags;
382         struct sfvic7110_gpio *chip = gc;
383
384         for (offset = 0; offset < 64; offset++) {
385                 if(offset < 32) {
386                         reg_offset = 0;
387                         index = offset;
388                 } else {
389                         reg_offset = 4;
390                         index = offset - 32;
391                 }
392
393                 raw_spin_lock_irqsave(&chip->lock, flags);
394                 value = readl_relaxed(chip->base + GPIO_MIS_LOW + reg_offset);
395                 if(value & BIT(index))
396                         writel_relaxed(BIT(index), chip->base + GPIO_IC_LOW +
397                                                    reg_offset);
398
399                 //generic_handle_irq(irq_find_mapping(chip->gc.irq.domain,
400                 //                                    offset));
401                 raw_spin_unlock_irqrestore(&chip->lock, flags);
402         }
403
404         return IRQ_HANDLED;
405 }
406
407 void sf_vic_gpio_dout_reverse(int gpio,int en)
408 {
409         unsigned int value;
410         int offset;
411
412         if(!gpio_base)
413                 return;
414
415         offset = GPIO_DOUT_X_REG + (gpio & ~0x3);
416
417         spin_lock(&sfg_lock);
418         value = ioread32(gpio_base + offset);
419         value &= ~(0x7f << ((offset & 0x3) * 8));
420         value |= (en & 0x1) << ((offset & 0x3) * 8);
421         iowrite32(value, gpio_base + offset);
422         spin_unlock(&sfg_lock);
423 }
424 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_reverse);
425
426 void sf_vic_gpio_dout_value(int gpio,int v)
427 {
428         unsigned int value;
429         int offset;
430
431         if(!gpio_base)
432                 return;
433
434         offset = GPIO_DOUT_X_REG + (gpio & ~0x3);
435
436         spin_lock(&sfg_lock);
437         value = ioread32(gpio_base + offset);
438         value &= ~(0x7f << ((offset & 0x3) * 8));
439         value |= (v & 0x7f) << ((offset & 0x3) * 8);
440         iowrite32(value,gpio_base + offset);
441         spin_unlock(&sfg_lock);
442 }
443 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_value);
444
445 void sf_vic_gpio_dout_low(int gpio)
446 {
447         sf_vic_gpio_dout_value(gpio, 0);
448 }
449 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_low);
450
451 void sf_vic_gpio_dout_high(int gpio)
452 {
453         sf_vic_gpio_dout_value(gpio, 1);
454 }
455 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_high);
456
457 void sf_vic_gpio_doen_reverse(int gpio,int en)
458 {
459         unsigned int value;
460         int offset;
461
462         if(!gpio_base)
463                 return;
464
465         offset = GPIO_DOEN_X_REG + (gpio & ~0x3);
466
467         spin_lock(&sfg_lock);
468         value = ioread32(gpio_base + offset);
469         value &= ~(0x3f << ((offset & 0x3) * 8));
470         value |= (en & 0x1) << ((offset & 0x3) * 8);
471         iowrite32(value,gpio_base + offset);
472         spin_unlock(&sfg_lock);
473 }
474 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_reverse);
475
476 void sf_vic_gpio_doen_value(int gpio,int v)
477 {
478         unsigned int value;
479         int offset;
480
481         if(!gpio_base)
482                 return;
483
484         offset = GPIO_DOEN_X_REG + (gpio & ~0x3);
485
486         spin_lock(&sfg_lock);
487         value = ioread32(gpio_base + offset);
488         value &= ~(0x3f << ((offset & 0x3) * 8));
489         value |= (v & 0x3f) << ((offset & 0x3) * 8);
490         iowrite32(value,gpio_base + offset);
491         spin_unlock(&sfg_lock);
492 }
493 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_value);
494
495 void sf_vic_gpio_doen_low(int gpio)
496 {
497         sf_vic_gpio_doen_value(gpio, 0);
498 }
499 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_low);
500
501 void sf_vic_gpio_doen_high(int gpio)
502 {
503         sf_vic_gpio_doen_value(gpio, 1);
504 }
505 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_high);
506
507 void sf_vic_gpio_manual(int offset,int v)
508 {
509         unsigned int value;
510
511         if(!gpio_base)
512                 return ;
513
514         spin_lock(&sfg_lock);
515         value = ioread32(gpio_base + offset);
516         value &= ~(0xFF);
517         value |= (v&0xFF);
518         iowrite32(value,gpio_base + offset);
519         spin_unlock(&sfg_lock);
520 }
521 EXPORT_SYMBOL_GPL(sf_vic_gpio_manual);
522
523 static int str_to_num(char *str)
524 {
525         char *p = str;
526         int value = 0;
527
528         if((*p == '0') && (*(p + 1) == 'x' || *(p + 1) == 'X')) {
529                 p = p + 2;
530                 while(((*p >= '0') && (*p <= '9')) ||
531                       ((*p >= 'a') && (*p <= 'f')) ||
532                       ((*p >= 'A') && (*p <= 'F'))) {
533                         if((*p >= '0') && (*p <= '9'))
534                                 value = value * 16 + (*p - '0');
535                         if((*p >= 'a') && (*p <= 'f'))
536                                 value = value * 16 + 10 + (*p - 'a');
537                         if((*p >= 'A') && (*p <= 'F'))
538                                 value = value * 16 + 10 + (*p - 'A');
539                         p = p + 1;
540                 }
541         } else {
542                 while((*p >= '0') && (*p <= '9')) {
543                         value = value * 10 + (*p - '0');
544                         p = p + 1;
545                 }
546         }
547
548         if(*p != '\0')
549                 return -EFAULT;
550
551         return value;
552 }
553
554 static ssize_t vic_gpio_proc_write(struct file *file, const char __user *buf,
555                                                 size_t count, loff_t *ppos)
556 {
557         int ret;
558         char message[64], cmd[8],gnum[8],v[8];
559         int gpionum, value;
560
561         if (mutex_lock_interruptible(&write_lock))
562                 return -ERESTARTSYS;
563
564         ret = copy_from_user(message, buf, count);
565         mutex_unlock(&write_lock);
566         if(ret)
567                 return -EFAULT;
568         sscanf(message, "%s %s %s", cmd, gnum, v);
569         gpionum = str_to_num(gnum);
570         if(gpionum < 0)
571                 return -EFAULT;
572         value = str_to_num(v);
573         if(value < 0)
574                 return -EFAULT;
575
576         if(!strcmp(cmd,"dout")) {
577                 if(gpionum < 0 || gpionum > 63){
578                         printk(KERN_ERR "vic-gpio: dout gpionum (0-63)  value (0/1) invalid: gpionum = %d value = %d\n",
579                                gpionum,value);
580                         return -EFAULT;
581                 }
582                 sf_vic_gpio_dout_value(gpionum, value);
583         }else if(!strcmp(cmd,"doen")) {
584                 if(gpionum < 0 || gpionum > 63){
585                         printk(KERN_ERR "vic-gpio: doen gpionum (0-63)  value (0/1) invalid: gpionum = %d value = %d\n",
586                                gpionum,value);
587                         return -EFAULT;
588                 }
589                 sf_vic_gpio_doen_value(gpionum,value);
590         }else if(!strcmp(cmd,"utrv")) {
591                 if(gpionum < 0 || gpionum > 63){
592                         printk(KERN_ERR "vic-gpio: utrv gpionum (0-63) is invalid: %d\n",gpionum);
593                         return -EFAULT;
594                 }
595                 sf_vic_gpio_doen_reverse(gpionum,value);
596         }else if(!strcmp(cmd,"enrv")) {
597                 if(gpionum < 0 || gpionum > 63){
598                         printk(KERN_ERR "vic-gpio: enrv gpionum (0-63) is invalid: %d\n",gpionum);
599                         return -EFAULT;
600                 }
601                 sf_vic_gpio_doen_reverse(gpionum, value);
602         }else if(!strcmp(cmd,"manu")) {
603                 if(gpionum < 0x250 || gpionum > 0x378 || (gpionum & 0x3)){
604                         printk(KERN_ERR "vic-gpio: manu offset (0x250-0x378 & mod 4) is invalid: %d\n",gpionum);
605                         return -EFAULT;
606                 }
607                 sf_vic_gpio_manual(gpionum, value);
608         }else {
609                 printk(KERN_ERR "vic-gpio: cmd (dout  doen utrv enrv manu) invalid: %s\n",cmd);
610         }
611
612         return count;
613 }
614
615 static ssize_t vic_gpio_proc_read(struct file *file, char __user *buf,
616                                   size_t count, loff_t *ppos)
617 {
618         int ret;
619         unsigned int copied;
620         char message[256];
621
622         sprintf(message, "Usage: echo 'cmd gpionum value' >/proc/vic_gpio\n\t"
623                 "cmd: dout  doen utrv enrv or manu\n\t"
624                 "gpionum: gpionum or address offset for manu\n\t"
625                 "value: 0/1 for utrv/enrv, value for dout/doen/manual\n");
626         copied = strlen(message);
627
628         if(*ppos >= copied)
629                 return 0;
630
631         if (mutex_lock_interruptible(&read_lock))
632                 return -ERESTARTSYS;
633
634         ret = copy_to_user(buf, message, copied);
635         if(ret) {
636                 mutex_unlock(&read_lock);
637         }
638         *ppos += copied;
639
640         mutex_unlock(&read_lock);
641
642         return copied;
643 }
644
645 static const struct file_operations vic_gpio_fops = {
646         .owner  = THIS_MODULE,
647         .read   = vic_gpio_proc_read,
648         .write  = vic_gpio_proc_write,
649         .llseek = noop_llseek,
650 };
651
652 static int sfvic7110_gpio_probe(struct platform_device *pdev)
653 {
654         struct device *dev = &pdev->dev;
655         struct sfvic7110_gpio *chip;
656         struct resource *res;
657         int irq, ret, ngpio;
658         int loop;
659         struct gpio_irq_chip *girq;
660         struct device_node *node = pdev->dev.of_node;
661         struct device_node *irq_parent;
662         struct irq_domain *parent;
663
664         chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
665         if (!chip) {
666                 dev_err(dev, "out of memory\n");
667                 return -ENOMEM;
668         }
669
670         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
671         chip->base = devm_ioremap_resource(dev, res);
672         if (IS_ERR(chip->base)) {
673                 dev_err(dev, "failed to allocate device memory\n");
674                 return PTR_ERR(chip->base);
675         }
676         gpio_base = chip->base ;
677
678         ngpio = 64;
679
680         raw_spin_lock_init(&chip->lock);
681         chip->gc.direction_input = sfvic7110_direction_input;
682         chip->gc.direction_output = sfvic7110_direction_output;
683         chip->gc.get_direction = sfvic7110_get_direction;
684         chip->gc.get = sfvic7110_get_value;
685         chip->gc.set = sfvic7110_set_value;
686         chip->gc.base = 0;
687         chip->gc.ngpio = ngpio;
688         chip->gc.label = dev_name(dev);
689         chip->gc.parent = dev;
690         chip->gc.owner = THIS_MODULE;
691
692         irq_parent = of_irq_find_parent(node);
693         if (!irq_parent) {
694                 dev_err(dev, "no IRQ parent node\n");
695                 return -ENODEV;
696         }
697         parent = irq_find_host(irq_parent);
698         if (!parent) {
699                 dev_err(dev, "no IRQ parent domain\n");
700                 return -ENODEV;
701         }
702
703         girq = &chip->gc.irq;
704         girq->chip = &sfvic7110_irqchip;
705         girq->fwnode = of_node_to_fwnode(node);
706         girq->parent_domain = parent;
707         girq->child_to_parent_hwirq = starfive_gpio_child_to_parent_hwirq;
708         girq->handler = handle_simple_irq;
709         girq->default_type = IRQ_TYPE_NONE;
710
711         /* Disable all GPIO interrupts before enabling parent interrupts */
712         iowrite32(0, chip->base + GPIO_IE_HIGH);
713         iowrite32(0, chip->base + GPIO_IE_LOW);
714         chip->enabled = 0;
715
716         platform_set_drvdata(pdev, chip);
717
718         ret = gpiochip_add_data(&chip->gc, chip);
719         if (ret){
720                 dev_err(dev, "gpiochip_add_data ret=%d!\n", ret);
721                 return ret;
722         }
723
724 #if 0
725         /* Disable all GPIO interrupts before enabling parent interrupts */
726         iowrite32(0, chip->base + GPIO_IE_HIGH);
727         iowrite32(0, chip->base + GPIO_IE_LOW);
728         chip->enabled = 0;
729
730         ret = gpiochip_irqchip_add(&chip->gc, &sfvic7110_irqchip, 0,
731                                    handle_simple_irq, IRQ_TYPE_NONE);
732         if (ret) {
733                 dev_err(dev, "could not add irqchip\n");
734                 gpiochip_remove(&chip->gc);
735                 return ret;
736         }
737 #endif
738
739         irq = platform_get_irq(pdev, 0);
740         if (irq < 0) {
741                 dev_err(dev, "Cannot get IRQ resource\n");
742                 return irq;
743         }
744
745         chip->irq_parent[0] = irq;
746
747         ret = devm_request_irq(dev, irq, sfvic7110_irq_handler, IRQF_SHARED,
748                                dev_name(dev), chip);
749         if (ret) {
750                 dev_err(dev, "IRQ handler registering failed (%d)\n", ret);
751                 return ret;
752         }
753
754         writel_relaxed(1, chip->base + GPIO_EN);
755
756         for(loop = 0; loop < MAX_GPIO; loop++) {
757                 unsigned int v;
758                 v = readl_relaxed(chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
759                 v |= 0x1;
760                 writel_relaxed(v, chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
761         }
762
763         if (proc_create(PROC_VIC, 0, NULL, (void *)&vic_gpio_fops) == NULL) {
764                 return -ENOMEM;
765         }
766         dev_info(dev, "SiFive GPIO chip registered %d GPIOs\n", ngpio);
767
768         return 0;
769 }
770
771 static const struct of_device_id sfvic7110_gpio_match[] = {
772         { .compatible = "starfive,gpio7110", },
773         { },
774 };
775
776 static struct platform_driver sfvic7110_gpio_driver = {
777         .probe  = sfvic7110_gpio_probe,
778         .driver = {
779                 .name           = "sfvic7110_gpio",
780                 .of_match_table = of_match_ptr(sfvic7110_gpio_match),
781         },
782 };
783
784 static int __init sfvic7110_gpio_init(void)
785 {
786         return platform_driver_register(&sfvic7110_gpio_driver);
787 }
788 subsys_initcall(sfvic7110_gpio_init);
789
790 static void __exit sfvic7110_gpio_exit(void)
791 {
792         platform_driver_unregister(&sfvic7110_gpio_driver);
793 }
794 module_exit(sfvic7110_gpio_exit);
795
796 MODULE_LICENSE("GPL");
797 MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
798 MODULE_DESCRIPTION("Starfive VIC GPIO generator driver");