I agree. Non-DT platforms have always used the callbacks to execute this
kind of code. As you've said before there are situations where it isn't
just about setting a GPIO or enabling a regulator but it also requires a
specific timing. Representing this in the platform data would become
tedious.
So I think for the DT case you can parse the power-on and power-off
sequences directly and execute code based on it, while in non-DT cases
the init and exit callbacks should be used instead. I think it even
makes sense to reuse the platform data's init and exit functions in the
DT case and implement the parser/interpreter within those.
I case where the regulator comes from a DT it should assume that it will
become available at some point, so -EPROBE_DEFER is correct. However if
the DT doesn't even contain the power-supply property, then EPROBE_DEFER
will never work because there's no regulator to become available.