From 5e1a6a97535f86f74495dafc1f75db73689ddad5 Mon Sep 17 00:00:00 2001
From: nerwalt <tlawren@gmail.com>
Date: Fri, 28 Jun 2024 07:11:50 -0600
Subject: [PATCH] Adding support for 9120

---
 embassy-nrf/Cargo.toml                |  14 +-
 embassy-nrf/src/chips/nrf9120.rs      | 430 ++++++++++++++++++++++++++
 embassy-nrf/src/gpiote.rs             |   8 +-
 embassy-nrf/src/lib.rs                |  42 +--
 embassy-nrf/src/nvmc.rs               |   4 +-
 embassy-nrf/src/saadc.rs              |   4 +-
 embassy-nrf/src/wdt.rs                |   8 +-
 examples/nrf9151/ns/Cargo.toml        |   2 +-
 examples/nrf9151/s/.cargo/config.toml |   1 -
 examples/nrf9151/s/Cargo.toml         |   2 +-
 examples/nrf9160/.cargo/config.toml   |   1 -
 11 files changed, 474 insertions(+), 42 deletions(-)
 create mode 100644 embassy-nrf/src/chips/nrf9120.rs

diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index f21603556..f5a3c4b0f 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -40,6 +40,7 @@ rt = [
     "nrf5340-app-pac?/rt",
     "nrf5340-net-pac?/rt",
     "nrf9160-pac?/rt",
+    "nrf9120-pac?/rt",
 ]
 
 ## Enable features requiring `embassy-time`
@@ -99,13 +100,10 @@ nrf5340-net = ["_nrf5340-net"]
 nrf9160-s = ["_nrf9160", "_s"]
 ## nRF9160 in Non-Secure mode
 nrf9160-ns = ["_nrf9160", "_ns"]
-
-# TODO - The nrf9151 is close enough to the nrf9160 for a lot of applications. It needs
-# more testing though and possilbly proper support
-## nRF9151 in Secure mode
-nrf9151-s = ["nrf9160-s"]
-## nRF9151 in Non-Secure mode
-nrf9151-ns = ["nrf9160-ns"]
+## nRF9120 in Secure mode
+nrf9120-s = ["_nrf9120", "_s"]
+## nRF9120 in Non-Secure mode
+nrf9120-ns = ["_nrf9120", "_ns"]
 
 # Features starting with `_` are for internal use only. They're not intended
 # to be enabled by other crates, and are not covered by semver guarantees.
@@ -114,6 +112,7 @@ _nrf5340-app = ["_nrf5340", "nrf5340-app-pac"]
 _nrf5340-net = ["_nrf5340", "nrf5340-net-pac"]
 _nrf5340 = ["_gpio-p1", "_dppi"]
 _nrf9160 = ["nrf9160-pac", "_dppi"]
+_nrf9120 = ["nrf9120-pac", "_dppi"]
 _nrf52 = ["_ppi"]
 _nrf51 = ["_ppi"]
 
@@ -168,3 +167,4 @@ nrf52840-pac = { version = "0.12.0", optional = true }
 nrf5340-app-pac = { version = "0.12.0", optional = true }
 nrf5340-net-pac = { version = "0.12.0", optional = true }
 nrf9160-pac = { version = "0.12.0", optional = true }
