drivers: dp: swdp_bitbang: power optimization
This patch changes GPIO initialization
to be in PORT_OFF state by default.
Also, if no transceiver is attached to the signals,
the GPIOs are configured to be disconnected to preserve power.
I tested this on a prototype board where we are going to have
a debugger in a low-power context.
Signed-off-by: Maximilian Deubel <maximilian.deubel@nordicsemi.no>
diff --git a/drivers/dp/swdp_bitbang.c b/drivers/dp/swdp_bitbang.c
index 3e0b6a2..a1d2838 100644
--- a/drivers/dp/swdp_bitbang.c
+++ b/drivers/dp/swdp_bitbang.c
@@ -568,29 +568,42 @@
static int sw_port_on(const struct device *dev)
{
const struct sw_config *config = dev->config;
-
- gpio_pin_set_dt(&config->clk, 1);
+ int ret;
if (config->dnoe.port) {
- gpio_pin_set_dt(&config->dnoe, 1);
- }
-
- if (config->dout.port) {
- gpio_pin_set_dt(&config->dout, 1);
- } else {
- int ret;
-
- ret = gpio_pin_configure_dt(&config->dio, GPIO_OUTPUT_ACTIVE);
+ ret = gpio_pin_configure_dt(&config->dnoe, GPIO_OUTPUT_ACTIVE);
if (ret) {
return ret;
}
}
- if (config->noe.port) {
- gpio_pin_set_dt(&config->noe, 1);
+ if (config->dout.port) {
+ ret = gpio_pin_configure_dt(&config->dout, GPIO_OUTPUT_ACTIVE);
+ if (ret) {
+ return ret;
+ }
}
- if (config->reset.port) {
- gpio_pin_set_dt(&config->reset, 1);
+
+ ret = gpio_pin_configure_dt(&config->dio, GPIO_INPUT);
+ if (ret) {
+ return ret;
+ }
+
+ if (config->noe.port) {
+ ret = gpio_pin_configure_dt(&config->noe, GPIO_OUTPUT_ACTIVE);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ ret = gpio_pin_configure_dt(&config->clk, GPIO_OUTPUT_ACTIVE);
+ if (ret) {
+ return ret;
+ }
+
+ ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_ACTIVE);
+ if (ret) {
+ return ret;
}
return 0;
@@ -599,27 +612,64 @@
static int sw_port_off(const struct device *dev)
{
const struct sw_config *config = dev->config;
+ int ret;
+ /* If there is a transceiver connected to IO, pins should always be driven. */
if (config->dnoe.port) {
- gpio_pin_set_dt(&config->dnoe, 0);
- }
+ ret = gpio_pin_configure_dt(&config->dnoe, GPIO_OUTPUT_INACTIVE);
+ if (ret) {
+ return ret;
+ }
- if (config->dout.port) {
- gpio_pin_set_dt(&config->dout, 0);
- } else {
- int ret;
+ if (config->dout.port) {
+ ret = gpio_pin_configure_dt(&config->dout, GPIO_OUTPUT_ACTIVE);
+ if (ret) {
+ return ret;
+ }
+ }
ret = gpio_pin_configure_dt(&config->dio, GPIO_INPUT);
if (ret) {
return ret;
}
+ } else {
+ if (config->dout.port) {
+ ret = gpio_pin_configure_dt(&config->dout, GPIO_DISCONNECTED);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ ret = gpio_pin_configure_dt(&config->dio, GPIO_DISCONNECTED);
+ if (ret) {
+ return ret;
+ }
}
+ /* If there is a transceiver connected to CLK, pins should always be driven. */
if (config->noe.port) {
- gpio_pin_set_dt(&config->noe, 0);
+ ret = gpio_pin_configure_dt(&config->noe, GPIO_OUTPUT_INACTIVE);
+ if (ret) {
+ return ret;
+ }
+
+ ret = gpio_pin_configure_dt(&config->clk, GPIO_OUTPUT_ACTIVE);
+ if (ret) {
+ return ret;
+ }
+
+ } else {
+ ret = gpio_pin_configure_dt(&config->clk, GPIO_DISCONNECTED);
+ if (ret) {
+ return ret;
+ }
}
+
if (config->reset.port) {
- gpio_pin_set_dt(&config->reset, 1);
+ ret = gpio_pin_configure_dt(&config->reset, GPIO_DISCONNECTED);
+ if (ret) {
+ return ret;
+ }
}
return 0;
@@ -631,44 +681,12 @@
struct sw_cfg_data *sw_data = dev->data;
int ret;
- ret = gpio_pin_configure_dt(&config->clk, GPIO_OUTPUT_ACTIVE);
+ /* start with the port turned off */
+ ret = sw_port_off(dev);
if (ret) {
return ret;
}
- ret = gpio_pin_configure_dt(&config->dio, GPIO_INPUT);
- if (ret) {
- return ret;
- }
-
- if (config->dout.port) {
- ret = gpio_pin_configure_dt(&config->dout, GPIO_OUTPUT_ACTIVE);
- if (ret) {
- return ret;
- }
- }
-
- if (config->dnoe.port) {
- ret = gpio_pin_configure_dt(&config->dnoe, GPIO_OUTPUT_INACTIVE);
- if (ret) {
- return ret;
- }
- }
-
- if (config->noe.port) {
- ret = gpio_pin_configure_dt(&config->noe, GPIO_OUTPUT_INACTIVE);
- if (ret) {
- return ret;
- }
- }
-
- if (config->reset.port) {
- ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_ACTIVE);
- if (ret) {
- return ret;
- }
- }
-
sw_data->turnaround = 1U;
sw_data->data_phase = false;
sw_data->fast_clock = false;