Toggle some bits and get a square
Ruby, 74 bytes



-&gt;n{(1..n).map{|x|a=(n^x*x).to_s 2;a.size&gt;Math.log2(n)?n:a.count(?1)}.min}


Try it online!

This simply generates the sequence \$\left[1^2, 2^2, \ldots, n^2\right]\$ (which is far more than enough), XORs it with \$n\$, and then takes either the number of 1s in its binary representation if the number of bits is less than or equal to \$\log_2n\$, or \$n\$ otherwise. It then takes the minimum number of bits flipped. Returning \$n\$ instead of the number of bits flipped when the highest bit flipped is greater than \$\log_2n\$ prevents these cases from being chosen as the minimum, as \$n\$ will always be greater than the number of bits it has.

Thanks to Piccolo for saving a byte.