diff --git a/cpu/atmega1281/include/periph_cpu.h b/cpu/atmega1281/include/periph_cpu.h
index 1f503fdb073274ab8c7a95d9d64b01090b70c760..9f69d979e7e1ca5508d57bb7af193783f3b858ac 100644
--- a/cpu/atmega1281/include/periph_cpu.h
+++ b/cpu/atmega1281/include/periph_cpu.h
@@ -42,6 +42,20 @@ enum {
     PORT_G = 6,       /**< port G */
 };
 
+/**
+ * @brief   Available external interrupt pins on the ATmega1281 family
+ *
+ * In order of their interrupt number.
+ */
+#define CPU_ATMEGA_EXT_INTS    { GPIO_PIN(PORT_D, 0), \
+                                 GPIO_PIN(PORT_D, 1), \
+                                 GPIO_PIN(PORT_D, 2), \
+                                 GPIO_PIN(PORT_D, 3), \
+                                 GPIO_PIN(PORT_E, 4), \
+                                 GPIO_PIN(PORT_E, 5), \
+                                 GPIO_PIN(PORT_E, 6), \
+                                 GPIO_PIN(PORT_E, 7) }
+
 /**
  * @name   Defines for the I2C interface
  * @{
diff --git a/cpu/atmega1284p/include/periph_cpu.h b/cpu/atmega1284p/include/periph_cpu.h
index c7f43419125f5f3a0667829a5799573c6f5f3115..047dae07c172faf185130d13d489b26b9d81d49f 100644
--- a/cpu/atmega1284p/include/periph_cpu.h
+++ b/cpu/atmega1284p/include/periph_cpu.h
@@ -35,7 +35,7 @@ extern "C" {
 #define GPIO_PIN(x, y)          ((x << 4) | y)
 
 /**
- * @brief   Available ports on the ATmega328p family
+ * @brief   Available ports on the ATmega1284p family
  */
 enum {
     PORT_A = 0,       /**< port A */
@@ -44,6 +44,15 @@ enum {
     PORT_D = 3        /**< port D */
 };
 
+/**
+ * @brief   Available external interrupt pins on the ATmega1284p family
+ *
+ * In order of their interrupt number
+ */
+#define CPU_ATMEGA_EXT_INTS    { GPIO_PIN(PORT_D, 2), \
+                                 GPIO_PIN(PORT_D, 3), \
+                                 GPIO_PIN(PORT_B, 2) }
+
 /**
  * @name   Defines for the I2C interface
  * @{
diff --git a/cpu/atmega2560/include/periph_cpu.h b/cpu/atmega2560/include/periph_cpu.h
index 92fd8096860223a09d94c220b5013c531e2be5f4..10cd8acc1e1e66de3d5a1f47fcddbb982a62fa15 100644
--- a/cpu/atmega2560/include/periph_cpu.h
+++ b/cpu/atmega2560/include/periph_cpu.h
@@ -44,6 +44,20 @@ enum {
     PORT_L = 10       /**< port L */
 };
 
+/**
+ * @brief   Available external interrupt pins on the ATmega2560 family
+ *
+ * In order of their interrupt number.
+ */
+#define CPU_ATMEGA_EXT_INTS    { GPIO_PIN(PORT_D, 0), \
+                                 GPIO_PIN(PORT_D, 1), \
+                                 GPIO_PIN(PORT_D, 2), \
+                                 GPIO_PIN(PORT_D, 3), \
+                                 GPIO_PIN(PORT_E, 4), \
+                                 GPIO_PIN(PORT_E, 5), \
+                                 GPIO_PIN(PORT_E, 6), \
+                                 GPIO_PIN(PORT_E, 7) }
+
 /**
  * @name   Defines for the I2C interface
  * @{
diff --git a/cpu/atmega256rfr2/include/periph_cpu.h b/cpu/atmega256rfr2/include/periph_cpu.h
index 731149bb5a0a62f67b8554aa505932036ee98ee0..03562a2402d5d35b39d3357b1c0f982aa43687f1 100644
--- a/cpu/atmega256rfr2/include/periph_cpu.h
+++ b/cpu/atmega256rfr2/include/periph_cpu.h
@@ -46,6 +46,20 @@ enum {
     PORT_G  = 6,        /**< port G */
 };
 
