diff --git a/cores/arduino/PMIC.cpp b/cores/arduino/PMIC.cpp
new file mode 100644
index 000000000..3ca46a9ab
--- /dev/null
+++ b/cores/arduino/PMIC.cpp
@@ -0,0 +1,79 @@
+/*
+  PMIC.cpp - initialization of Power Management ICs
+  Copyright (c) 2020 Kevin P. Fleming.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "Arduino.h"
+
+#ifdef USE_BQ24195L_PMIC
+
+#include "PMIC/BQ24195.h"
+
+#include "wiring_private.h"
+
+void setupPMIC(SERCOM& sercom, bool batteryPresent, bool USBDetect) {
+  BQ24195_REG00 reg00;
+  reg00.IINLIM = 0b110; // input current limit 2A
+  reg00.VINDPM = 0b0000; // input voltage limit 3.88V
+  reg00.EN_HIZ = 0b0; // disable
+
+  sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG);
+  sercom.sendDataMasterWIRE(BQ24195_REG00_ADDRESS);
+  sercom.sendDataMasterWIRE(reg00.val);
+  sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+
+  BQ24195_REG01 reg01;
+  reg01.RSVD = 0b1;
+  reg01.SYS_MIN = 0b101; // minimum system voltage 3.5V
+  reg01.CHG_CONFIG_ENABLE = (batteryPresent ? 0b1 : 0b0); // battery charge enable/disable
+  reg01.CHG_CONFIG_OTG = 0b0;
+  reg01.WATCHDOG_TIMER_RESET = 0b1; // reset watchdog timer
+  reg01.REGISTER_RESET = 0b0; // keep current register setting
+
+  sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG);
+  sercom.sendDataMasterWIRE(BQ24195_REG01_ADDRESS);
+  sercom.sendDataMasterWIRE(reg01.val);
+  sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+
+  BQ24195_REG05 reg05;
+  reg05.RSVD = 0b0;
+  reg05.CHG_TIMER = 0b01; // fast charge timer 8 hours
+  reg05.EN_TIMER = (batteryPresent ? 0b1 : 0b0); // enable/disable charge safety timer
+  reg05.WATCHDOG = 0b00; // disable watchdog timer to stay in host mode
+  reg05.TERM_STAT = 0b0; // charge termination indicator match ITERM
+  reg05.EN_TERM = 0b1; // enable charge termination
+
+  sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG);
+  sercom.sendDataMasterWIRE(BQ24195_REG05_ADDRESS);
+  sercom.sendDataMasterWIRE(reg05.val);
+  sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+
+  BQ24195_REG07 reg07;
+  reg07.INT_MASK_BAT = 0b1; // INT on battery fault
+  reg07.INT_MASK_CHG = 0b1; // INT on charge fault
+  reg07.RSVD = 0b010;
+  reg07.BATFET_DISABLE = (batteryPresent ? 0b0 : 0b1); // battery FET enable/disable
+  reg07.TMR2X_EN = 0b0; // safety timer not slowed by 2X
+  reg07.DPDM_EN = (USBDetect ? 0b1 : 0b0); // D+/D- detection enable/disable
+
+  sercom.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG);
+  sercom.sendDataMasterWIRE(BQ24195_REG07_ADDRESS);
+  sercom.sendDataMasterWIRE(reg07.val);
+  sercom.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+}
+
+#endif
diff --git a/cores/arduino/PMIC.h b/cores/arduino/PMIC.h
new file mode 100644
index 000000000..c859c0f01
--- /dev/null
+++ b/cores/arduino/PMIC.h
@@ -0,0 +1,24 @@
+/*
+  PMIC.h - initialization of Power Management ICs
+  Copyright (c) 2020 Kevin P. Fleming.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#pragma once
+
+#include "Arduino.h"
+
+extern void setupPMIC(SERCOM& sercom, bool batteryPresent, bool USBDetect);
diff --git a/cores/arduino/PMIC/BQ24195.h b/cores/arduino/PMIC/BQ24195.h
new file mode 100644
index 000000000..f36e5e395
--- /dev/null
+++ b/cores/arduino/PMIC/BQ24195.h
@@ -0,0 +1,178 @@
+/*
+  BQ24195.h - Register definitions for BQ24195/BQ24195L PMICs.
+  Copyright (c) 2020 Kevin P. Fleming.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef union {
+  struct {
+    uint8_t IINLIM:3;
+    uint8_t VINDPM:4;
+    uint8_t EN_HIZ:1;
+  };
+  uint8_t val;
+} BQ24195_REG00;
+
+static_assert(sizeof(BQ24195_REG00) == 1, "BQ24195_REG00 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t RSVD:1;
+    uint8_t SYS_MIN:3;
+    uint8_t CHG_CONFIG_ENABLE:1;
+    uint8_t CHG_CONFIG_OTG:1;
+    uint8_t WATCHDOG_TIMER_RESET:1;
+    uint8_t REGISTER_RESET:1;
+  };
+  uint8_t val;
+} BQ24195_REG01;
+
+static_assert(sizeof(BQ24195_REG01) == 1, "BQ24195_REG01 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t FORCE_20PCT:1;
+    uint8_t RSVD:1;
+    uint8_t ICHG:6;
+  };
+  uint8_t val;
+} BQ24195_REG02;
+
+static_assert(sizeof(BQ24195_REG02) == 1, "BQ24195_REG02 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t ITERM:4;
+    uint8_t IPRECHG:4;
+  };
+  uint8_t val;
+} BQ24195_REG03;
+
+static_assert(sizeof(BQ24195_REG03) == 1, "BQ24195_REG03 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t VRECHG:1;
+    uint8_t BATLOWV:1;
+    uint8_t VREG:6;
+  };
+  uint8_t val;
+} BQ24195_REG04;
+
+static_assert(sizeof(BQ24195_REG04) == 1, "BQ24195_REG04 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t RSVD:1;
+    uint8_t CHG_TIMER:2;
+    uint8_t EN_TIMER:1;
+    uint8_t WATCHDOG:2;
+    uint8_t TERM_STAT:1;
+    uint8_t EN_TERM:1;
+  };
+  uint8_t val;
+} BQ24195_REG05;
+
+static_assert(sizeof(BQ24195_REG05) == 1, "BQ24195_REG05 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t VRECHG:1;
+    uint8_t BATLOWV:1;
+    uint8_t VREG:6;
+  };
+  uint8_t val;
+} BQ24195_REG06;
+
+static_assert(sizeof(BQ24195_REG06) == 1, "BQ24195_REG06 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t INT_MASK_BAT:1;
+    uint8_t INT_MASK_CHG:1;
+    uint8_t RSVD:3;
+    uint8_t BATFET_DISABLE:1;
+    uint8_t TMR2X_EN:1;
+    uint8_t DPDM_EN:1;
+  };
+  uint8_t val;
+} BQ24195_REG07;
+
+static_assert(sizeof(BQ24195_REG07) == 1, "BQ24195_REG07 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t VSYS_STAT:1;
+    uint8_t THERM_STAT:1;
+    uint8_t PG_STAT:1;
+    uint8_t DPM_STAT:1;
+    uint8_t CHRG_STAT:2;
+    uint8_t VBUS_STAT:2;
+  };
+  uint8_t val;
+} BQ24195_REG08;
+
+static_assert(sizeof(BQ24195_REG08) == 1, "BQ24195_REG08 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t NTC_FAULT:3;
+    uint8_t BAT_FAULT:1;
+    uint8_t CHRG_FAULT:2;
+    uint8_t RSVD:1;
+    uint8_t WATCHDOG_FAULT:1;
+  };
+  uint8_t val;
+} BQ24195_REG09;
+
+static_assert(sizeof(BQ24195_REG09) == 1, "BQ24195_REG09 union size is incorrect, should be 1 byte.");
+
+typedef union {
+  struct {
+    uint8_t DEV_REG:2;
+    uint8_t TS_PROFILE:1;
+    uint8_t PN:3;
+    uint8_t RSVD:2;
+  };
+  uint8_t val;
+} BQ24195_REG0A;
+
+static_assert(sizeof(BQ24195_REG0A) == 1, "BQ24195_REG0A union size is incorrect, should be 1 byte.");
+
+#define BQ24195_ADDRESS		0x6B
+#define BQ24195_REG00_ADDRESS	0x00
+#define BQ24195_REG01_ADDRESS	0x01
+#define BQ24195_REG02_ADDRESS	0x02
+#define BQ24195_REG03_ADDRESS	0x03
+#define BQ24195_REG04_ADDRESS	0x04
+#define BQ24195_REG05_ADDRESS	0x05
+#define BQ24195_REG06_ADDRESS	0x06
+#define BQ24195_REG07_ADDRESS	0x07
+#define BQ24195_REG08_ADDRESS	0x08
+#define BQ24195_REG09_ADDRESS	0x09
+#define BQ24195_REG0A_ADDRESS	0x0A
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/variants/mkrgsm1400/variant.cpp b/variants/mkrgsm1400/variant.cpp
index 2b25934b2..d3ca1fd31 100644
--- a/variants/mkrgsm1400/variant.cpp
+++ b/variants/mkrgsm1400/variant.cpp
@@ -177,76 +177,28 @@ SERCOM sercom3(SERCOM3);
 SERCOM sercom4(SERCOM4);
 SERCOM sercom5(SERCOM5);
 
-#if defined(USE_BQ24195L_PMIC)
-
+#ifdef USE_BQ24195L_PMIC
+#include "PMIC.h"
 #include "wiring_private.h"
-
-#define PMIC_ADDRESS  0x6B
-#define PMIC_REG01    0x01
-#define PMIC_REG07    0x07
-
-#define PMIC_REG00    0x00
-
-static inline void set_voltage_current_thresholds() {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG00);
-  PERIPH_WIRE.sendDataMasterWIRE(0x07);  // input voltage limit = 3.88V, input current limit = 3A
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
-static inline void enable_battery_charging() {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01);
-  PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
-static inline void disable_battery_fet(bool disabled) {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG07);
-  // No D+/D– detection + Safety timer not slowed by 2X during input DPM or thermal regulation +
-  // BAT fet disabled/enabled + charge and bat fault INT
-  PERIPH_WIRE.sendDataMasterWIRE(0x0B | (disabled ? 0x20 : 0x00));
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
 #endif
 
 void initVariant() {
-#if defined(USE_BQ24195L_PMIC)
+#ifdef USE_BQ24195L_PMIC
   pinMode(ADC_BATTERY, OUTPUT);
   digitalWrite(ADC_BATTERY, LOW);
   delay(10);
   pinMode(ADC_BATTERY, INPUT);
   delay(100);
 
+  PERIPH_WIRE.initMasterWIRE(100000);
+  PERIPH_WIRE.enableWIRE();
+  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
+  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
+
   bool batteryPresent = analogRead(ADC_BATTERY) > 600;
-  if (batteryPresent) {
-    enable_battery_charging();
-  }
-  disable_battery_fet(!batteryPresent);
-  set_voltage_current_thresholds();
+  setupPMIC(PERIPH_WIRE, batteryPresent, true);
+
+  PERIPH_WIRE.disableWIRE();
 #endif
 
   // put GSM modem in reset on start to conserve power if it's not used
diff --git a/variants/mkrnb1500/variant.cpp b/variants/mkrnb1500/variant.cpp
index 5e61669e5..45a73d4e1 100644
--- a/variants/mkrnb1500/variant.cpp
+++ b/variants/mkrnb1500/variant.cpp
@@ -177,75 +177,28 @@ SERCOM sercom3(SERCOM3);
 SERCOM sercom4(SERCOM4);
 SERCOM sercom5(SERCOM5);
 
-#if defined(USE_BQ24195L_PMIC)
-
+#ifdef USE_BQ24195L_PMIC
+#include "PMIC.h"
 #include "wiring_private.h"
-
-#define PMIC_ADDRESS  0x6B
-#define PMIC_REG00    0x00
-#define PMIC_REG01    0x01
-#define PMIC_REG07    0x07
-
-static inline void enable_battery_charging() {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01);
-  PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
-static inline void set_voltage_current_thresholds() {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG00);
-  PERIPH_WIRE.sendDataMasterWIRE(0x06); // 3.880 V + 2A ILIM
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
-static inline void disable_battery_fet(bool disabled) {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG07);
-  // No D+/D– detection + Safety timer not slowed by 2X during input DPM or thermal regulation +
-  // BAT fet disabled/enabled + charge and bat fault INT
-  PERIPH_WIRE.sendDataMasterWIRE(0x0B | (disabled ? 0x20 : 0x00));
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
 #endif
 
 void initVariant() {
-#if defined(USE_BQ24195L_PMIC)
+#ifdef USE_BQ24195L_PMIC
   pinMode(ADC_BATTERY, OUTPUT);
   digitalWrite(ADC_BATTERY, LOW);
   delay(10);
   pinMode(ADC_BATTERY, INPUT);
   delay(100);
 
+  PERIPH_WIRE.initMasterWIRE(100000);
+  PERIPH_WIRE.enableWIRE();
+  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
+  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
+
   bool batteryPresent = analogRead(ADC_BATTERY) > 600;
-  if (batteryPresent) {
-    enable_battery_charging();
-  }
-  disable_battery_fet(!batteryPresent);
-  set_voltage_current_thresholds();
+  setupPMIC(PERIPH_WIRE, batteryPresent, false);
+
+  PERIPH_WIRE.disableWIRE();
 #endif
 
   // power off the module
diff --git a/variants/mkrvidor4000/variant.cpp b/variants/mkrvidor4000/variant.cpp
index 3a4ece488..0ad45ec9a 100644
--- a/variants/mkrvidor4000/variant.cpp
+++ b/variants/mkrvidor4000/variant.cpp
@@ -168,59 +168,41 @@ extern "C" {
     }
 }
 
-#if defined(USE_BQ24195L_PMIC)
-
+#ifdef USE_BQ24195L_PMIC
+#include "PMIC.h"
 #include "wiring_private.h"
 
-#define PMIC_ADDRESS  0x6B
-#define PMIC_REG00    0x00
-#define PMIC_REG01    0x01
-#define PMIC_REG07    0x07
-
-static inline void enable_battery_charging() {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
+static inline bool is_battery_present() {
+  BQ24195_REG08 reg08;
 
-  bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  if (!ret) {
-    return;
-  }
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01);
-  PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V
+  PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG);
+  PERIPH_WIRE.sendDataMasterWIRE(BQ24195_REG08_ADDRESS);
   PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
 
-  PERIPH_WIRE.disableWIRE();
+  PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_READ_FLAG);
+  reg08.val = PERIPH_WIRE.readDataWIRE();
+  PERIPH_WIRE.prepareNackBitWIRE();
+  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+  return (reg08.DPM_STAT == 0b1);
 }
+#endif
 
-static inline void disable_battery_fet(bool disabled) {
+void initVariant() {
+#ifdef USE_BQ24195L_PMIC
   PERIPH_WIRE.initMasterWIRE(100000);
   PERIPH_WIRE.enableWIRE();
   pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
   pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
 
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG07);
-  // No D+/D– detection + Safety timer not slowed by 2X during input DPM or thermal regulation +
-  // BAT fet disabled/enabled + charge and bat fault INT
-  PERIPH_WIRE.sendDataMasterWIRE(0x0B | (disabled ? 0x20 : 0x00));
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG00);
-  PERIPH_WIRE.sendDataMasterWIRE(0x6 | 0x30);
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
+  setupPMIC(PERIPH_WIRE, true, false);
+  delay(100);
+  if (!is_battery_present()) {
+    setupPMIC(PERIPH_WIRE, false, false);
+  }
 
   PERIPH_WIRE.disableWIRE();
-}
-
 #endif
 
-void initVariant() {
-#if defined(USE_BQ24195L_PMIC)
-  enable_battery_charging();
-#endif
   startFPGA();
 }
 
diff --git a/variants/mkrwan1300/variant.cpp b/variants/mkrwan1300/variant.cpp
index 447393d06..143f2aceb 100644
--- a/variants/mkrwan1300/variant.cpp
+++ b/variants/mkrwan1300/variant.cpp
@@ -175,86 +175,41 @@ extern "C" {
 const void* g_apTCInstances[TCC_INST_NUM + TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 };
 
 
-#if defined(USE_BQ24195L_PMIC)
+#ifdef USE_BQ24195L_PMIC
+#include "PMIC.h"
 #include "wiring_private.h"
-#include "delay.h"
-
-#define PMIC_ADDRESS  0x6B
-#define PMIC_REG01    0x01
-#define PMIC_REG07    0x07
-#define PMIC_REG08    0x08
-
-static inline void enable_battery_charging() {
-
-  bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  if (!ret) {
-    return;
-  }
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01);
-  PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-}
-
-static inline void disable_battery_charging() {
-
-  bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  if (!ret) {
-    return;
-  }
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01);
-  PERIPH_WIRE.sendDataMasterWIRE(0x0B); // Charge Battery + Minimum System Voltage 3.5V
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-}
-
-static inline void disable_battery_fet(bool disabled) {
-
-  bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  if (!ret) {
-    return;
-  }
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG07);
-  // No D+/D– detection + Safety timer not slowed by 2X during input DPM or thermal regulation +
-  // BAT fet disabled/enabled + charge and bat fault INT
-  PERIPH_WIRE.sendDataMasterWIRE(0x0B | (disabled ? 0x20 : 0x00));
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-}
 
 static inline bool is_battery_present() {
+  BQ24195_REG08 reg08;
 
-  bool ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  if (!ret) {
-    return false;
-  }
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG08);
+  PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_WRITE_FLAG);
+  PERIPH_WIRE.sendDataMasterWIRE(BQ24195_REG08_ADDRESS);
   PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
 
-  ret = PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_READ_FLAG );
-  if (!ret) {
-    return false;
-  }
-  uint8_t res = PERIPH_WIRE.readDataWIRE();
+  PERIPH_WIRE.startTransmissionWIRE(BQ24195_ADDRESS, WIRE_READ_FLAG);
+  reg08.val = PERIPH_WIRE.readDataWIRE();
   PERIPH_WIRE.prepareNackBitWIRE();
   PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-  return ((res & 0b1000) != 0);
+  return (reg08.DPM_STAT == 0b1);
 }
+#endif
 
 void initVariant() {
+#ifdef USE_BQ24195L_PMIC
   PERIPH_WIRE.initMasterWIRE(100000);
   PERIPH_WIRE.enableWIRE();
   pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
   pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
 
-  enable_battery_charging();
-  //disable_battery_fet(false);
+  setupPMIC(PERIPH_WIRE, true, false);
   delay(100);
-  bool batteryPresent = is_battery_present();
-  if (!batteryPresent) {
-    disable_battery_charging();
+  if (!is_battery_present()) {
+    setupPMIC(PERIPH_WIRE, false, false);
   }
 
   PERIPH_WIRE.disableWIRE();
-}
 #endif
+}
 
 // Multi-serial objects instantiation
 SERCOM sercom0(SERCOM0);
@@ -278,4 +233,4 @@ Uart Serial2(&sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIA
 void SERCOM4_Handler()
 {
   Serial2.IrqHandler();
-}
\ No newline at end of file
+}
diff --git a/variants/mkrwifi1010/variant.cpp b/variants/mkrwifi1010/variant.cpp
index eb146fa59..bf8303f3b 100644
--- a/variants/mkrwifi1010/variant.cpp
+++ b/variants/mkrwifi1010/variant.cpp
@@ -177,59 +177,28 @@ SERCOM sercom3(SERCOM3);
 SERCOM sercom4(SERCOM4);
 SERCOM sercom5(SERCOM5);
 
-#if defined(USE_BQ24195L_PMIC)
-
+#ifdef USE_BQ24195L_PMIC
+#include "PMIC.h"
 #include "wiring_private.h"
-
-#define PMIC_ADDRESS  0x6B
-#define PMIC_REG01    0x01
-#define PMIC_REG07    0x07
-
-static inline void enable_battery_charging() {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG01);
-  PERIPH_WIRE.sendDataMasterWIRE(0x1B); // Charge Battery + Minimum System Voltage 3.5V
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
-static inline void disable_battery_fet(bool disabled) {
-  PERIPH_WIRE.initMasterWIRE(100000);
-  PERIPH_WIRE.enableWIRE();
-  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
-  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
-
-  PERIPH_WIRE.startTransmissionWIRE( PMIC_ADDRESS, WIRE_WRITE_FLAG );
-  PERIPH_WIRE.sendDataMasterWIRE(PMIC_REG07);
-  // No D+/D– detection + Safety timer not slowed by 2X during input DPM or thermal regulation +
-  // BAT fet disabled/enabled + charge and bat fault INT
-  PERIPH_WIRE.sendDataMasterWIRE(0x0B | (disabled ? 0x20 : 0x00));
-  PERIPH_WIRE.prepareCommandBitsWire(WIRE_MASTER_ACT_STOP);
-
-  PERIPH_WIRE.disableWIRE();
-}
-
 #endif
 
 void initVariant() {
-#if defined(USE_BQ24195L_PMIC)
+#ifdef USE_BQ24195L_PMIC
   pinMode(ADC_BATTERY, OUTPUT);
   digitalWrite(ADC_BATTERY, LOW);
   delay(10);
   pinMode(ADC_BATTERY, INPUT);
   delay(100);
 
+  PERIPH_WIRE.initMasterWIRE(100000);
+  PERIPH_WIRE.enableWIRE();
+  pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType);
+  pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType);
+
   bool batteryPresent = analogRead(ADC_BATTERY) > 600;
-  if (batteryPresent) {
-    enable_battery_charging();
-  }
-  disable_battery_fet(!batteryPresent);
+  setupPMIC(PERIPH_WIRE, batteryPresent, false);
+
+  PERIPH_WIRE.disableWIRE();
 #endif
 
   // NINA - SPI boot