Here's a function, based on @itsjeyd's answer, that is robust to the edge case listed in the comment to that answer (that is, when you're on the last heading/subtree):

    (defun org-end-of-subtree ()
      (interactive)
      (let ((org-special-ctrl-a/e t))
        (if (condition-case nil
                (outline-forward-same-level 1)
              (error t))
            (progn
              (goto-char (point-max))
              (outline-back-to-heading))
          (outline-previous-visible-heading 1))
        (org-end-of-line 1)))