diff --git a/stmhal/boards/LIMIFROG/mpconfigboard.h b/stmhal/boards/LIMIFROG/mpconfigboard.h
index 95fd6bf50666fee5b22724044d89f262e1f1adcd..d04634ac38b4007bce526e2e62c6e0d6ce270a00 100644
--- a/stmhal/boards/LIMIFROG/mpconfigboard.h
+++ b/stmhal/boards/LIMIFROG/mpconfigboard.h
@@ -37,13 +37,6 @@ void LIMIFROG_board_early_init(void);
 #define MICROPY_HW_I2C1_SDA (pin_B9)
 #define MICROPY_HW_I2C2_SCL (pin_B10)
 #define MICROPY_HW_I2C2_SDA (pin_B11)
-// We use an array of baudrates and corresponding TIMINGR values.
-//
-// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
-// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
-#define MICROPY_HW_I2C_BAUDRATE_TIMING  {{100000, 0x90112626}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX     100000
 
 // SPI busses
 #define MICROPY_HW_SPI1_NSS     (pin_A4)
diff --git a/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h b/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h
index 647525384faee6ad8d5b2d35c0187bb2e2162d4e..cafea136f90b396626d2abd1e1094603ff321f8b 100644
--- a/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h
+++ b/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h
@@ -52,11 +52,6 @@
 #define MICROPY_HW_I2C3_SCL         (pin_H7)
 #define MICROPY_HW_I2C3_SDA         (pin_H8)
 
-// TODO These should go in i2c.c
-#define MICROPY_HW_I2C_BAUDRATE_TIMING  {{100000, 0x40912732}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX     100000
-
 // SPI
 #define MICROPY_HW_SPI3_NSS         (pin_A4)
 #define MICROPY_HW_SPI3_SCK         (pin_B3)
diff --git a/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h b/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h
index 181580b147f82b30a459a34375f896ef6fc28bf7..f2474619feac3c14648371f3c5b174e643ed2c30 100644
--- a/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h
+++ b/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h
@@ -21,10 +21,6 @@
 #define MICROPY_HW_UART_REPL        PYB_UART_2
 #define MICROPY_HW_UART_REPL_BAUD   115200
 
-#define MICROPY_HW_I2C_BAUDRATE_TIMING  {{100000, 0x90112626}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX     100000
-
 #define MICROPY_HW_FLASH_LATENCY    FLASH_LATENCY_4
 
 // I2C busses
diff --git a/stmhal/boards/STM32F769DISC/mpconfigboard.h b/stmhal/boards/STM32F769DISC/mpconfigboard.h
index 72465c7994bb9fc04a039b1fe8c29b385a2f9182..50b9c1618fae1f56265612bee62b34030af320a6 100644
--- a/stmhal/boards/STM32F769DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F769DISC/mpconfigboard.h
@@ -43,11 +43,6 @@
 #define MICROPY_HW_I2C3_SCL         (pin_H7)
 #define MICROPY_HW_I2C3_SDA         (pin_H8)
 
-// TODO These should go in i2c.c
-#define MICROPY_HW_I2C_BAUDRATE_TIMING  {{100000, 0x40912732}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX     100000
-
 // SPI
 #define MICROPY_HW_SPI2_NSS         (pin_A11)
 #define MICROPY_HW_SPI2_SCK         (pin_A12)
diff --git a/stmhal/boards/STM32F7DISC/mpconfigboard.h b/stmhal/boards/STM32F7DISC/mpconfigboard.h
index 38665055f1207d17b89a8fe6ff8565f209d473a9..44a39c0a1a19c0349ce90c0d4819ecbb8287aa5c 100644
--- a/stmhal/boards/STM32F7DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F7DISC/mpconfigboard.h
@@ -51,16 +51,6 @@ void STM32F7DISC_board_early_init(void);
 #define MICROPY_HW_I2C3_SCL         (pin_H7)
 #define MICROPY_HW_I2C3_SDA         (pin_H8)
 
