By MMIO semantics do you mean explicit load and store instructions? I’ve never felt that pointer reads or writes were lacking descriptiveness here. I would argue the only surprising thing is that they might be optimized out (which is what volatile prevents).
Volatile on a non pointer value is not for MMIO, though, that’s typically for concurrency like with interrupts.