diff --git a/embedded-hal-bus/Cargo.toml b/embedded-hal-bus/Cargo.toml
index 6ab831fb..d0ebecf7 100644
--- a/embedded-hal-bus/Cargo.toml
+++ b/embedded-hal-bus/Cargo.toml
@@ -15,8 +15,18 @@ repository = "https://github.com/rust-embedded/embedded-hal"
 version = "0.2.0"
 
 [features]
+# Enable shared bus implementations using `std::sync::Mutex`, and implement `std::error::Error` for `DeviceError`
 std = ["alloc"]
+# Use `portable-atomic` to enable `atomic-device` on devices without native atomic CAS
+#
+# `portable-atomic` emulates atomic CAS functionality, allowing `embedded-hal-bus` to use `atomic-device` on hardware
+# that does not natively support atomic CAS. If you enable this, you must also add `portable-atomic` to your crate with
+# a feature flag such as `unsafe-assume-single-core` or `critical-section` to choose how atomic CAS is implemented.
+# See https://docs.rs/portable-atomic/1.7.0/portable_atomic/#optional-features for more info.
+portable-atomic = ["dep:portable-atomic"]
+# Enable `embedded-hal-async` support.
 async = ["dep:embedded-hal-async"]
+# Derive `defmt::Format` from `defmt` 0.3 for enums and structs. See https://github.com/knurling-rs/defmt for more info
 defmt-03 = ["dep:defmt-03", "embedded-hal/defmt-03", "embedded-hal-async?/defmt-03"]
 # Enables additional utilities requiring a global allocator.
 alloc = []
@@ -26,7 +36,7 @@ embedded-hal = { version = "1.0.0", path = "../embedded-hal" }
 embedded-hal-async = { version = "1.0.0", path = "../embedded-hal-async", optional = true }
 critical-section = { version = "1.0" }
 defmt-03 = { package = "defmt", version = "0.3", optional = true }
-portable-atomic = {version = "1", default-features = false}
+portable-atomic = {version = "1.3", default-features = false, optional = true, features = ["require-cas"]}
 
 [package.metadata.docs.rs]
 features = ["std", "async"]
diff --git a/embedded-hal-bus/README.md b/embedded-hal-bus/README.md
index 2089cb8a..2e6d9db0 100644
--- a/embedded-hal-bus/README.md
+++ b/embedded-hal-bus/README.md
@@ -30,11 +30,17 @@ provides mechanisms to obtain multiple `I2c` instances out of a single `I2c` ins
 
 ## Optional Cargo features
 
-- **`std`**: enable shared bus implementations using `std::sync::Mutex`, and implement
-  `std::error::Error` for `DeviceError`.
 - **`async`**: enable `embedded-hal-async` support.
 - **`defmt-03`**: Derive `defmt::Format` from `defmt` 0.3 for enums and structs.
 - **`alloc`**: enable implementations using `alloc` (for instance, `spi::RcDevice`, which makes use of `alloc::rc::Rc`)
+- **`portable-atomic`**: Use `portable-atomic` to enable `atomic-device` on devices without native atomic CAS
+
+  `portable-atomic` emulates atomic CAS functionality, allowing `embedded-hal-bus` to use `atomic-device` on hardware
+  that does not natively support atomic CAS. If you enable this, you must also add `portable-atomic` to your crate with
+  a feature flag such as `unsafe-assume-single-core` or `critical-section` to choose how atomic CAS is implemented.
+  See <https://docs.rs/portable-atomic/1.7.0/portable_atomic/#optional-features> for more info.
+- **`std`**: enable shared bus implementations using `std::sync::Mutex`, and implement
+  `std::error::Error` for `DeviceError`.
 
 ## Minimum Supported Rust Version (MSRV)
 
diff --git a/embedded-hal-bus/src/i2c/mod.rs b/embedded-hal-bus/src/i2c/mod.rs
index 6420d06c..5f322631 100644
--- a/embedded-hal-bus/src/i2c/mod.rs
+++ b/embedded-hal-bus/src/i2c/mod.rs
@@ -8,7 +8,9 @@ mod mutex;
 pub use mutex::*;
 mod critical_section;
 pub use self::critical_section::*;
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 mod atomic;
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 pub use atomic::*;
 
 #[cfg(feature = "alloc")]
diff --git a/embedded-hal-bus/src/spi/mod.rs b/embedded-hal-bus/src/spi/mod.rs
index b654a54c..5a8356e2 100644
--- a/embedded-hal-bus/src/spi/mod.rs
+++ b/embedded-hal-bus/src/spi/mod.rs
@@ -11,9 +11,11 @@ pub use refcell::*;
 mod mutex;
 #[cfg(feature = "std")]
 pub use mutex::*;
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 mod atomic;
 mod critical_section;
 mod shared;
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 pub use atomic::*;
 
 #[cfg(feature = "alloc")]
diff --git a/embedded-hal-bus/src/util.rs b/embedded-hal-bus/src/util.rs
index 739f4b1b..bb16577c 100644
--- a/embedded-hal-bus/src/util.rs
+++ b/embedded-hal-bus/src/util.rs
@@ -1,25 +1,34 @@
 //! Utilities shared by all bus types.
 
+#[allow(unused_imports)]
 use core::cell::UnsafeCell;
 
+#[cfg(not(feature = "portable-atomic"))]
+use core::sync::atomic::AtomicBool;
+#[cfg(feature = "portable-atomic")]
+use portable_atomic::AtomicBool;
+
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 /// Cell type used by [`spi::AtomicDevice`](crate::spi::AtomicDevice) and [`i2c::AtomicDevice`](crate::i2c::AtomicDevice).
 ///
 /// To use `AtomicDevice`, you must wrap the bus with this struct, and then
 /// construct multiple `AtomicDevice` instances with references to it.
 pub struct AtomicCell<BUS> {
     pub(crate) bus: UnsafeCell<BUS>,
-    pub(crate) busy: portable_atomic::AtomicBool,
+    pub(crate) busy: AtomicBool,
 }
-
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 unsafe impl<BUS: Send> Send for AtomicCell<BUS> {}
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 unsafe impl<BUS: Send> Sync for AtomicCell<BUS> {}
 
+#[cfg(any(feature = "portable-atomic", target_has_atomic = "8"))]
 impl<BUS> AtomicCell<BUS> {
     /// Create a new `AtomicCell`
     pub fn new(bus: BUS) -> Self {
         Self {
             bus: UnsafeCell::new(bus),
-            busy: portable_atomic::AtomicBool::from(false),
+            busy: AtomicBool::from(false),
         }
     }
 }