You are misunderstanding the strict aliasing rule.
That rule is not only about types. It's about semantics too. Aliasing through a void * cast to some other pointer type is perfectly fine as long as there is an object of the appropriate type. (Else void * would not be useful.)
E. g.,
uint32_t reg = 1337;
void *ptr = ®
*(uint32_t *)ptr = 42;
is OK, because ptr does contain the address of an uint32_t object; it's just that it has a different type.
So, the following piece of code:
uint32_t *regs = mmap(0xf00ba12, ...);
regs[0] = 0xffffffff;
may or may not violate the strict aliasing rule, depending on whether the register at address 0xf00ba12 is of type uint32_t. Thus, in your case, this is valid.
The strict aliasing rule concerns programmers who try to cheat by working around the type system and accessing an object through an lvalue of a different type. That of course involves casting pointers, but it's not the act of casting and dereferencing pointers that violates strict aliasing, but the fact that there's no object of the given type at the referencing address.
And please do not use -fno-strict-aliasing!