What matters with volatile (and any other language construct, really, but volatile in particular) isn't what the people adding it to the Standard expected. It's whether the Standard states, explicitly or by implication, that it will work; what implementations do; and what the people writing those implementations expect.
Like const and restrict, volatile has been intended to be applied to pointers from the very start (that's always been its intended use: all the cv-quals are of limited use applied to non-pointer types). So saying that casting a normal pointer to volatile was not expected is unsupported by the facts. Of course they didn't expect tricks involving typeof(), because typeof() isn't in the Standard! So what matters is surely whether it works, and can be expected to continue to work, in compilers implementing typeof(). The answer to the first is, yes, it works, and if it stops working, well, the kernel hackers and compiler hackers do talk to each other, and it'll either be made to work again or another technique will be implemented to do the same thing (in which case ACCESS_ONCE() just becomes a compiler-version-specific macro).
But this doesn't strike me as something too terribly likely to break in future compiler versions. The precise semantics of volatile are distinctly underspecified, to be sure, but C11 atomic operations are specifically declared as taking objects of volatile-qualified type, and volatile's meaning as 'minimize optimizations applied to things manipulating anything of volatile type, do not duplicate, elide, move, fold, spindle or mutilate' is of long standing.