2 ******************************************************************************
3 * @file gpio-starfive-vic7110.c
4 * @author StarFive Technology
8 ******************************************************************************
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.
18 * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
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>
31 #include <linux/pinctrl/consumer.h>
32 #include <linux/platform_device.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>
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
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
60 #define GPIO_DOEN_X_REG 0x0
61 #define GPIO_DOUT_X_REG 0x40
63 #define GPIO_INPUT_ENABLE_X_REG 0x120
67 #define PROC_VIC "vic_gpio7110"
69 struct sfvic7110_gpio {
73 unsigned long enabled;
74 unsigned trigger[MAX_GPIO];
75 unsigned int irq_parent[MAX_GPIO];
76 struct sfvic7110_gpio *self_ptr[MAX_GPIO];
79 /* lock for procfs read access */
80 static DEFINE_MUTEX(read_lock);
82 /* lock for procfs write access */
83 static DEFINE_MUTEX(write_lock);
85 static DEFINE_SPINLOCK(sfg_lock);
87 static void __iomem *gpio_base = NULL;
89 static int sfvic7110_direction_input(struct gpio_chip *gc, unsigned offset)
91 struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
95 if (offset >= gc->ngpio)
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);
108 static int sfvic7110_direction_output(struct gpio_chip *gc, unsigned offset, int value)
110 struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
114 if (offset >= gc->ngpio)
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));
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);
131 static int sfvic7110_get_direction(struct gpio_chip *gc, unsigned offset)
133 struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
136 if (offset >= gc->ngpio)
139 v = readl_relaxed(chip->base + GPIO_DOEN_X_REG + (offset & ~0x3));
140 return !!(v & (0x3f << ((offset & 0x3) * 8)));
143 static int sfvic7110_get_value(struct gpio_chip *gc, unsigned offset)
145 struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
148 if (offset >= gc->ngpio)
152 value = readl_relaxed(chip->base + GPIO_DIN_LOW);
153 return (value >> offset) & 0x1;
155 value = readl_relaxed(chip->base + GPIO_DIN_HIGH);
156 return (value >> (offset - 32)) & 0x1;
160 static void sfvic7110_set_value(struct gpio_chip *gc, unsigned offset, int value)
162 struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
166 if (offset >= gc->ngpio)
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);
177 static void sfvic7110_set_ie(struct sfvic7110_gpio *chip, int offset)
180 int old_value, new_value;
181 int reg_offset, index;
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);
197 static int sfvic7110_irq_set_type(struct irq_data *d, unsigned trigger)
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;
205 if (offset < 0 || offset >= gc->ngpio)
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);
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);
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);
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);
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);
273 chip->trigger[offset] = trigger;
274 sfvic7110_set_ie(chip, offset);
278 /* chained_irq_{enter,exit} already mask the parent */
279 static void sfvic7110_irq_mask(struct irq_data *d)
281 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
282 struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
284 int offset = irqd_to_hwirq(d);
285 int reg_offset, index;
287 if (offset < 0 || offset >= gc->ngpio)
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);
303 static void sfvic7110_irq_unmask(struct irq_data *d)
305 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
306 struct sfvic7110_gpio *chip = gpiochip_get_data(gc);
308 int offset = irqd_to_hwirq(d);
309 int reg_offset, index;
311 if (offset < 0 || offset >= gc->ngpio)
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);
327 static void sfvic7110_irq_enable(struct irq_data *d)
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);
333 sfvic7110_irq_unmask(d);
334 assign_bit(offset, &chip->enabled, 1);
337 static void sfvic7110_irq_disable(struct irq_data *d)
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
343 assign_bit(offset, &chip->enabled, 0);
344 sfvic7110_set_ie(chip, offset);
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,
357 static int starfive_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
359 unsigned int child_type,
360 unsigned int *parent,
361 unsigned int *parent_type)
363 struct sfvic7110_gpio *chip;// = gpiochip_get_data(gc);
364 struct irq_data *d;// = irq_get_irq_data(chip->irq_parent[child]);
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);
375 static irqreturn_t sfvic7110_irq_handler(int irq, void *gc)
378 // = self_ptr - &chip->self_ptr[0];
379 int reg_offset, index;
382 struct sfvic7110_gpio *chip = gc;
384 for (offset = 0; offset < 64; offset++) {
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 +
399 //generic_handle_irq(irq_find_mapping(chip->gc.irq.domain,
401 raw_spin_unlock_irqrestore(&chip->lock, flags);
407 void sf_vic_gpio_dout_reverse(int gpio,int en)
415 offset = GPIO_DOUT_X_REG + (gpio & ~0x3);
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);
424 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_reverse);
426 void sf_vic_gpio_dout_value(int gpio,int v)
434 offset = GPIO_DOUT_X_REG + (gpio & ~0x3);
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);
443 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_value);
445 void sf_vic_gpio_dout_low(int gpio)
447 sf_vic_gpio_dout_value(gpio, 0);
449 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_low);
451 void sf_vic_gpio_dout_high(int gpio)
453 sf_vic_gpio_dout_value(gpio, 1);
455 EXPORT_SYMBOL_GPL(sf_vic_gpio_dout_high);
457 void sf_vic_gpio_doen_reverse(int gpio,int en)
465 offset = GPIO_DOEN_X_REG + (gpio & ~0x3);
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);
474 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_reverse);
476 void sf_vic_gpio_doen_value(int gpio,int v)
484 offset = GPIO_DOEN_X_REG + (gpio & ~0x3);
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);
493 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_value);
495 void sf_vic_gpio_doen_low(int gpio)
497 sf_vic_gpio_doen_value(gpio, 0);
499 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_low);
501 void sf_vic_gpio_doen_high(int gpio)
503 sf_vic_gpio_doen_value(gpio, 1);
505 EXPORT_SYMBOL_GPL(sf_vic_gpio_doen_high);
507 void sf_vic_gpio_manual(int offset,int v)
514 spin_lock(&sfg_lock);
515 value = ioread32(gpio_base + offset);
518 iowrite32(value,gpio_base + offset);
519 spin_unlock(&sfg_lock);
521 EXPORT_SYMBOL_GPL(sf_vic_gpio_manual);
523 static int str_to_num(char *str)
528 if((*p == '0') && (*(p + 1) == 'x' || *(p + 1) == 'X')) {
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');
542 while((*p >= '0') && (*p <= '9')) {
543 value = value * 10 + (*p - '0');
554 static ssize_t vic_gpio_proc_write(struct file *file, const char __user *buf,
555 size_t count, loff_t *ppos)
558 char message[64], cmd[8],gnum[8],v[8];
561 if (mutex_lock_interruptible(&write_lock))
564 ret = copy_from_user(message, buf, count);
565 mutex_unlock(&write_lock);
568 sscanf(message, "%s %s %s", cmd, gnum, v);
569 gpionum = str_to_num(gnum);
572 value = str_to_num(v);
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",
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",
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);
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);
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);
607 sf_vic_gpio_manual(gpionum, value);
609 printk(KERN_ERR "vic-gpio: cmd (dout doen utrv enrv manu) invalid: %s\n",cmd);
615 static ssize_t vic_gpio_proc_read(struct file *file, char __user *buf,
616 size_t count, loff_t *ppos)
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);
631 if (mutex_lock_interruptible(&read_lock))
634 ret = copy_to_user(buf, message, copied);
636 mutex_unlock(&read_lock);
640 mutex_unlock(&read_lock);
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,
652 static int sfvic7110_gpio_probe(struct platform_device *pdev)
654 struct device *dev = &pdev->dev;
655 struct sfvic7110_gpio *chip;
656 struct resource *res;
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;
664 chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
666 dev_err(dev, "out of memory\n");
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);
676 gpio_base = chip->base ;
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;
687 chip->gc.ngpio = ngpio;
688 chip->gc.label = dev_name(dev);
689 chip->gc.parent = dev;
690 chip->gc.owner = THIS_MODULE;
692 irq_parent = of_irq_find_parent(node);
694 dev_err(dev, "no IRQ parent node\n");
697 parent = irq_find_host(irq_parent);
699 dev_err(dev, "no IRQ parent domain\n");
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;
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);
716 platform_set_drvdata(pdev, chip);
718 ret = gpiochip_add_data(&chip->gc, chip);
720 dev_err(dev, "gpiochip_add_data ret=%d!\n", ret);
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);
730 ret = gpiochip_irqchip_add(&chip->gc, &sfvic7110_irqchip, 0,
731 handle_simple_irq, IRQ_TYPE_NONE);
733 dev_err(dev, "could not add irqchip\n");
734 gpiochip_remove(&chip->gc);
739 irq = platform_get_irq(pdev, 0);
741 dev_err(dev, "Cannot get IRQ resource\n");
745 chip->irq_parent[0] = irq;
747 ret = devm_request_irq(dev, irq, sfvic7110_irq_handler, IRQF_SHARED,
748 dev_name(dev), chip);
750 dev_err(dev, "IRQ handler registering failed (%d)\n", ret);
754 writel_relaxed(1, chip->base + GPIO_EN);
756 for(loop = 0; loop < MAX_GPIO; loop++) {
758 v = readl_relaxed(chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
760 writel_relaxed(v, chip->base + GPIO_INPUT_ENABLE_X_REG + (loop << 2));
763 if (proc_create(PROC_VIC, 0, NULL, (void *)&vic_gpio_fops) == NULL) {
766 dev_info(dev, "SiFive GPIO chip registered %d GPIOs\n", ngpio);
771 static const struct of_device_id sfvic7110_gpio_match[] = {
772 { .compatible = "starfive,gpio7110", },
776 static struct platform_driver sfvic7110_gpio_driver = {
777 .probe = sfvic7110_gpio_probe,
779 .name = "sfvic7110_gpio",
780 .of_match_table = of_match_ptr(sfvic7110_gpio_match),
784 static int __init sfvic7110_gpio_init(void)
786 return platform_driver_register(&sfvic7110_gpio_driver);
788 subsys_initcall(sfvic7110_gpio_init);
790 static void __exit sfvic7110_gpio_exit(void)
792 platform_driver_unregister(&sfvic7110_gpio_driver);
794 module_exit(sfvic7110_gpio_exit);
796 MODULE_LICENSE("GPL");
797 MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
798 MODULE_DESCRIPTION("Starfive VIC GPIO generator driver");