From c164906420521546849d03a26977fb91838aca8e Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 15 Nov 2022 09:47:43 +0100 Subject: [PATCH] jtag/drivers/bcm2835gpio: don't touch pad setting on /dev/gpiomem The pads were configured at a wrong memory address if /dev/gpiomem was mapped. The pad setting registers are not accessible in mapped /dev/gpiomem, disable the pads setting if the driver doesn't open /dev/mem. While on it, do not fail the driver initialization if pad mapping fails - just emit a warning and work with unchanged pad setting. Signed-off-by: Tomas Vanek Change-Id: I0bce76cade8f7efd75efd9087a7d9ba6511a6239 Reviewed-on: https://review.openocd.org/c/openocd/+/7684 Tested-by: jenkins Reviewed-by: Jonathan Bell Reviewed-by: Antonio Borneo --- doc/openocd.texi | 6 +++++- src/jtag/drivers/bcm2835gpio.c | 34 +++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index f32ef3475..f27e17cea 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3292,8 +3292,12 @@ configuration on exit. GPIO numbers >= 32 can't be used for performance reasons. GPIO configuration is handled by the generic command @ref{adapter gpio, @command{adapter gpio}}. +/dev/gpiomem is preferred for GPIO mapping with fallback to /dev/mem. +If /dev/mem is used GPIO 0-27 pads are set to the limited +slew rate and drive strength is reduced to 4 mA (2 mA on RPi 4). + See @file{interface/raspberrypi-native.cfg} for a sample config and -pinout. +@file{interface/raspberrypi-gpio-connector.cfg} for pinout. @deffn {Config Command} {bcm2835gpio speed_coeffs} @var{speed_coeff} @var{speed_offset} Set SPEED_COEFF and SPEED_OFFSET for delay calculations. If unspecified, diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 879ca3c84..16c76cdb8 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -409,10 +409,13 @@ static int bcm2835gpio_init(void) return ERROR_JTAG_INIT_FAILED; } + bool pad_mapping_possible = false; + dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC); if (dev_mem_fd < 0) { LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem"); dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); + pad_mapping_possible = true; } if (dev_mem_fd < 0) { LOG_ERROR("open: %s", strerror(errno)); @@ -428,21 +431,28 @@ static int bcm2835gpio_init(void) return ERROR_JTAG_INIT_FAILED; } - pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, + /* TODO: move pads config to a separate utility */ + if (pad_mapping_possible) { + pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, BCM2835_PADS_GPIO_0_27); - if (pads_base == MAP_FAILED) { - LOG_ERROR("mmap: %s", strerror(errno)); - bcm2835gpio_munmap(); - close(dev_mem_fd); - return ERROR_JTAG_INIT_FAILED; + if (pads_base == MAP_FAILED) { + LOG_ERROR("mmap pads: %s", strerror(errno)); + LOG_WARNING("Continuing with unchanged GPIO pad settings (drive strength and slew rate)"); + } + } else { + pads_base = MAP_FAILED; } close(dev_mem_fd); - /* set 4mA drive strength, slew rate limited, hysteresis on */ - initial_drive_strength_etc = pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] & 0x1f; - pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1; + if (pads_base != MAP_FAILED) { + /* set 4mA drive strength, slew rate limited, hysteresis on */ + initial_drive_strength_etc = pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] & 0x1f; +LOG_INFO("initial pads conf %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]); + pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1; +LOG_INFO("pads conf set to %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]); + } /* Configure JTAG/SWD signals. Default directions and initial states are handled * by adapter.c and "adapter gpio" command. @@ -513,8 +523,10 @@ static int bcm2835gpio_quit(void) restore_gpio(ADAPTER_GPIO_IDX_SRST); restore_gpio(ADAPTER_GPIO_IDX_LED); - /* Restore drive strength. MSB is password ("5A") */ - pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5A000000 | initial_drive_strength_etc; + if (pads_base != MAP_FAILED) { + /* Restore drive strength. MSB is password ("5A") */ + pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5A000000 | initial_drive_strength_etc; + } bcm2835gpio_munmap(); return ERROR_OK; -- 2.11.4.GIT