You can’t change a smart contract after it is deployed. That’s the whole point of the smart contract computing paradigm.
If you want to render your smart contract unusable, you’ll have to add the code to do so yourself. For example, you could add a persistent variable in your contract that acts as a global “off switch” for all of your contract’s public functions.
Insofar as upgrades, the recommended way to upgrade a smart contract is to deploy a new version of the smart contract, and seamlessly read state from the prior version of the contract via the
(at-block ...) built-in function. You would need to update any other software that interacts with the smart contract to use the latest version. To make this seamless, you could write a separate smart contract that stores the contract address of the latest version, which your off-chain app inspects in order to determine which version of the smart contract to use. You’d set up this “lookup” contract so that only you, the developer could set the contract address version for the app to use.