+nrf9120-pac = { path = "../../nrf-pacs/pacs/nrf9120-pac", optional = true }
diff --git a/embassy-nrf/src/chips/nrf9120.rs b/embassy-nrf/src/chips/nrf9120.rs
new file mode 100644
index 000000000..b53510118
--- /dev/null
+++ b/embassy-nrf/src/chips/nrf9120.rs
@@ -0,0 +1,430 @@
+/// Peripheral Access Crate
+#[allow(unused_imports)]
+#[rustfmt::skip]
+pub mod pac {
+    // The nRF9120 has a secure and non-secure (NS) mode.
+    // To avoid cfg spam, we remove _ns or _s suffixes here.
+
+    pub use nrf9120_pac::NVIC_PRIO_BITS;
+
+    #[cfg(feature="rt")]
+    #[doc(no_inline)]
+    pub use nrf9120_pac::interrupt;
+
+    #[doc(no_inline)]
+    pub use nrf9120_pac::{
+        Interrupt,
+
+        cc_host_rgf_s as cc_host_rgf,
+        clock_ns as clock,
+        cryptocell_s as cryptocell,
+        ctrl_ap_peri_s as ctrl_ap_peri,
+        dppic_ns as dppic,
+        egu0_ns as egu0,
+        ficr_s as ficr,
+        fpu_ns as fpu,
+        gpiote0_s as gpiote,
+        i2s_ns as i2s,
+        ipc_ns as ipc,
+        kmu_ns as kmu,
+        nvmc_ns as nvmc,
+        p0_ns as p0,
+        pdm_ns as pdm,
+        power_ns as power,
+        pwm0_ns as pwm0,
+        regulators_ns as regulators,
+        rtc0_ns as rtc0,
+        saadc_ns as saadc,
+        spim0_ns as spim0,
+        spis0_ns as spis0,
+        spu_s as spu,
+        tad_s as tad,
+        timer0_ns as timer0,
+        twim0_ns as twim0,
+        twis0_ns as twis0,
+        uarte0_ns as uarte0,
+        uicr_s as uicr,
+        vmc_ns as vmc,
+        wdt_ns as wdt,
+    };
+    
+    /// Non-Secure mode (NS) peripherals
+    pub mod ns {
+        #[doc(no_inline)]
+        pub use nrf9120_pac::{
+            CLOCK_NS as CLOCK,
+            DPPIC_NS as DPPIC,
+            EGU0_NS as EGU0,
+            EGU1_NS as EGU1,
+            EGU2_NS as EGU2,
+            EGU3_NS as EGU3,
+            EGU4_NS as EGU4,
+            EGU5_NS as EGU5,
+            FPU_NS as FPU,
+            GPIOTE1_NS as GPIOTE1,
+            I2S_NS as I2S,
+            IPC_NS as IPC,
+            KMU_NS as KMU,
+            NVMC_NS as NVMC,
+            P0_NS as P0,
+            PDM_NS as PDM,
+            POWER_NS as POWER,
+            PWM0_NS as PWM0,
+            PWM1_NS as PWM1,
+            PWM2_NS as PWM2,
+            PWM3_NS as PWM3,
+            REGULATORS_NS as REGULATORS,
+            RTC0_NS as RTC0,
+            RTC1_NS as RTC1,
+            SAADC_NS as SAADC,
+            SPIM0_NS as SPIM0,
+            SPIM1_NS as SPIM1,
+            SPIM2_NS as SPIM2,
+            SPIM3_NS as SPIM3,
+            SPIS0_NS as SPIS0,
+            SPIS1_NS as SPIS1,
+            SPIS2_NS as SPIS2,
+            SPIS3_NS as SPIS3,
+            TIMER0_NS as TIMER0,
+            TIMER1_NS as TIMER1,
+            TIMER2_NS as TIMER2,
+            TWIM0_NS as TWIM0,
+            TWIM1_NS as TWIM1,
+            TWIM2_NS as TWIM2,
+            TWIM3_NS as TWIM3,
+            TWIS0_NS as TWIS0,
+            TWIS1_NS as TWIS1,
+            TWIS2_NS as TWIS2,
+            TWIS3_NS as TWIS3,
+            UARTE0_NS as UARTE0,
+            UARTE1_NS as UARTE1,
+            UARTE2_NS as UARTE2,
+            UARTE3_NS as UARTE3,
+            VMC_NS as VMC,
+            WDT_NS as WDT,
+        };
+    }
+
+    /// Secure mode (S) peripherals
+    pub mod s {
+        #[doc(no_inline)]
+        pub use nrf9120_pac::{
+            CC_HOST_RGF_S as CC_HOST_RGF,
+            CLOCK_S as CLOCK,
+            CRYPTOCELL_S as CRYPTOCELL,
+            CTRL_AP_PERI_S as CTRL_AP_PERI,
+            DPPIC_S as DPPIC,
+            EGU0_S as EGU0,
+            EGU1_S as EGU1,
+            EGU2_S as EGU2,
+            EGU3_S as EGU3,
+            EGU4_S as EGU4,
+            EGU5_S as EGU5,
+            FICR_S as FICR,
+            FPU as FPU,
+            GPIOTE0_S as GPIOTE0,
+            I2S_S as I2S,
+            IPC_S as IPC,
+            KMU_S as KMU,
+            NVMC_S as NVMC,
+            P0_S as P0,
+            PDM_S as PDM,
+            POWER_S as POWER,
+            PWM0_S as PWM0,
+            PWM1_S as PWM1,
+            PWM2_S as PWM2,
+            PWM3_S as PWM3,
+            REGULATORS_S as REGULATORS,
+            RTC0_S as RTC0,
+            RTC1_S as RTC1,
+            SAADC_S as SAADC,
+            SPIM0_S as SPIM0,
+            SPIM1_S as SPIM1,
+            SPIM2_S as SPIM2,
+            SPIM3_S as SPIM3,
+            SPIS0_S as SPIS0,
+            SPIS1_S as SPIS1,
+            SPIS2_S as SPIS2,
+            SPIS3_S as SPIS3,
+            SPU_S as SPU,
+            TAD_S as TAD,
+            TIMER0_S as TIMER0,
+            TIMER1_S as TIMER1,
+            TIMER2_S as TIMER2,
+            TWIM0_S as TWIM0,
+            TWIM1_S as TWIM1,
+            TWIM2_S as TWIM2,
+            TWIM3_S as TWIM3,
+            TWIS0_S as TWIS0,
+            TWIS1_S as TWIS1,
+            TWIS2_S as TWIS2,
+            TWIS3_S as TWIS3,
+            UARTE0_S as UARTE0,
+            UARTE1_S as UARTE1,
+            UARTE2_S as UARTE2,
+            UARTE3_S as UARTE3,
+            UICR_S as UICR,
+            VMC_S as VMC,
+            WDT_S as WDT,
+        };
+    }
+
+    #[cfg(feature = "_ns")]
+    pub use ns::*;
+    #[cfg(feature = "_s")]
+    pub use s::*;
+}
+
+/// The maximum buffer size that the EasyDMA can send/recv in one operation.
+pub const EASY_DMA_SIZE: usize = (1 << 13) - 1;
+pub const FORCE_COPY_BUFFER_SIZE: usize = 1024;
+
+pub const FLASH_SIZE: usize = 1024 * 1024;
+
+embassy_hal_internal::peripherals! {
+    // RTC
+    RTC0,
+    RTC1,
+
+    // WDT
+    WDT,
+
+    // NVMC
+    NVMC,
+
+    // UARTE, TWI & SPI
+    SERIAL0,
+    SERIAL1,
+    SERIAL2,
+    SERIAL3,
+
+    // SAADC
+    SAADC,
+
+    // PWM
+    PWM0,
+    PWM1,
+    PWM2,
+    PWM3,
+
+    // TIMER
+    TIMER0,
+    TIMER1,
+    TIMER2,
+
+    // GPIOTE
+    GPIOTE_CH0,
+    GPIOTE_CH1,
+    GPIOTE_CH2,
+    GPIOTE_CH3,
+    GPIOTE_CH4,
+    GPIOTE_CH5,
+    GPIOTE_CH6,
+    GPIOTE_CH7,
+
+    // PPI
+    PPI_CH0,
+    PPI_CH1,
+    PPI_CH2,
+    PPI_CH3,
+    PPI_CH4,
+    PPI_CH5,
+    PPI_CH6,
+    PPI_CH7,
+    PPI_CH8,
+    PPI_CH9,
+    PPI_CH10,
+    PPI_CH11,
+    PPI_CH12,
+    PPI_CH13,
+    PPI_CH14,
+    PPI_CH15,
+
+    PPI_GROUP0,
+    PPI_GROUP1,
+    PPI_GROUP2,
+    PPI_GROUP3,
+    PPI_GROUP4,
+    PPI_GROUP5,
+
+    // GPIO port 0
+    P0_00,
+    P0_01,
+    P0_02,
+    P0_03,
+    P0_04,
+    P0_05,
+    P0_06,
+    P0_07,
+    P0_08,
+    P0_09,
+    P0_10,
+    P0_11,
+    P0_12,
+    P0_13,
+    P0_14,
+    P0_15,
+    P0_16,
+    P0_17,
+    P0_18,
+    P0_19,
+    P0_20,
+    P0_21,
+    P0_22,
+    P0_23,
+    P0_24,
+    P0_25,
+    P0_26,
+    P0_27,
+    P0_28,
+    P0_29,
+    P0_30,
+    P0_31,
+
+    // PDM
+    PDM,
+
+    // EGU
+    EGU0,
+    EGU1,
+    EGU2,
+    EGU3,
+    EGU4,
+    EGU5,
+}
+
+impl_uarte!(SERIAL0, UARTE0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0);
+impl_uarte!(SERIAL1, UARTE1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1);
+impl_uarte!(SERIAL2, UARTE2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2);
+impl_uarte!(SERIAL3, UARTE3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3);
+
+impl_spim!(SERIAL0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0);
+impl_spim!(SERIAL1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1);
+impl_spim!(SERIAL2, SPIM2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2);
+impl_spim!(SERIAL3, SPIM3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3);
+
+impl_spis!(SERIAL0, SPIS0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0);
+impl_spis!(SERIAL1, SPIS1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1);
+impl_spis!(SERIAL2, SPIS2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2);
+impl_spis!(SERIAL3, SPIS3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3);
+
+impl_twim!(SERIAL0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0);
+impl_twim!(SERIAL1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1);
+impl_twim!(SERIAL2, TWIM2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2);
+impl_twim!(SERIAL3, TWIM3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3);
+
+impl_twis!(SERIAL0, TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_UARTE0);
+impl_twis!(SERIAL1, TWIS1, SPIM1_SPIS1_TWIM1_TWIS1_UARTE1);
+impl_twis!(SERIAL2, TWIS2, SPIM2_SPIS2_TWIM2_TWIS2_UARTE2);
+impl_twis!(SERIAL3, TWIS3, SPIM3_SPIS3_TWIM3_TWIS3_UARTE3);
+
+impl_pwm!(PWM0, PWM0, PWM0);
+impl_pwm!(PWM1, PWM1, PWM1);
+impl_pwm!(PWM2, PWM2, PWM2);
+impl_pwm!(PWM3, PWM3, PWM3);
+
+impl_pdm!(PDM, PDM, PDM);
+
+impl_timer!(TIMER0, TIMER0, TIMER0);
+impl_timer!(TIMER1, TIMER1, TIMER1);
+impl_timer!(TIMER2, TIMER2, TIMER2);
+
+impl_pin!(P0_00, 0, 0);
+impl_pin!(P0_01, 0, 1);
+impl_pin!(P0_02, 0, 2);
+impl_pin!(P0_03, 0, 3);
+impl_pin!(P0_04, 0, 4);
+impl_pin!(P0_05, 0, 5);
+impl_pin!(P0_06, 0, 6);
+impl_pin!(P0_07, 0, 7);
+impl_pin!(P0_08, 0, 8);
+impl_pin!(P0_09, 0, 9);
+impl_pin!(P0_10, 0, 10);
+impl_pin!(P0_11, 0, 11);
+impl_pin!(P0_12, 0, 12);
+impl_pin!(P0_13, 0, 13);
+impl_pin!(P0_14, 0, 14);
+impl_pin!(P0_15, 0, 15);
+impl_pin!(P0_16, 0, 16);
+impl_pin!(P0_17, 0, 17);
+impl_pin!(P0_18, 0, 18);
+impl_pin!(P0_19, 0, 19);
+impl_pin!(P0_20, 0, 20);
+impl_pin!(P0_21, 0, 21);
+impl_pin!(P0_22, 0, 22);
+impl_pin!(P0_23, 0, 23);
+impl_pin!(P0_24, 0, 24);
+impl_pin!(P0_25, 0, 25);
+impl_pin!(P0_26, 0, 26);
+impl_pin!(P0_27, 0, 27);
+impl_pin!(P0_28, 0, 28);
+impl_pin!(P0_29, 0, 29);
+impl_pin!(P0_30, 0, 30);
+impl_pin!(P0_31, 0, 31);
+
+impl_ppi_channel!(PPI_CH0, 0 => configurable);
+impl_ppi_channel!(PPI_CH1, 1 => configurable);
+impl_ppi_channel!(PPI_CH2, 2 => configurable);
+impl_ppi_channel!(PPI_CH3, 3 => configurable);
+impl_ppi_channel!(PPI_CH4, 4 => configurable);
+impl_ppi_channel!(PPI_CH5, 5 => configurable);
+impl_ppi_channel!(PPI_CH6, 6 => configurable);
+impl_ppi_channel!(PPI_CH7, 7 => configurable);
+impl_ppi_channel!(PPI_CH8, 8 => configurable);
+impl_ppi_channel!(PPI_CH9, 9 => configurable);
+impl_ppi_channel!(PPI_CH10, 10 => configurable);
+impl_ppi_channel!(PPI_CH11, 11 => configurable);
+impl_ppi_channel!(PPI_CH12, 12 => configurable);
+impl_ppi_channel!(PPI_CH13, 13 => configurable);
+impl_ppi_channel!(PPI_CH14, 14 => configurable);
+impl_ppi_channel!(PPI_CH15, 15 => configurable);
+
+impl_saadc_input!(P0_13, ANALOG_INPUT0);
+impl_saadc_input!(P0_14, ANALOG_INPUT1);
+impl_saadc_input!(P0_15, ANALOG_INPUT2);
+impl_saadc_input!(P0_16, ANALOG_INPUT3);
+impl_saadc_input!(P0_17, ANALOG_INPUT4);
+impl_saadc_input!(P0_18, ANALOG_INPUT5);
+impl_saadc_input!(P0_19, ANALOG_INPUT6);
+impl_saadc_input!(P0_20, ANALOG_INPUT7);
+
+impl_egu!(EGU0, EGU0, EGU0);
+impl_egu!(EGU1, EGU1, EGU1);
+impl_egu!(EGU2, EGU2, EGU2);
+impl_egu!(EGU3, EGU3, EGU3);
+impl_egu!(EGU4, EGU4, EGU4);
+impl_egu!(EGU5, EGU5, EGU5);
+
+embassy_hal_internal::interrupt_mod!(
+    SPU,
+    CLOCK_POWER,
+    SPIM0_SPIS0_TWIM0_TWIS0_UARTE0,
+    SPIM1_SPIS1_TWIM1_TWIS1_UARTE1,
+    SPIM2_SPIS2_TWIM2_TWIS2_UARTE2,
+    SPIM3_SPIS3_TWIM3_TWIS3_UARTE3,
+    GPIOTE0,
+    SAADC,
+    TIMER0,
+    TIMER1,
+    TIMER2,
+    RTC0,
+    RTC1,
+    WDT,
+    EGU0,
+    EGU1,
+    EGU2,
+    EGU3,
+    EGU4,
+    EGU5,
+    PWM0,
+    PWM1,
+    PWM2,
+    PDM,
+    PWM3,
+    I2S,
+    IPC,
+    FPU,
+    GPIOTE1,
+    KMU,
+    CRYPTOCELL,
+);
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index a74b3157b..5366de3f0 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -53,9 +53,9 @@ pub enum OutputChannelPolarity {
 
 fn regs() -> &'static pac::gpiote::RegisterBlock {
     cfg_if::cfg_if! {
-        if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s"))] {
+        if #[cfg(any(feature="nrf5340-app-s", feature="nrf9160-s", feature="nrf9120-s"))] {
             unsafe { &*pac::GPIOTE0::ptr() }
-        } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns"))] {
+        } else if #[cfg(any(feature="nrf5340-app-ns", feature="nrf9160-ns", feature="nrf9120-ns"))] {
             unsafe { &*pac::GPIOTE1::ptr() }
         } else {
             unsafe { &*pac::GPIOTE::ptr() }
@@ -81,9 +81,9 @@ pub(crate) fn init(irq_prio: crate::interrupt::Priority) {
     }
 
     // Enable interrupts
-    #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s"))]
+    #[cfg(any(feature = "nrf5340-app-s", feature = "nrf9160-s", feature = "nrf9120-s"))]
     let irq = interrupt::GPIOTE0;
-    #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns"))]
+    #[cfg(any(feature = "nrf5340-app-ns", feature = "nrf9160-ns", feature = "nrf9120-ns"))]
     let irq = interrupt::GPIOTE1;
     #[cfg(any(feature = "_nrf51", feature = "_nrf52", feature = "nrf5340-net"))]
     let irq = interrupt::GPIOTE;
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 05b52f687..15d2e65b2 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -24,6 +24,8 @@
     feature = "nrf5340-net",
     feature = "nrf9160-s",
     feature = "nrf9160-ns",
+    feature = "nrf9120-s",
+    feature = "nrf9120-ns",
 )))]
 compile_error!("No chip feature activated. You must activate exactly one of the following features: nrf52810, nrf52811, nrf52832, nrf52833, nrf52840");
 
