Skip to content

Commit cbb15d7

Browse files
qemu: honor GPIO pull-up/down on ESP32S3 inputs
Apply IOMUX pull states to input pins so default PULL_UP/PULL_DOWN values are reflected in GPIO_IN when pins are not driven. This prevents gpio's being initialized low (until their value is set) while actually configured as PULL_UP, for instance.
1 parent 4e47c5c commit cbb15d7

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

hw/gpio/esp32s3_gpio.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,12 +545,47 @@ static uint64_t esp32_iomux_read(void *opaque, hwaddr addr, unsigned int size) {
545545
return 0;
546546
}
547547

548+
static void esp32s3_apply_pull_state(ESP32S3GPIOState *s, int gpio)
549+
{
550+
if (gpio < 0 || gpio >= N_GPIOS) {
551+
return;
552+
}
553+
554+
bool output = false;
555+
if (gpio < 32) {
556+
output = (s->gpio_enable >> gpio) & 1;
557+
} else {
558+
output = (s->gpio_enable1 >> (gpio - 32)) & 1;
559+
}
560+
if (output) {
561+
return;
562+
}
563+
564+
uint32_t io_mux = s->iomux_regs[gpio + 1];
565+
bool pullup = FIELD_EX32(io_mux, IO_MUX, FUN_WPU);
566+
bool pulldown = FIELD_EX32(io_mux, IO_MUX, FUN_WPD);
567+
if (pullup == pulldown) {
568+
return;
569+
}
570+
571+
int val = pullup ? 1 : 0;
572+
if (gpio < 32) {
573+
s->gpio_in = (s->gpio_in & ~(1U << gpio)) | (val << gpio);
574+
} else {
575+
int n1 = gpio - 32;
576+
s->gpio_in1 = (s->gpio_in1 & ~(1U << n1)) | (val << n1);
577+
}
578+
}
579+
548580
static void esp32_iomux_write(void *opaque, hwaddr addr, uint64_t value,
549581
unsigned int size) {
550582
ESP32S3GPIOState *s = ESP32S3_GPIO(opaque);
551583
int n=addr/4;
552584
if(n<N_GPIOS+1) {
553585
s->iomux_regs[n]=value;
586+
if (n > 0) {
587+
esp32s3_apply_pull_state(s, n - 1);
588+
}
554589
}
555590
}
556591

@@ -886,6 +921,10 @@ static void ESP32S3_GPIO_write(void *opaque, hwaddr addr, uint64_t value,
886921
break;
887922
}
888923

924+
for (int i = 0; i < N_GPIOS; i++) {
925+
esp32s3_apply_pull_state(s, i);
926+
}
927+
889928
if (s->gpio_out != oldvalue) {
890929
uint32_t diff = (s->gpio_out ^ oldvalue);
891930
for (int i = 0; i < 32; i++) {
@@ -955,6 +994,9 @@ static void ESP32S3_GPIO_reset(Object *dev, ResetType type) {
955994
}
956995
s->iomux_regs[i+1]=v;
957996
}
997+
for (int i = 0; i < N_GPIOS; i++) {
998+
esp32s3_apply_pull_state(s, i);
999+
}
9581000
}
9591001

9601002
static void esp32_gpio_realize(DeviceState *dev, Error **errp) {

0 commit comments

Comments
 (0)