+/**
+ * @brief   Available external interrupt pins on the ATmega256rfr family
+ *
+ * In order of their interrupt number.
+ */
+#define CPU_ATMEGA_EXT_INTS    { GPIO_PIN(PORT_D, 0), \
+                                 GPIO_PIN(PORT_D, 1), \
+                                 GPIO_PIN(PORT_D, 2), \
+                                 GPIO_PIN(PORT_D, 3), \
+                                 GPIO_PIN(PORT_E, 4), \
+                                 GPIO_PIN(PORT_E, 5), \
+                                 GPIO_PIN(PORT_E, 6), \
+                                 GPIO_PIN(PORT_E, 7) }
+
 /**
  * @name   Defines for the I2C interface
  * @{
diff --git a/cpu/atmega328p/include/periph_cpu.h b/cpu/atmega328p/include/periph_cpu.h
index 5e29096ad46bd848970b15a96355214f9859c455..03ab92365fd9c6e1d5893a2f682e8d688df300ce 100644
--- a/cpu/atmega328p/include/periph_cpu.h
+++ b/cpu/atmega328p/include/periph_cpu.h
@@ -41,6 +41,14 @@ enum {
     PORT_D = 3        /**< port D */
 };
 
+/**
+ * @brief   Available external interrupt pins on the ATmega328p family
+ *
+ * In order of their interrupt number.
+ */
+#define CPU_ATMEGA_EXT_INTS    { GPIO_PIN(PORT_D, 2), \
+                                 GPIO_PIN(PORT_D, 3) }
+
 /**
  * @name   Defines for the I2C interface
  * @{
diff --git a/cpu/atmega_common/periph/gpio.c b/cpu/atmega_common/periph/gpio.c
index 5e0bced64e70c3deb3913986a3219a75345a66e5..233ae29509734d931a9b9aad8902d8a8ab724818 100644
--- a/cpu/atmega_common/periph/gpio.c
+++ b/cpu/atmega_common/periph/gpio.c
@@ -30,6 +30,7 @@
 #include "cpu.h"
 #include "periph/gpio.h"
 #include "periph_conf.h"
+#include "periph_cpu.h"
 
 #define GPIO_BASE_PORT_A        (0x20)
 #define GPIO_OFFSET_PORT_H      (0xCB)
@@ -40,18 +41,18 @@
  * @brief     Define GPIO interruptions for an specific atmega CPU, by default
  *            2 (for small atmega CPUs)
  */
-#if defined(INT2_vect)
-#define GPIO_EXT_INT_NUMOF      (3U)
-#elif defined(INT3_vect)
-#define GPIO_EXT_INT_NUMOF      (4U)
-#elif defined(INT4_vect)
-#define GPIO_EXT_INT_NUMOF      (4U)
-#elif defined(INT5_vect)
-#define GPIO_EXT_INT_NUMOF      (4U)
+#if defined(INT7_vect)
+#define GPIO_EXT_INT_NUMOF      (8U)
 #elif defined(INT6_vect)
+#define GPIO_EXT_INT_NUMOF      (7U)
+#elif defined(INT5_vect)
+#define GPIO_EXT_INT_NUMOF      (6U)
+#elif defined(INT4_vect)
+#define GPIO_EXT_INT_NUMOF      (5U)
+#elif defined(INT3_vect)
 #define GPIO_EXT_INT_NUMOF      (4U)
-#elif defined(INT7_vect)
-#define GPIO_EXT_INT_NUMOF      (4U)
+#elif defined(INT2_vect)
+#define GPIO_EXT_INT_NUMOF      (3U)
 #else
 #define GPIO_EXT_INT_NUMOF      (2U)
 #endif
@@ -109,6 +110,21 @@ static inline uint16_t _pin_addr(gpio_t pin)
     return (_port_addr(pin) - 0x02);
 }
 