@@ -47,7 +49,7 @@ pub mod gpio;
 pub mod gpiote;
 
 // TODO: tested on other chips
-#[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340-app")))]
+#[cfg(not(any(feature = "_nrf9160", feature = "_nrf9120", feature = "_nrf5340-app")))]
 pub mod radio;
 
 #[cfg(not(feature = "nrf51"))]
@@ -62,7 +64,8 @@ pub mod nvmc;
     feature = "nrf52833",
     feature = "nrf52840",
     feature = "_nrf5340-app",
-    feature = "_nrf9160"
+    feature = "_nrf9160",
+    feature = "_nrf9120"
 ))]
 pub mod pdm;
 pub mod ppi;
@@ -73,11 +76,11 @@ pub mod ppi;
     feature = "_nrf5340-net"
 )))]
 pub mod pwm;
-#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))]
+#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf9120", feature = "_nrf5340-net")))]
 pub mod qdec;
 #[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
 pub mod qspi;
-#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160")))]
+#[cfg(not(any(feature = "_nrf5340-app", feature = "_nrf9160", feature = "_nrf9120")))]
 pub mod rng;
 #[cfg(not(any(feature = "nrf51", feature = "nrf52820", feature = "_nrf5340-net")))]
 pub mod saadc;
@@ -85,7 +88,7 @@ pub mod saadc;
 pub mod spim;
 #[cfg(not(feature = "nrf51"))]
 pub mod spis;
