diff --git a/patches/spec.diff b/patches/spec.diff
index 197c0e761056f4e0f1635bef3402c100670be5df..be3ca4f4a16dec68c8b4839e3849f7ab6d6b70cd 100644
--- a/patches/spec.diff
+++ b/patches/spec.diff
@@ -23,10 +23,18 @@ index 50cda24..585eda1 100644
  #include <linux/fpga/fpga-mgr.h>
  #include <linux/delay.h>
 diff --git a/software/kernel/gn412x-gpio.c b/software/kernel/gn412x-gpio.c
-index c5ca4e5..468d1a4 100644
+index fa7003c..5882b1e 100644
 --- a/software/kernel/gn412x-gpio.c
 +++ b/software/kernel/gn412x-gpio.c
-@@ -77,12 +77,18 @@ static int gn412x_dbg_init(struct gn412x_gpio_dev *gn412x)
+@@ -19,6 +19,7 @@
+ struct gn412x_gpio_dev {
+ 	void __iomem *mem;
+ 	struct gpio_chip gpiochip;
++	struct irq_chip irqchip;
+ 
+ 	struct completion	compl;
+ 	struct gn412x_platform_data *pdata;
+@@ -77,12 +78,18 @@ static int gn412x_dbg_init(struct gn412x_gpio_dev *gn412x)
  	struct dentry *dir, *file;
  	int err;
  
@@ -48,7 +56,7 @@ index c5ca4e5..468d1a4 100644
  		goto err_dir;
  	}
  
-@@ -93,7 +99,7 @@ static int gn412x_dbg_init(struct gn412x_gpio_dev *gn412x)
+@@ -93,7 +100,7 @@ static int gn412x_dbg_init(struct gn412x_gpio_dev *gn412x)
  				       dir, &gn412x->dbg_reg32);
  	if (IS_ERR_OR_NULL(file)) {
  		err = PTR_ERR(file);
@@ -57,7 +65,7 @@ index c5ca4e5..468d1a4 100644
  			 "Cannot create debugfs file \"%s\" (%d)\n",
  			 GN412X_DBG_REG_NAME, err);
  		goto err_reg32;
-@@ -183,9 +189,15 @@ static int gn412x_gpio_request(struct gpio_chip *chip, unsigned int offset)
+@@ -183,9 +190,15 @@ static int gn412x_gpio_request(struct gpio_chip *chip, unsigned int offset)
  {
  	int val;
  
@@ -74,7 +82,7 @@ index c5ca4e5..468d1a4 100644
  			chip->label, offset);
  		return -EBUSY;
  	}
-@@ -264,13 +276,19 @@ static int gn412x_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
+@@ -264,13 +277,19 @@ static int gn412x_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
  {
  	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
  
@@ -95,7 +103,24 @@ index c5ca4e5..468d1a4 100644
  			"Impossible to set GPIO IRQ %ld to both LEVEL and EDGE (0x%x)\n",
  			d->hwirq, flow_type);
  		return -EINVAL;
-@@ -381,6 +399,12 @@ static irqreturn_t gn412x_gpio_irq_handler_t(int irq, void *arg)
+@@ -342,16 +361,6 @@ static void gn412x_gpio_irq_ack(struct irq_data *d)
+ 	 */
+ }
+ 
+-static struct irq_chip gn412x_gpio_irq_chip = {
+-	.name = "GN412X-GPIO",
+-	.irq_startup = gn412x_gpio_irq_startup,
+-	.irq_disable = gn412x_gpio_irq_disable,
+-	.irq_mask = gn412x_gpio_irq_mask,
+-	.irq_unmask = gn412x_gpio_irq_unmask,
+-	.irq_set_type = gn412x_gpio_irq_set_type,
+-	.irq_ack = gn412x_gpio_irq_ack,
+-};
+-
+ /**
+  * This will run in hard-IRQ context since we do not have much to do
+  */
+@@ -381,6 +390,12 @@ static irqreturn_t gn412x_gpio_irq_handler_t(int irq, void *arg)
  	irqreturn_t ret = IRQ_NONE;
  	int i;
  
@@ -108,7 +133,7 @@ index c5ca4e5..468d1a4 100644
  	gpio_int_status = gn412x_ioread32(gn412x, GNGPIO_INT_STATUS);
  	gpio_int_status &= ~gn412x_ioread32(gn412x, GNGPIO_INT_MASK);
  	if (!gpio_int_status)