-// The STM32F7 uses a TIMINGR register which is configured using an Excel
-// Spreadsheet from AN4235: http://www.st.com/web/en/catalog/tools/PF258335
-// We use an array of baudrates and corresponding TIMINGR values.
-//
-// The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant
-// defined in the STM32F7Cube file Drivers/BSP/STM32F746G-Discovery/stm32f7456g_discovery.h
-#define MICROPY_HW_I2C_BAUDRATE_TIMING  {{100000, 0x40912732}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX     100000
-
 // SPI
 #define MICROPY_HW_SPI2_NSS         (pin_I0)
 #define MICROPY_HW_SPI2_SCK         (pin_I1)
diff --git a/stmhal/boards/STM32L476DISC/mpconfigboard.h b/stmhal/boards/STM32L476DISC/mpconfigboard.h
index a93b486c68bdfa874027614a9822351c1bfdf35b..258a86b6062bd27d6f38a4c64ac591b854bb6237 100644
--- a/stmhal/boards/STM32L476DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32L476DISC/mpconfigboard.h
@@ -47,13 +47,6 @@ void STM32L476DISC_board_early_init(void);
 #define MICROPY_HW_I2C1_SDA (pin_B7)
 #define MICROPY_HW_I2C2_SCL (pin_B10)
 #define MICROPY_HW_I2C2_SDA (pin_B11)
-// We use an array of baudrates and corresponding TIMINGR values.
-//
-// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
-// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
-#define MICROPY_HW_I2C_BAUDRATE_TIMING  {{100000, 0x90112626}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX     100000
 
 // SPI busses
 #define MICROPY_HW_SPI2_NSS     (pin_D0)
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 412a8e3638b7dfe78e45fe87ddde1d98f2c06c04..e818ec380f20b31afdffd403adc0dc5459796f1a 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -37,14 +37,6 @@
 #include "dma.h"
 #include "i2c.h"
 
-#if !defined(MICROPY_HW_I2C_BAUDRATE_DEFAULT)
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 400000
-#endif
-
-#if !defined(MICROPY_HW_I2C_BAUDRATE_MAX)
-#define MICROPY_HW_I2C_BAUDRATE_MAX 400000
-#endif
-
 /// \moduleref pyb
 /// \class I2C - a two-wire serial protocol
 ///
@@ -134,10 +126,42 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = {
     #endif
 };
 
-#if defined(MICROPY_HW_I2C_BAUDRATE_TIMING)
+#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
+
 // The STM32F0, F3, F7 and L4 use a TIMINGR register rather than ClockSpeed and
 // DutyCycle.
 
+#if defined(STM32F746xx)
+
+// The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant
+// defined in the STM32F7Cube file Drivers/BSP/STM32F746G-Discovery/stm32f7456g_discovery.h
+#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x40912732}}
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (100000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (100000)
+
+#elif defined(STM32F767xx) || defined(STM32F769xx)
+
+// These timing values are for f_I2CCLK=54MHz and are only approximate
+#define MICROPY_HW_I2C_BAUDRATE_TIMING { \
+        {100000, 0xb0420f13}, \
+        {400000, 0x70330309}, \
+        {1000000, 0x50100103}, \
+    }
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (400000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (1000000)
+
+#elif defined(MCU_SERIES_L4)
+
+// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
+// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
+#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x90112626}}
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (100000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (100000)
+
+#else
+#error "no I2C timings for this MCU"
+#endif
+
 STATIC const struct {
     uint32_t    baudrate;
     uint32_t    timing;
@@ -167,6 +191,9 @@ uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
 
 #else
 
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (400000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (400000)
+
 STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) {
     init->ClockSpeed = baudrate;
     init->DutyCycle = I2C_DUTYCYCLE_16_9;
@@ -176,7 +203,7 @@ uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
     return init->ClockSpeed;
 }
 
-#endif // MICROPY_HW_I2C_BAUDRATE_TIMING
+#endif
 
 void i2c_init0(void) {
     // reset the I2C1 handles