-#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
+#[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
 pub mod temp;
 pub mod timer;
 #[cfg(not(feature = "nrf51"))]
@@ -116,6 +119,7 @@ pub mod wdt;
 #[cfg_attr(feature = "_nrf5340-app", path = "chips/nrf5340_app.rs")]
 #[cfg_attr(feature = "_nrf5340-net", path = "chips/nrf5340_net.rs")]
 #[cfg_attr(feature = "_nrf9160", path = "chips/nrf9160.rs")]
+#[cfg_attr(feature = "_nrf9120", path = "chips/nrf9120.rs")]
 mod chip;
 
 /// Macro to bind interrupts to handlers.
@@ -196,15 +200,15 @@ pub mod config {
         /// Internal RC oscillator
         InternalRC,
         /// Synthesized from the high frequency clock source.
-        #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
+        #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
         Synthesized,
         /// External source from xtal.
         ExternalXtal,
         /// External source from xtal with low swing applied.
-        #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
+        #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
         ExternalLowSwing,
         /// External source from xtal with full swing applied.
-        #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
+        #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
         ExternalFullSwing,
     }
 
@@ -222,7 +226,7 @@ pub mod config {
     }
 
     /// Settings for enabling the built in DCDC converters.
-    #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
+    #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
     pub struct DcdcConfig {
         /// Config for the first stage DCDC (VDDH -> VDD), if disabled LDO will be used.
         #[cfg(feature = "nrf52840")]
@@ -264,7 +268,7 @@ pub mod config {
     }
 
     /// Settings for enabling the built in DCDC converter.
-    #[cfg(feature = "_nrf9160")]
+    #[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
     pub struct DcdcConfig {
         /// Config for the main rail, if disabled LDO will be used.
         pub regmain: bool,
@@ -298,7 +302,7 @@ pub mod config {
                 // xtals if they know they have them.
                 hfclk_source: HfclkSource::Internal,
                 lfclk_source: LfclkSource::InternalRC,
-                #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
+                #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
                 dcdc: DcdcConfig {
                     #[cfg(feature = "nrf52840")]
                     reg0: false,
@@ -312,7 +316,7 @@ pub mod config {
                     regmain: false,
                     regradio: false,
                 },
-                #[cfg(feature = "_nrf9160")]
+                #[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
                 dcdc: DcdcConfig { regmain: false },
                 #[cfg(feature = "gpiote")]
                 gpiote_interrupt_priority: crate::interrupt::Priority::P0,
@@ -329,7 +333,7 @@ pub mod config {
     }
 }
 
-#[cfg(feature = "_nrf9160")]
+#[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
 #[allow(unused)]
 mod consts {
     pub const UICR_APPROTECT: *mut u32 = 0x00FF8000 as *mut u32;
@@ -468,7 +472,7 @@ pub fn init(config: config::Config) -> Peripherals {
             // UICR.APPROTECT = Enabled
             let res = uicr_write(consts::UICR_APPROTECT, consts::APPROTECT_ENABLED);
             needs_reset |= res == WriteResult::Written;
-            #[cfg(any(feature = "_nrf5340-app", feature = "_nrf9160"))]
+            #[cfg(any(feature = "_nrf5340-app", feature = "_nrf9160", feature = "_nrf9120"))]
             {
                 let res = uicr_write(consts::UICR_SECUREAPPROTECT, consts::APPROTECT_ENABLED);
                 needs_reset |= res == WriteResult::Written;
@@ -552,7 +556,7 @@ pub fn init(config: config::Config) -> Peripherals {
     }
 
     // Configure LFCLK.
-    #[cfg(not(any(feature = "nrf51", feature = "_nrf5340", feature = "_nrf9160")))]
+    #[cfg(not(any(feature = "nrf51", feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
     match config.lfclk_source {
         config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()),
         config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()),
@@ -572,7 +576,7 @@ pub fn init(config: config::Config) -> Peripherals {
             w
         }),
     }
-    #[cfg(feature = "_nrf9160")]
+    #[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
     match config.lfclk_source {
         config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().lfrc()),
         config::LfclkSource::ExternalXtal => r.lfclksrc.write(|w| w.src().lfxo()),
@@ -585,7 +589,7 @@ pub fn init(config: config::Config) -> Peripherals {
     r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) });
     while r.events_lfclkstarted.read().bits() == 0 {}
 
-    #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))]
+    #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160", feature = "_nrf9120")))]
     {
         // Setup DCDCs.
         let pwr = unsafe { &*pac::POWER::ptr() };
@@ -597,7 +601,7 @@ pub fn init(config: config::Config) -> Peripherals {
             pwr.dcdcen.write(|w| w.dcdcen().set_bit());
         }
     }
-    #[cfg(feature = "_nrf9160")]
+    #[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
     {
         // Setup DCDC.
         let reg = unsafe { &*pac::REGULATORS::ptr() };
@@ -629,7 +633,7 @@ pub fn init(config: config::Config) -> Peripherals {
     time_driver::init(config.time_interrupt_priority);
 
     // Disable UARTE (enabled by default for some reason)
-    #[cfg(feature = "_nrf9160")]
+    #[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
     unsafe {
         (*pac::UARTE0::ptr()).enable.write(|w| w.enable().disabled());
         (*pac::UARTE1::ptr()).enable.write(|w| w.enable().disabled());
diff --git a/embassy-nrf/src/nvmc.rs b/embassy-nrf/src/nvmc.rs
index 4f9eda167..df027636c 100644
--- a/embassy-nrf/src/nvmc.rs
+++ b/embassy-nrf/src/nvmc.rs
@@ -71,12 +71,12 @@ impl<'d> Nvmc<'d> {
         while p.readynext.read().readynext().is_busy() {}
     }
 
-    #[cfg(not(any(feature = "_nrf9160", feature = "_nrf5340")))]
+    #[cfg(not(any(feature = "_nrf9160", feature = "_nrf9120", feature = "_nrf5340")))]
     fn erase_page(&mut self, page_addr: u32) {
         Self::regs().erasepage().write(|w| unsafe { w.bits(page_addr) });
     }
 
-    #[cfg(any(feature = "_nrf9160", feature = "_nrf5340"))]
+    #[cfg(any(feature = "_nrf9160", feature = "_nrf9120", feature = "_nrf5340"))]
     fn erase_page(&mut self, page_addr: u32) {
         let first_page_word = page_addr as *mut u32;
         unsafe {
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index 17c65fa3e..e139b15da 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -722,9 +722,9 @@ macro_rules! impl_saadc_input {
 pub struct VddInput;
 
 impl_peripheral!(VddInput);
-#[cfg(not(feature = "_nrf9160"))]
+#[cfg(not(any(feature = "_nrf9160", feature = "_nrf9120")))]
 impl_saadc_input!(@local, VddInput, VDD);
-#[cfg(feature = "_nrf9160")]
+#[cfg(not(any(feature = "_nrf9160", feature = "_nrf9120")))]
 impl_saadc_input!(@local, VddInput, VDDGPIO);
 
 /// A dummy `Input` pin implementation for SAADC peripheral sampling from the
diff --git a/embassy-nrf/src/wdt.rs b/embassy-nrf/src/wdt.rs
index 40a674424..5b3e1e930 100644
--- a/embassy-nrf/src/wdt.rs
+++ b/embassy-nrf/src/wdt.rs
@@ -30,9 +30,9 @@ impl Config {
     pub fn try_new(_wdt: &peripherals::WDT) -> Option<Self> {
         let r = unsafe { &*WDT::ptr() };
 
-        #[cfg(not(feature = "_nrf9160"))]
+        #[cfg(not(any(feature = "_nrf9160", feature = "_nrf9120")))]
         let runstatus = r.runstatus.read().runstatus().bit();
-        #[cfg(feature = "_nrf9160")]
+        #[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
         let runstatus = r.runstatus.read().runstatuswdt().bit();
 
         if runstatus {
@@ -83,9 +83,9 @@ impl Watchdog {
         let crv = config.timeout_ticks.max(MIN_TICKS);
         let rren = (1u32 << N) - 1;
 
-        #[cfg(not(feature = "_nrf9160"))]
+        #[cfg(not(any(feature = "_nrf9160", feature = "_nrf9120")))]
         let runstatus = r.runstatus.read().runstatus().bit();
-        #[cfg(feature = "_nrf9160")]
+        #[cfg(any(feature = "_nrf9160", feature = "_nrf9120"))]
         let runstatus = r.runstatus.read().runstatuswdt().bit();
 
         if runstatus {
diff --git a/examples/nrf9151/ns/Cargo.toml b/examples/nrf9151/ns/Cargo.toml
index 0765d52d1..d73f17e87 100644
--- a/examples/nrf9151/ns/Cargo.toml
+++ b/examples/nrf9151/ns/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
 [dependencies]
 embassy-executor = { version = "0.5.0", path = "../../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
 embassy-time = { version = "0.3.1", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
-embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9151-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
+embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-ns", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
 
 defmt = "0.3"
 defmt-rtt = "0.4"
diff --git a/examples/nrf9151/s/.cargo/config.toml b/examples/nrf9151/s/.cargo/config.toml
index 1444b0cd1..f64c63966 100644
--- a/examples/nrf9151/s/.cargo/config.toml
+++ b/examples/nrf9151/s/.cargo/config.toml
@@ -1,5 +1,4 @@
 [target.'cfg(all(target_arch = "arm", target_os = "none"))']
-# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list`
 runner = "probe-rs run --chip nRF9160_xxAA"
 
 [build]
diff --git a/examples/nrf9151/s/Cargo.toml b/examples/nrf9151/s/Cargo.toml
index 0299002a0..164f9c94e 100644
--- a/examples/nrf9151/s/Cargo.toml
+++ b/examples/nrf9151/s/Cargo.toml
@@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
 [dependencies]
 embassy-executor = { version = "0.5.0", path = "../../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
 embassy-time = { version = "0.3.1", path = "../../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
-embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9151-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
+embassy-nrf = { version = "0.1.0", path = "../../../embassy-nrf", features = ["defmt", "nrf9120-s", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
 
 defmt = "0.3"
 defmt-rtt = "0.4"
diff --git a/examples/nrf9160/.cargo/config.toml b/examples/nrf9160/.cargo/config.toml
index 1444b0cd1..f64c63966 100644
--- a/examples/nrf9160/.cargo/config.toml
+++ b/examples/nrf9160/.cargo/config.toml
@@ -1,5 +1,4 @@
 [target.'cfg(all(target_arch = "arm", target_os = "none"))']
-# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list`
 runner = "probe-rs run --chip nRF9160_xxAA"
 
 [build]