+static inline int8_t _int_num(gpio_t pin)
+{
+    uint8_t num;
+    const gpio_t ext_ints[GPIO_EXT_INT_NUMOF] = CPU_ATMEGA_EXT_INTS;
+
+    /* find pin in ext_ints array to get the interrupt number */
+    for (num = 0; num < GPIO_EXT_INT_NUMOF; num++) {
+        if (pin == ext_ints[num]) {
+            return num;
+        }
+    }
+
+    return -1;
+}
+
 int gpio_init(gpio_t pin, gpio_mode_t mode)
 {
     switch (mode) {
@@ -132,20 +148,14 @@ int gpio_init(gpio_t pin, gpio_mode_t mode)
 int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
                   gpio_cb_t cb, void *arg)
 {
-    uint8_t pin_num = _pin_num(pin);
-
-    if ((_port_num(pin) == PORT_D && pin_num > 3)
-#if defined (PORTE)
-         || (_port_num(pin) == PORT_E && pin_num < 4)
-         || (_port_num(pin) != PORT_D && _port_num(pin) != PORT_E)
-#elif defined(CPU_ATMEGA328P)
-         || (pin_num < 2) || (_port_num(pin) != PORT_D)
-#elif defined(CPU_ATMEGA1284P)
-         || (_port_num(pin) == PORT_B && pin_num != 2)
-         || (_port_num(pin) == PORT_D && pin_num < 2)
-         || (_port_num(pin) != PORT_D && _port_num(pin) != PORT_D)
-#endif
-         || ((mode != GPIO_IN) && (mode != GPIO_IN_PU))) {
+    int8_t int_num = _int_num(pin);
+
+    if ((mode != GPIO_IN) && (mode != GPIO_IN_PU)) {
+        return -1;
+    }
+
+    /* not a valid interrupt pin */
+    if (int_num < 0) {
         return -1;
     }
 
@@ -154,35 +164,27 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
     /* clear global interrupt flag */
     cli();
 
-#if defined(CPU_ATMEGA328P)
-    /* INT pins start at PD2 instead of at PD0 */
-    pin_num -= 2;
-#elif defined(CPU_ATMEGA1284P)
-    /* INT pins start at PD2 instead of at PD0 on PORT_D */
-    if (_port_num(pin) == PORT_D) {
-        pin_num -= 2;
-    }
-#endif
-
-    EIMSK |= (1 << pin_num);
+    /* enable interrupt number int_num */
+    EIMSK |= (1 << int_num);
 
     /* configure the flank */
     if (flank > GPIO_RISING) {
         return -1;
     }
 
-    if (pin_num < 4) {
-        EICRA |= (flank << (pin_num * 2));
+    /* apply flank to interrupt number int_num */
+    if (int_num < 4) {
+        EICRA |= (flank << (int_num * 2));
     }
 #if defined(EICRB)
     else {
-        EICRB |= (flank << (pin_num * 2) % 4);
+        EICRB |= (flank << ((int_num % 4) * 2));
     }
 #endif
 
     /* set callback */
-    config[pin_num].cb = cb;
-    config[pin_num].arg = arg;
+    config[int_num].cb = cb;
+    config[int_num].arg = arg;
 
     /* set global interrupt flag */
     sei();
@@ -192,38 +194,12 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
 
 void gpio_irq_enable(gpio_t pin)
 {
-#if defined(CPU_ATMEGA328P)
-    /* INT pins start at PD2 instead of at PD0 */
-    EIMSK |= (1 << (_pin_num(pin) - 2));
-#elif defined(CPU_ATMEGA1284P)
-    /* INT pins start at PD2 instead of at PD0 on PORT_D */
-    if (_port_num(pin) == PORT_D) {
-        EIMSK |= (1 << (_pin_num(pin) - 2));
-    }
-    else {
-        EIMSK |= (1 << _pin_num(pin));
-    }
-#else
-    EIMSK |= (1 << _pin_num(pin));
-#endif
+    EIMSK |= (1 << _int_num(pin));
 }
 
 void gpio_irq_disable(gpio_t pin)
 {
-#if defined(CPU_ATMEGA328P)
-    /* INT pins start at PD2 instead of at PD0 */
-    EIMSK &= ~(1 << (_pin_num(pin) - 2));
-#elif defined (CPU_ATMEGA1284P)
-    /* INT pins start at PD2 instead of at PD0 on PORT_D */
-    if (_port_num(pin) == PORT_D) {
-        EIMSK &= ~(1 << (_pin_num(pin) - 2));
-    }
-    else {
-        EIMSK &= ~(1 << _pin_num(pin));
-    }
-#else
-    EIMSK &= ~(1 << _pin_num(pin));
-#endif
+    EIMSK &= ~(1 << _int_num(pin));
 }
 
 int gpio_read(gpio_t pin)
@@ -261,10 +237,10 @@ void gpio_write(gpio_t pin, int value)
     }
 }
 
-static inline void irq_handler(uint8_t pin_num)
+static inline void irq_handler(uint8_t int_num)
 {
     __enter_isr();
-    config[pin_num].cb(config[pin_num].arg);
+    config[int_num].cb(config[int_num].arg);
     __exit_isr();
 }