In almost all cases, making variables const when possible is a Good Thing (tm) as it expresses intent and reduces the chance of misuse.
When passing arguments however, there is a caveat.
passing a pointer or reference to a const resource is sensible and correct:
void foo(const char* text);    
void foo(const std::string& text);
But when passing an actual copy as an argument, making it const has a number of drawbacks. Consider:
std::string sorted(const std::string source)
{
    // I must copy source again because it's immutable
    auto result = source; // redundant copy
    std::sort(std::begin(result), std::end(result));
    return result;
}
whereas passing a mutable argument allows the function to use it more efficiently:
std::string sorted(std::string source)
{
    // lots of opportunity for copy elision and RVO here.
    std::sort(std::begin(source), std::end(source));
    return source;
}
To address the specific question of whether this is good form:
void foo(const char* const text);
The answer is a qualified, "NO" because:
- the second const provides no guarantees to anyone. The called function could simply copy the pointer - textand modify the copy.
 
- It clutters the API with another word, while adding no value. 
BUT There is a counter-argument that the second const is not there for the benefit of the caller, but for the implementor of foo().
In this case, it provides him with a safe const pointer to const data which he can use without accidentally changing.
The counter-counter argument to that is that all this does is leak implementation details through the interface.