-@@ -388,8 +412,12 @@ static irqreturn_t gn412x_gpio_irq_handler_t(int irq, void *arg)
+@@ -388,8 +403,12 @@ static irqreturn_t gn412x_gpio_irq_handler_t(int irq, void *arg)
  
  	loop = gpio_int_status;
  	for_each_set_bit(i, &loop, GN4124_GPIO_MAX) {
@@ -122,7 +147,7 @@ index c5ca4e5..468d1a4 100644
  		/*
  		 * Ok, now we execute the handler for the given IRQ. Please
  		 * note that this is not the action requested by the device
-@@ -457,7 +485,11 @@ static void gn412x_gpio_irq_set_nested_thread(struct gn412x_gpio_dev *gn412x,
+@@ -457,7 +476,11 @@ static void gn412x_gpio_irq_set_nested_thread(struct gn412x_gpio_dev *gn412x,
  {
  	int irq;
  
@@ -134,10 +159,21 @@ index c5ca4e5..468d1a4 100644
  	irq_set_nested_thread(irq, nest);
  }
  
-@@ -500,7 +532,11 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
+@@ -500,7 +523,22 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
  	}
  	gn412x_iowrite32(gn412x, 0, GNGPIO_BYPASS_MODE);
  
++	gn412x_gpio_int_cfg_disable(gn412x);
++	gn412x_iowrite32(gn412x, 0xFFFF, GNGPIO_INT_MASK_SET);
++
++	gn412x->irqchip.name = "GN412X-GPIO",
++	gn412x->irqchip.irq_startup = gn412x_gpio_irq_startup,
++	gn412x->irqchip.irq_disable = gn412x_gpio_irq_disable,
++	gn412x->irqchip.irq_mask = gn412x_gpio_irq_mask,
++	gn412x->irqchip.irq_unmask = gn412x_gpio_irq_unmask,
++	gn412x->irqchip.irq_set_type = gn412x_gpio_irq_set_type,
++	gn412x->irqchip.irq_ack = gn412x_gpio_irq_ack,
++
 +#if KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE
  	gn412x->gpiochip.dev = &pdev->dev;
 +#else
@@ -146,7 +182,33 @@ index c5ca4e5..468d1a4 100644
  	gn412x->gpiochip.label = "gn412x-gpio";
  	gn412x->gpiochip.owner = THIS_MODULE;
  	gn412x->gpiochip.request = gn412x_gpio_request;
-@@ -529,6 +565,7 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
+@@ -513,22 +551,29 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
+ 	gn412x->gpiochip.base = -1;
+ 	gn412x->gpiochip.ngpio = GN4124_GPIO_MAX;
+ 	gn412x->gpiochip.can_sleep = 0;
+-
++#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
++	gn412x->gpiochip.irq.chip = &gn412x->irqchip;
++	gn412x->gpiochip.irq.first = 0;
++	gn412x->gpiochip.irq.handler = handle_simple_irq;
++	gn412x->gpiochip.irq.default_type = IRQ_TYPE_NONE;
++	gn412x->gpiochip.irq.threaded = true;
++#endif
+ 	err = gpiochip_add(&gn412x->gpiochip);
+ 	if (err)
+ 		goto err_add;
+ 
+-	gn412x_gpio_int_cfg_disable(gn412x);
+-	gn412x_iowrite32(gn412x, 0xFFFF, GNGPIO_INT_MASK_SET);
++#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
+ 	err = gpiochip_irqchip_add(&gn412x->gpiochip,
+-				   &gn412x_gpio_irq_chip,
++				   &gn412x->irqchip,
+ 				   0, handle_simple_irq,
+ 				   IRQ_TYPE_NONE);
+ 	if (err)
+ 		goto err_add_irq;
++#endif
  
  	gn412x_gpio_irq_set_nested_thread_all(gn412x, true);
  
@@ -154,7 +216,7 @@ index c5ca4e5..468d1a4 100644
  	err = request_threaded_irq(platform_get_irq(pdev, 0),
  				   gn412x_gpio_irq_handler_h,
  				   gn412x_gpio_irq_handler_t,
-@@ -537,6 +574,16 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
+@@ -537,6 +582,16 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
  				   gn412x);
  	if (err) {
  		dev_err(gn412x->gpiochip.dev, "Can't request IRQ %d (%d)\n",
@@ -171,8 +233,72 @@ index c5ca4e5..468d1a4 100644
  			platform_get_irq(pdev, 0), err);
  		goto err_req;
  	}
+@@ -549,8 +604,10 @@ static int gn412x_gpio_probe(struct platform_device *pdev)
+ 
+ err_req:
+ 	gn412x_gpio_irq_set_nested_thread_all(gn412x, false);
++#if KERNEL_VERSION(4, 15, 0) > LINUX_VERSION_CODE
+ err_add_irq:
+ 	gpiochip_remove(&gn412x->gpiochip);
++#endif
+ err_add:
+ 	iounmap(gn412x->mem);
+ err_map:
+diff --git a/software/kernel/spec-core-fpga.c b/software/kernel/spec-core-fpga.c
+index 4c339a3..d8bf776 100644
+--- a/software/kernel/spec-core-fpga.c
++++ b/software/kernel/spec-core-fpga.c
+@@ -200,6 +200,21 @@ static struct resource spec_fpga_vic_res[] = {
+ 	},
+ };
+ 
++struct irq_domain *spec_fpga_irq_find_host(struct device *dev)
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,7,0)
++	struct irq_fwspec fwspec = {
++		.fwnode = dev->fwnode,
++		.param_count = 2,
++		.param[0] = ((unsigned long)dev >> 32) & 0xffffffff,
++		.param[1] = ((unsigned long)dev) & 0xffffffff,
++	};
++	return irq_find_matching_fwspec(&fwspec, DOMAIN_BUS_ANY);
++#else
++	return (irq_find_host((void *)dev));
++#endif
++}
++
+ /* Vector Interrupt Controller */
+ static int spec_fpga_vic_init(struct spec_fpga *spec_fpga)
+ {
+@@ -274,7 +289,7 @@ static int spec_fpga_dma_init(struct spec_fpga *spec_fpga)
+ 			ddr_status);
+ 		return -ENODEV;
+ 	}
+-	vic_domain = irq_find_host((void *)&spec_fpga->vic_pdev->dev);
++	vic_domain = spec_fpga_irq_find_host(&spec_fpga->vic_pdev->dev);
+ 	if (!vic_domain) {
+ 		dev_err(&spec_fpga->dev,
+ 			"Failed to load DMA engine: can't find VIC\n");
+@@ -429,7 +444,7 @@ static int spec_fpga_devices_init(struct spec_fpga *spec_fpga)
+ 		n_mfd++;
+ 	}
+ 
+-	vic_domain = irq_find_host((void *)&spec_fpga->vic_pdev->dev);
++	vic_domain = spec_fpga_irq_find_host(&spec_fpga->vic_pdev->dev);
+ 	if (!vic_domain) {
+ 		/* Remove IRQ resource from all devices */
+ 		fpga_mfd_devs[0].num_resources = 1;  /* FMC I2C */
+@@ -736,7 +751,7 @@ static int spec_fpga_app_init(struct spec_fpga *spec_fpga)
+ 	res[0].end = pci_resource_end(pcidev, 0);
+ 
+ 	if (spec_fpga->vic_pdev)
+-		vic_domain = irq_find_host((void *)&spec_fpga->vic_pdev->dev);
++		vic_domain = spec_fpga_irq_find_host(&spec_fpga->vic_pdev->dev);
+ 	else
+ 		vic_domain = NULL;
+ 
 diff --git a/software/kernel/spec-core.c b/software/kernel/spec-core.c
-index 174efb8..b1f20f8 100644
+index c338c19..eeef8cd 100644
 --- a/software/kernel/spec-core.c
 +++ b/software/kernel/spec-core.c
 @@ -15,6 +15,10 @@
@@ -187,7 +313,7 @@ index 174efb8..b1f20f8 100644
  #include "platform_data/gn412x-gpio.h"
  #include "spec.h"
 diff --git a/software/kernel/spec-gn412x-dma.c b/software/kernel/spec-gn412x-dma.c
-index a861737..e87934f 100644
+index a861737..98643a4 100644
 --- a/software/kernel/spec-gn412x-dma.c
 +++ b/software/kernel/spec-gn412x-dma.c
 @@ -20,6 +20,8 @@
@@ -222,13 +348,19 @@ index a861737..e87934f 100644
  
  static irqreturn_t gn412x_dma_irq_handler(int irq, void *arg)
  {
-@@ -742,7 +746,12 @@ static int gn412x_dma_engine_init(struct gn412x_dma_device *gn412x_dma,
+@@ -742,7 +746,18 @@ static int gn412x_dma_engine_init(struct gn412x_dma_device *gn412x_dma,
  	dma->device_alloc_chan_resources = gn412x_dma_alloc_chan_resources;
  	dma->device_free_chan_resources = gn412x_dma_free_chan_resources;
  	dma->device_prep_slave_sg = gn412x_dma_prep_slave_sg;
 +#if KERNEL_VERSION(4, 0, 0) > LINUX_VERSION_CODE
  	dma->device_control = gn412x_dma_device_control;
 +#else
++	dma->src_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES;
++	dma->dst_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES;
++	dma->directions =
++		1 << DMA_DEV_TO_MEM |
++		1 << DMA_MEM_TO_DEV;
++	dma->residue_granularity = 0;
 +	dma->device_config = gn412x_dma_slave_config;
 +	dma->device_terminate_all = gn412x_dma_terminate_all;
 +#endif