Toggle pin between SPI and GPIO

Hello,

On a project with a custom board with an nRF9160 and an external flash W25Q64, I noticed a strange power consumption behaviour.

When my system goes idle, the current is very slowly increasing then decreasing. We are talking a ramp up/down of ~100µA in ~20 seconds.

This is not some kind of noise, since I can replicate the issue every time. The fact that it's very slow makes me think of a current leak in a unused/undefined pin.

First, I noticed that the definition of wp-gpios and hold-gpios in the devicetree had no effect (at least, in my case). I therefore removed that, and setup those as GPIO high. This reduced the issue, but it's still here.

After that, I noticed that when the system goes idle, the current remain stable if I tied the SPI pins to ground, using a cable. How can I do that in software ?

Is there a way to change the pin definition at runtime, to toggle between SPI (SCK, MOSI, MISO) and GPIO low ? If so, how can I process.

So far, my dts is :

spi3_default: spi3_default {
	group1 {
		psels = <NRF_PSEL(SPIM_SCK, 0, 13)>,
				<NRF_PSEL(SPIM_MOSI, 0, 11)>,
				<NRF_PSEL(SPIM_MISO, 0, 12)>;
	};
};
spi3_sleep: spi3_sleep {		
	group1 {
		psels = <NRF_PSEL(SPIM_SCK, 0, 13)>,
				<NRF_PSEL(SPIM_MOSI, 0, 11)>,
				<NRF_PSEL(SPIM_MISO, 0, 12)>;
				low-power-enable;
	};

&spi3 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	pinctrl-0 = <&spi3_default>;
	pinctrl-1 = <&spi3_sleep>;
	pinctrl-names = "default", "sleep";
	
	cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;

	w25q64: w25q64jv@0
	{
		compatible =  "jedec,spi-nor" ;		
		
		reg = <0>;		
		
		spi-max-frequency = <1000000>;	// Max supported by NVM is 133MHz. But there is no reason to go too fast.
		size 		= <0x4000000> ;		// 64Mbits
		jedec-id 	= [EF 40 17];		// JEDEC ID is [MF 7-0]=0xEF [ID 15-8]= [ID 7-0 = Size]=		
		has-dpd;						// Enable the Deep Power Down management
		t-enter-dpd	= <3000>;
		t-exit-dpd 	= <3000>;
		};
};

I go idle like this:

static const struct device *flash_dev = DEVICE_DT_GET(DT_NODELABEL(w25q64));
const struct device *spi3_dev= DEVICE_DT_GET(DT_NODELABEL(spi3));

// Sends the 0xB9 command, to enter power down
pm_device_action_run(flash_dev, PM_DEVICE_ACTION_SUSPEND) ;
    
// Disable SPI peripheral
// If not done, it seems that there is a current leakage through MISO
pm_device_action_run(spi3_dev, PM_DEVICE_ACTION_SUSPEND) ;

Thanks.

Related