Merge branch 'jh7110_dev_5.15' of http://192.168.110.45/sdk/sft-riscvpi-linux-5.10...
[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 static irqreturn_t sfvic7110_irq_handler(int irq, void *gc)
357 {
358         int offset;
359         // = self_ptr - &chip->self_ptr[0];
360         int reg_offset, index;
361         unsigned int value;
362         unsigned long flags;
363         struct sfvic7110_gpio *chip = gc;
364
365         for (offset = 0; offset < 64; offset++) {
366                 if(offset < 32) {
367                         reg_offset = 0;
368                         index = offset;
369                 } else {
370                         reg_offset = 4;
371                         index = offset - 32;
372                 }
373
374                 raw_spin_lock_irqsave(&chip->lock, flags);
375                 value = readl_relaxed(chip->base + GPIO_MIS_LOW + reg_offset);
376                 if(value & BIT(index))
377                         writel_relaxed(BIT(index), chip->base + GPIO_IC_LOW +
378                                                    reg_offset);
379
380                 //generic_handle_irq(irq_find_mapping(chip->gc.irq.domain,
381                 //                                    offset));
382                 raw_spin_unlock_irqrestore(&chip->lock, flags);
383         }
384
385         return IRQ_HANDLED;
386 }
387
388 void sf_vic_gpio_dout_reverse(int gpio,int en)
389 {
390         unsigned int value;
391         int offset;
392
393         if(!gpio_base)
394                 return;
395
396         offset = GPIO_DOUT_X_REG + (gpio & ~0x3);
397
398         spin_lock(&sfg_lock);
399         value = ioread32(gpio_base + offset);
400         value &= ~(0x7f << ((offset & 0x3) * 8));
401         value |= (en & 0x1) << ((offset & 0x3) * 8);
402         iowrite32(value, gpio_base + offset);
403         spin_unlock(&sfg_lock);
404 }
405 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_reverse);
406
407 void sf_vic_gpio_dout_value(int gpio,int v)
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 |= (v & 0x7f) << ((offset & 0x3) * 8);
421         iowrite32(value,gpio_base + offset);
422         spin_unlock(&sfg_lock);
423 }
424 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_value);
425
426 void sf_vic_gpio_dout_low(int gpio)
427 {
428         sf_vic_gpio_dout_value(gpio, 0);
429 }
430 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_low);
431
432 void sf_vic_gpio_dout_high(int gpio)
433 {
434         sf_vic_gpio_dout_value(gpio, 1);
435 }
436 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_high);
437
438 void sf_vic_gpio_doen_reverse(int gpio,int en)
439 {
440         unsigned int value;
441         int offset;
442
443         if(!gpio_base)
444                 return;
445
446         offset = GPIO_DOEN_X_REG + (gpio & ~0x3);
447
448         spin_lock(&sfg_lock);
449         value = ioread32(gpio_base + offset);
450         value &= ~(0x3f << ((offset & 0x3) * 8));
451         value |= (en & 0x1) << ((offset & 0x3) * 8);
452         iowrite32(value,gpio_base + offset);
453         spin_unlock(&sfg_lock);
454 }
455 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_reverse);
456
457 void sf_vic_gpio_doen_value(int gpio,int v)
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 |= (v & 0x3f) << ((offset & 0x3) * 8);
471         iowrite32(value,gpio_base + offset);
472         spin_unlock(&sfg_lock);
473 }
474 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_value);
475
476 void sf_vic_gpio_doen_low(int gpio)
477 {
478         sf_vic_gpio_doen_value(gpio, 0);
479 }
480 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_low);
481
482 void sf_vic_gpio_doen_high(int gpio)
483 {
484         sf_vic_gpio_doen_value(gpio, 1);
485 }
486 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_high);
487
488 void sf_vic_gpio_manual(int offset,int v)
489 {
490         unsigned int value;
491
492         if(!gpio_base)
493                 return ;
494
495         spin_lock(&sfg_lock);
496         value = ioread32(gpio_base + offset);
497         value &= ~(0xFF);
498         value |= (v&0xFF);
499         iowrite32(value,gpio_base + offset);
500         spin_unlock(&sfg_lock);
501 }
502 EXPORT_SYMBOL_GPL(sf_vic_gpio_manual);
503
504 static int str_to_num(char *str)
505 {
506         char *p = str;
507         int value = 0;
508
509         if((*p == '0') && (*(p + 1) == 'x' || *(p + 1) == 'X')) {
510                 p = p + 2;
511                 while(((*p >= '0') && (*p <= '9')) ||
512                       ((*p >= 'a') && (*p <= 'f')) ||
513                       ((*p >= 'A') && (*p <= 'F'))) {
514                         if((*p >= '0') && (*p <= '9'))
515                                 value = value * 16 + (*p - '0');
516                         if((*p >= 'a') && (*p <= 'f'))
517                                 value = value * 16 + 10 + (*p - 'a');
518                         if((*p >= 'A') && (*p <= 'F'))
519                                 value = value * 16 + 10 + (*p - 'A');
520                         p = p + 1;
521                 }
522         } else {
523                 while((*p >= '0') && (*p <= '9')) {
524                         value = value * 10 + (*p - '0');
525                         p = p + 1;
526                 }
527         }
528
529         if(*p != '\0')
530                 return -EFAULT;
531
532         return value;
533 }
534
535 static ssize_t vic_gpio_proc_write(struct file *file, const char __user *buf,
536                                                 size_t count, loff_t *ppos)
537 {
538         int ret;
539         char message[64], cmd[8],gnum[8],v[8];
540         int gpionum, value;
541
542         if (mutex_lock_interruptible(&write_lock))
543                 return -ERESTARTSYS;
544
545         ret = copy_from_user(message, buf, count);
546         mutex_unlock(&write_lock);
547         if(ret)
548                 return -EFAULT;
549         sscanf(message, "%s %s %s", cmd, gnum, v);
550         gpionum = str_to_num(gnum);
551         if(gpionum < 0)
552                 return -EFAULT;
553         value = str_to_num(v);
554         if(value < 0)
555                 return -EFAULT;
556
557         if(!strcmp(cmd,"dout")) {
558                 if(gpionum < 0 || gpionum > 63){
559                         printk(KERN_ERR "vic-gpio: dout gpionum (0-63)  value (0/1) invalid: gpionum = %d value = %d\n",
560                                gpionum,value);
561                         return -EFAULT;
562                 }
563                 sf_vic_gpio_dout_value(gpionum, value);
564         }else if(!strcmp(cmd,"doen")) {
565                 if(gpionum < 0 || gpionum > 63){
566                         printk(KERN_ERR "vic-gpio: doen gpionum (0-63)  value (0/1) invalid: gpionum = %d value = %d\n",
567                                gpionum,value);
568                         return -EFAULT;
569                 }
570                 sf_vic_gpio_doen_value(gpionum,value);
571         }else if(!strcmp(cmd,"utrv")) {
572                 if(gpionum < 0 || gpionum > 63){
573                         printk(KERN_ERR "vic-gpio: utrv gpionum (0-63) is invalid: %d\n",gpionum);
574                         return -EFAULT;
575                 }
576                 sf_vic_gpio_doen_reverse(gpionum,value);
577         }else if(!strcmp(cmd,"enrv")) {
578                 if(gpionum < 0 || gpionum > 63){
579                         printk(KERN_ERR "vic-gpio: enrv gpionum (0-63) is invalid: %d\n",gpionum);
580                         return -EFAULT;
581                 }
582                 sf_vic_gpio_doen_reverse(gpionum, value);
583         }else if(!strcmp(cmd,"manu")) {
584                 if(gpionum < 0x250 || gpionum > 0x378 || (gpionum & 0x3)){
585                         printk(KERN_ERR "vic-gpio: manu offset (0x250-0x378 & mod 4) is invalid: %d\n",gpionum);
586                         return -EFAULT;
587                 }
588                 sf_vic_gpio_manual(gpionum, value);
589         }else {
590                 printk(KERN_ERR "vic-gpio: cmd (dout  doen utrv enrv manu) invalid: %s\n",cmd);
591         }
592
593         return count;
594 }
595
596 static ssize_t vic_gpio_proc_read(struct file *file, char __user *buf,
597                                   size_t count, loff_t *ppos)
598 {
599         int ret;
600         unsigned int copied;
601         char message[256];
602
603         sprintf(message, "Usage: echo 'cmd gpionum value' >/proc/vic_gpio\n\t"
604                 "cmd: dout  doen utrv enrv or manu\n\t"
605                 "gpionum: gpionum or address offset for manu\n\t"
606                 "value: 0/1 for utrv/enrv, value for dout/doen/manual\n");
607         copied = strlen(message);
608
609         if(*ppos >= copied)
610                 return 0;
611
612         if (mutex_lock_interruptible(&read_lock))
613                 return -ERESTARTSYS;
614
615         ret = copy_to_user(buf, message, copied);
616         if(ret) {
617                 mutex_unlock(&read_lock);
618         }
619         *ppos += copied;
620
621         mutex_unlock(&read_lock);
622
623         return copied;
624 }
625
626 static const struct file_operations vic_gpio_fops = {
627         .owner  = THIS_MODULE,
628         .read   = vic_gpio_proc_read,
629         .write  = vic_gpio_proc_write,
630         .llseek = noop_llseek,
631 };
632
633 static int sfvic7110_gpio_probe(struct platform_device *pdev)
634 {
635         struct device *dev = &pdev->dev;
636         struct sfvic7110_gpio *chip;
637         struct resource *res;
638         int irq, ret, ngpio;
639         int loop;
640
641         chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
642         if (!chip) {
643                 dev_err(dev, "out of memory\n");
644                 return -ENOMEM;
645         }
646
647         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
648         chip->base = devm_ioremap_resource(dev, res);
649         if (IS_ERR(chip->base)) {
650                 dev_err(dev, "failed to allocate device memory\n");
651                 return PTR_ERR(chip->base);
652         }
653         gpio_base = chip->base ;
654
655         ngpio = 64;
656
657         raw_spin_lock_init(&chip->lock);
658         chip->gc.direction_input = sfvic7110_direction_input;
659         chip->gc.direction_output = sfvic7110_direction_output;
660         chip->gc.get_direction = sfvic7110_get_direction;
661         chip->gc.get = sfvic7110_get_value;
662         chip->gc.set = sfvic7110_set_value;
663         chip->gc.base = 0;
664         chip->gc.ngpio = ngpio;
665         chip->gc.label = dev_name(dev);
666         chip->gc.parent = dev;
667         chip->gc.owner = THIS_MODULE;
668
669         ret = gpiochip_add_data(&chip->gc, chip);
670         if (ret){
671                 dev_err(dev, "gpiochip_add_data ret=%d!\n", ret);
672                 return ret;
673         }
674
675         /* Disable all GPIO interrupts before enabling parent interrupts */
676         iowrite32(0, chip->base + GPIO_IE_HIGH);
677         iowrite32(0, chip->base + GPIO_IE_LOW);
678         chip->enabled = 0;
679
680         ret = gpiochip_irqchip_add(&chip->gc, &sfvic7110_irqchip, 0,
681                                    handle_simple_irq, IRQ_TYPE_NONE);
682         if (ret) {
683                 dev_err(dev, "could not add irqchip\n");
684                 gpiochip_remove(&chip->gc);
685                 return ret;
686         }
687         irq = platform_get_irq(pdev, 0);
688         if (irq < 0) {
689                 dev_err(dev, "Cannot get IRQ resource\n");
690                 return irq;
691         }
692
693         ret = devm_request_irq(dev, irq, sfvic7110_irq_handler, IRQF_SHARED,
694                                dev_name(dev), chip);
695         if (ret) {
696                 dev_err(dev, "IRQ handler registering failed (%d)\n", ret);
697                 return ret;
698         }
699
700         writel_relaxed(1, chip->base + GPIO_EN);
701
702         for(loop = 0; loop < MAX_GPIO; loop++) {
703                 unsigned int v;
704                 v = readl_relaxed(chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
705                 v |= 0x1;
706                 writel_relaxed(v, chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
707         }
708
709         if (proc_create(PROC_VIC, 0, NULL, (void *)&vic_gpio_fops) == NULL) {
710                 return -ENOMEM;
711         }
712         dev_info(dev, "SiFive GPIO chip registered %d GPIOs\n", ngpio);
713
714         return 0;
715 }
716
717 static const struct of_device_id sfvic7110_gpio_match[] = {
718         { .compatible = "starfive,gpio7110", },
719         { },
720 };
721
722 static struct platform_driver sfvic7110_gpio_driver = {
723         .probe  = sfvic7110_gpio_probe,
724         .driver = {
725                 .name           = "sfvic7110_gpio",
726                 .of_match_table = of_match_ptr(sfvic7110_gpio_match),
727         },
728 };
729
730 static int __init sfvic7110_gpio_init(void)
731 {
732         return platform_driver_register(&sfvic7110_gpio_driver);
733 }
734 subsys_initcall(sfvic7110_gpio_init);
735
736 static void __exit sfvic7110_gpio_exit(void)
737 {
738         platform_driver_unregister(&sfvic7110_gpio_driver);
739 }
740 module_exit(sfvic7110_gpio_exit);
741
742 MODULE_LICENSE("GPL");
743 MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
744 MODULE_DESCRIPTION("Starfive VIC GPIO generator driver");