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>
This commit is contained in:
Maximilian Deubel 2024-06-24 16:50:42 +02:00 committed by Anas Nashif
parent 8746a2aa12
commit b0936ae353

View file

@ -568,29 +568,42 @@ static int sw_configure(const struct device *dev,
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_on(const struct device *dev)
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 @@ static int sw_gpio_init(const struct device *dev)
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;