まとめです
1:"hoge"は変更不可な領域を指すポインタ
2:char s[] = "hoge"は変更可能な領域に静的に確保されたメモリに"hoge"を書きこんで先頭ポインタを返す
3:char s[]で定義したsは変更不可なため、アドレスを変更しようとする(s="fuga"とか)と怒られる
4:foo(char s[])は暗黙にfoo(char* s)と読み換えられる。したがってfoo("hoge")は変更不可能な領域を指すポインタ
 が渡されるため、内部で変更しようとすると怒られる
「変更不可」が2つの意味(内容の変更不可(リテラル)と、メモリアドレスの変更不可(左辺値))を持っていたために混乱したのかと思っています。