This is an automated email from Gerrit.

Anonymous Coward ([email protected]) just uploaded a new patch set 
to Gerrit, which you can find at http://openocd.zylin.com/4671

-- gerrit

commit d75d978ba4f3638e0c46f398fb86513578163044
Author: Kai Geissdoerfer <[email protected]>
Date:   Wed Aug 15 11:35:36 2018 +0000

    jtag/drivers: support for am335x memory-mapped gpio interface
    
    Change-Id: I01a0c4b7789ce42b6b713dc39adcfb2e93b325fb
    Signed-off-by: Kai Geissdoerfer <[email protected]>

diff --git a/README b/README
index 985e39a..587819d 100644
--- a/README
+++ b/README
@@ -111,7 +111,7 @@ OpenJTAG, Openmoko, OpenRD, OSBDM, Presto, Redbee, RLink, 
SheevaPlug
 devkit, Stellaris evkits, ST-LINK (SWO tracing supported),
 STM32-PerformanceStick, STR9-comStick, sysfsgpio, TUMPA, Turtelizer,
 ULINK, USB-A9260, USB-Blaster, USB-JTAG, USBprog, VPACLink, VSLLink,
-Wiggler, XDS100v2, Xverve.
+Wiggler, XDS100v2, Xverve, AM335X.
 
 Debug targets
 -------------
diff --git a/configure.ac b/configure.ac
index d4338df..447c2ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -300,6 +300,11 @@ AS_CASE(["${host_cpu}"],
     AC_ARG_ENABLE([bcm2835gpio],
       AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for 
bitbanging on BCM2835 (as found in Raspberry Pi)]),
       [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no])
+
+    AC_ARG_ENABLE([am335x_gpio],
+      AS_HELP_STRING([--enable-am335x_gpio], [Enable building support for 
bitbanging on AM335X (as found in BeagleBone)]),
+      [build_am335x_gpio=$enableval], [build_am335x_gpio=no])
+
     AC_ARG_ENABLE([imx_gpio],
       AS_HELP_STRING([--enable-imx_gpio], [Enable building support for 
bitbanging on NXP IMX processors]),
       [build_imx_gpio=$enableval], [build_imx_gpio=no])
@@ -308,6 +313,7 @@ AS_CASE(["${host_cpu}"],
     build_ep93xx=no
     build_at91rm9200=no
     build_bcm2835gpio=no
+    build_am335x_gpio=no
     build_imx_gpio=no
 ])
 
@@ -522,6 +528,13 @@ AS_IF([test "x$build_bcm2835gpio" = "xyes"], [
   AC_DEFINE([BUILD_BCM2835GPIO], [0], [0 if you don't want bcm2835gpio.])
 ])
 
+AS_IF([test "x$build_am335x_gpio" = "xyes"], [
+  build_bitbang=yes
+  AC_DEFINE([BUILD_AM335X_GPIO], [1], [1 if you want am335x_gpio.])
+], [
+  AC_DEFINE([BUILD_AM335X_GPIO], [0], [0 if you don't want am335x_gpio.])
+])
+
 AS_IF([test "x$build_imx_gpio" = "xyes"], [
   build_bitbang=yes
   AC_DEFINE([BUILD_IMX_GPIO], [1], [1 if you want imx_gpio.])
@@ -702,6 +715,7 @@ AM_CONDITIONAL([ZY1000_MASTER], [test 
"x$build_zy1000_master" = "xyes"])
 AM_CONDITIONAL([IOUTIL], [test "x$build_ioutil" = "xyes"])
 AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"])
 AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"])
+AM_CONDITIONAL([AM335X_GPIO], [test "x$build_am335x_gpio" = "xyes"])
 AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"])
 AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"])
 AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes" -o 
"x$build_jtag_vpi" = "xyes"])
diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am
index ccef018..5313ef1 100644
--- a/src/jtag/drivers/Makefile.am
+++ b/src/jtag/drivers/Makefile.am
@@ -147,6 +147,9 @@ endif
 if BCM2835GPIO
 DRIVERFILES += %D%/bcm2835gpio.c
 endif
+if AM335X_GPIO
+DRIVERFILES += %D%/am335x_gpio.c
+endif
 if OPENJTAG
 DRIVERFILES += %D%/openjtag.c
 endif
@@ -181,4 +184,3 @@ DRIVERHEADERS = \
        %D%/versaloon/versaloon.h \
        %D%/versaloon/versaloon_include.h \
        %D%/versaloon/versaloon_internal.h
-
diff --git a/src/jtag/drivers/am335x_gpio.c b/src/jtag/drivers/am335x_gpio.c
new file mode 100644
index 0000000..b99b61d
--- /dev/null
+++ b/src/jtag/drivers/am335x_gpio.c
@@ -0,0 +1,641 @@
+/***************************************************************************
+ *   Copyright (C) 2018                                                    *
+ *   by Kai Geissdoerfer, [email protected]                   *
+ *                                                                         *
+ *   Based on bcm2835gpio.c and imx_gpio                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <jtag/interface.h>
+#include "bitbang.h"
+
+#include <sys/mman.h>
+
+/* Clock manager for enabling clock for GPIO banks */
+#define AM335X_CM_PER_START_ADDR 0x44E00000
+#define AM335X_CM_PER_REGS_SIZE 250
+
+struct am335x_cm_per_regs {
+       char unused[172];
+       /* One register to control clock of each GPIO1, GPIO2, GPIO3 */
+       uint32_t gpio_clkctrl[3];
+} __attribute__((packed, aligned(4)));
+
+#define AM335X_GPIO_BANKS_COUNT 4
+#define AM335X_GPIO_REGS_SIZE 2000
+
+/* Each GPIO bank appears as its own peripheral in non-contiguous memory */
+uint32_t gpio_bank_start_addr[] = {
+       /* GPIO0 start address */
+       0x44e07000,
+       /* GPIO1 start address */
+       0x4804C000,
+       /* GPIO2 start address */
+       0x481AC000,
+       /* GPIO3 start address */
+       0x481AE000
+};
+
+struct am335x_gpio_regs {
+       char unused[308];
+       /* output enable register*/
+       uint32_t oe;
+       uint32_t datain;
+       uint32_t dataout;
+} __attribute__((packed, aligned(4)));
+
+static volatile struct am335x_gpio_regs *gpio_base[4];
+static volatile struct am335x_cm_per_regs *cm_per_base;
+static int fd_mem;
+
+/* GPIO numbers for each signal. Negative values are invalid */
+static int tck_gpio = -1;
+static int tck_gpio_mode;
+static int tms_gpio = -1;
+static int tms_gpio_mode;
+static int tdi_gpio = -1;
+static int tdi_gpio_mode;
+static int tdo_gpio = -1;
+static int tdo_gpio_mode;
+static int trst_gpio = -1;
+static int trst_gpio_mode;
+static int srst_gpio = -1;
+static int srst_gpio_mode;
+static int swclk_gpio = -1;
+static int swclk_gpio_mode;
+static int swdio_gpio = -1;
+static int swdio_gpio_mode;
+
+/* For storing GPIO clock enabled status */
+static int gpio_cm_per_enabled[AM335X_GPIO_BANKS_COUNT];
+
+enum PIN_MODE {OUTPUT = 0, INPUT = 1};
+enum PIN_VALUE {LOW = 0, HIGH = 1};
+
+/*
+ * Note: GPIO number can be mapped to bank and pin with division/modulo
+ * E.g. GPIO 41 is on GPIO0 (41/32) pin 9 (41%32)
+*/
+static inline void gpio_write(int gpio_num, int value)
+{
+       if (value)
+               gpio_base[gpio_num / 32]->dataout |= (1U << (gpio_num % 32));
+       else
+               gpio_base[gpio_num / 32]->dataout &= ~(1U << (gpio_num % 32));
+}
+
+static inline void gpio_mode_set(int gpio_num, int mode)
+{
+       unsigned int bank = gpio_num / 32;
+       unsigned int idx = gpio_num % 32;
+       gpio_base[bank]->oe = (gpio_base[bank]->oe & ~(1U << idx)) | (mode << 
idx);
+}
+
+static inline int gpio_mode_get(int gpio_num)
+{
+
+       return (gpio_base[gpio_num / 32]->oe >> (gpio_num % 32)) & 1U;
+}
+
+static inline int gpio_read(int gpio_num)
+{
+       return (gpio_base[gpio_num / 32]->datain >> (gpio_num % 32)) & 1U;
+}
+
+int setup_mmap_gpio(int gpio_num)
+{
+
+       unsigned int gpio_bank = gpio_num / 32;
+       LOG_DEBUG("Initializing GPIO #%d", gpio_num);
+       if (!gpio_base[gpio_bank]) {
+               LOG_DEBUG("Mapping GPIO bank #%u", gpio_bank);
+               gpio_base[gpio_bank] = mmap(0, AM335X_GPIO_REGS_SIZE, PROT_READ 
| PROT_WRITE,
+                       MAP_SHARED, fd_mem, gpio_bank_start_addr[gpio_bank]);
+               if (gpio_base[gpio_bank] == MAP_FAILED)
+                       return -1;
+
+               /* Clock for GPIO1-3 has to be enabled manually */
+               if (gpio_bank != 0) {
+                       LOG_DEBUG("Enabling clock for GPIO bank #%u", 
gpio_bank);
+                       /* Backup state */
+                       gpio_cm_per_enabled[gpio_bank] = 
cm_per_base->gpio_clkctrl[gpio_bank] & (1 << 1);
+                       cm_per_base->gpio_clkctrl[gpio_bank] |= (1 << 1);
+               }
+       }
+
+       return ERROR_OK;
+
+}
+
+static void release_gpio_banks(void)
+{
+       unsigned int gpio_bank;
+       for (gpio_bank = 0; gpio_bank < AM335X_GPIO_BANKS_COUNT; gpio_bank++) {
+               if (gpio_base[gpio_bank]) {
+                       munmap((void *) gpio_base[gpio_bank], 
AM335X_GPIO_REGS_SIZE);
+
+                       /* Restore clock state for GPIO1-3 */
+                       if (gpio_bank != 0) {
+                               uint32_t state = 
cm_per_base->gpio_clkctrl[gpio_bank] & ~(1 << 1);
+                               state |= gpio_cm_per_enabled[gpio_bank];
+                               cm_per_base->gpio_clkctrl[gpio_bank] = state;
+                       }
+               }
+       }
+       munmap((void *) cm_per_base, AM335X_CM_PER_REGS_SIZE);
+
+       close(fd_mem);
+}
+
+/*
+ * Helper func to determine if gpio number valid
+ *
+ */
+static int is_gpio_valid(int gpio)
+{
+       return gpio >= 0 && gpio < (32 * AM335X_GPIO_BANKS_COUNT);
+}
+
+static bb_value_t am335x_gpio_read(void);
+static int am335x_gpio_write(int tck, int tms, int tdi);
+static int am335x_gpio_reset(int trst, int srst);
+
+static int am335x_gpio_swdio_read(void);
+static void am335x_gpio_swdio_drive(bool is_output);
+
+static int am335x_gpio_init(void);
+static int am335x_gpio_quit(void);
+
+static struct bitbang_interface am335x_gpio_bitbang = {
+       .read = am335x_gpio_read,
+       .write = am335x_gpio_write,
+       .reset = am335x_gpio_reset,
+       .swdio_read = am335x_gpio_swdio_read,
+       .swdio_drive = am335x_gpio_swdio_drive,
+       .blink = NULL
+};
+
+/* Transition delay coefficients. Tuned for AM335X 1GHz. Adjusted
+ * experimentally for:10kHz, 100Khz, 500KHz. Measured mmap raw GPIO toggling
+ * speed on AM335X@1GHz: 1.4MHz.
+ */
+static int speed_coeff = 230000;
+static int speed_offset = 320;
+static unsigned int jtag_delay;
+
+static bb_value_t am335x_gpio_read(void)
+{
+       return gpio_read(tdo_gpio) ? BB_HIGH : BB_LOW;
+}
+
+static int am335x_gpio_write(int tck, int tms, int tdi)
+{
+       gpio_write(tms_gpio, tms);
+       gpio_write(tdi_gpio, tdi);
+       gpio_write(tck_gpio, tck);
+
+       for (unsigned int i = 0; i < jtag_delay; i++)
+               asm volatile ("");
+
+       return ERROR_OK;
+}
+
+static int am335x_gpio_swd_write(int tck, int tms, int tdi)
+{
+       gpio_write(swdio_gpio, tdi);
+       gpio_write(swclk_gpio, tck);
+
+       for (unsigned int i = 0; i < jtag_delay; i++)
+               asm volatile ("");
+
+       return ERROR_OK;
+}
+
+/* (1) assert or (0) deassert reset lines */
+static int am335x_gpio_reset(int trst, int srst)
+{
+       if (trst_gpio != -1)
+               gpio_write(trst_gpio, trst);
+
+       if (srst_gpio != -1)
+               gpio_write(srst_gpio, srst);
+
+       return ERROR_OK;
+}
+
+static void am335x_gpio_swdio_drive(bool is_output)
+{
+       gpio_mode_set(swdio_gpio, is_output ? OUTPUT : INPUT);
+}
+
+static int am335x_gpio_swdio_read(void)
+{
+       return gpio_read(swdio_gpio);
+}
+
+static int am335x_gpio_khz(int khz, int *jtag_speed)
+{
+       if (!khz) {
+               LOG_DEBUG("RCLK not supported");
+               return ERROR_FAIL;
+       }
+       *jtag_speed = speed_coeff/khz - speed_offset;
+       if (*jtag_speed < 0)
+               *jtag_speed = 0;
+       return ERROR_OK;
+}
+
+static int am335x_gpio_speed_div(int speed, int *khz)
+{
+       *khz = speed_coeff/(speed + speed_offset);
+       return ERROR_OK;
+}
+
+static int am335x_gpio_speed(int speed)
+{
+       jtag_delay = speed;
+       return ERROR_OK;
+}
+
+
+COMMAND_HANDLER(am335x_gpio_handle_jtag_gpionums)
+{
+       if (CMD_ARGC == 4) {
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
+       } else if (CMD_ARGC != 0) {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       command_print(CMD_CTX,
+                       "am335x_gpio GPIO config: tck = %d, tms = %d, tdi = %d, 
tdo = %d",
+                       tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_jtag_gpionum_tck)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio GPIO config: tck = %d", tck_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_jtag_gpionum_tms)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio GPIO config: tms = %d", tms_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_jtag_gpionum_tdo)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio GPIO config: tdo = %d", tdo_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_jtag_gpionum_tdi)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio GPIO config: tdi = %d", tdi_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_jtag_gpionum_srst)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio GPIO config: srst = %d", srst_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_jtag_gpionum_trst)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio GPIO config: trst = %d", trst_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_swd_gpionums)
+{
+       if (CMD_ARGC == 2) {
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
+       } else if (CMD_ARGC != 0) {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       command_print(CMD_CTX,
+                       "am335x_gpio GPIO nums: swclk = %d, swdio = %d",
+                       swclk_gpio, swdio_gpio);
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_swd_gpionum_swclk)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio num: swclk = %d", swclk_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_swd_gpionum_swdio)
+{
+       if (CMD_ARGC == 1)
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
+
+       command_print(CMD_CTX, "am335x_gpio num: swdio = %d", swdio_gpio);
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(am335x_gpio_handle_speed_coeffs)
+{
+       if (CMD_ARGC == 2) {
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
+       }
+       return ERROR_OK;
+}
+
+static const struct command_registration am335x_gpio_command_handlers[] = {
+       {
+               .name = "am335x_gpio_jtag_nums",
+               .handler = &am335x_gpio_handle_jtag_gpionums,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
+               .usage = "(tck tms tdi tdo)* ",
+       },
+       {
+               .name = "am335x_gpio_tck_num",
+               .handler = &am335x_gpio_handle_jtag_gpionum_tck,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tck.",
+       },
+       {
+               .name = "am335x_gpio_tms_num",
+               .handler = &am335x_gpio_handle_jtag_gpionum_tms,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tms.",
+       },
+       {
+               .name = "am335x_gpio_tdo_num",
+               .handler = &am335x_gpio_handle_jtag_gpionum_tdo,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tdo.",
+       },
+       {
+               .name = "am335x_gpio_tdi_num",
+               .handler = &am335x_gpio_handle_jtag_gpionum_tdi,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for tdi.",
+       },
+       {
+               .name = "am335x_gpio_swd_nums",
+               .handler = &am335x_gpio_handle_swd_gpionums,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio numbers for swclk, swdio. (in that order)",
+               .usage = "(swclk swdio)* ",
+       },
+       {
+               .name = "am335x_gpio_swclk_num",
+               .handler = &am335x_gpio_handle_swd_gpionum_swclk,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for swclk.",
+       },
+       {
+               .name = "am335x_gpio_swdio_num",
+               .handler = &am335x_gpio_handle_swd_gpionum_swdio,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for swdio.",
+       },
+       {
+               .name = "am335x_gpio_srst_num",
+               .handler = &am335x_gpio_handle_jtag_gpionum_srst,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for srst.",
+       },
+       {
+               .name = "am335x_gpio_trst_num",
+               .handler = &am335x_gpio_handle_jtag_gpionum_trst,
+               .mode = COMMAND_CONFIG,
+               .help = "gpio number for trst.",
+       },
+       {
+               .name = "am335x_gpio_speed_coeffs",
+               .handler = &am335x_gpio_handle_speed_coeffs,
+               .mode = COMMAND_CONFIG,
+               .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
+       },
+
+       COMMAND_REGISTRATION_DONE
+};
+
+static const char * const am335x_gpio_transports[] = { "jtag", "swd", NULL };
+
+struct jtag_interface am335x_gpio_interface = {
+       .name = "am335x_gpio",
+       .supported = DEBUG_CAP_TMS_SEQ,
+       .execute_queue = bitbang_execute_queue,
+       .transports = am335x_gpio_transports,
+       .swd = &bitbang_swd,
+       .speed = am335x_gpio_speed,
+       .khz = am335x_gpio_khz,
+       .speed_div = am335x_gpio_speed_div,
+       .commands = am335x_gpio_command_handlers,
+       .init = am335x_gpio_init,
+       .quit = am335x_gpio_quit,
+};
+
+static bool am335x_gpio_jtag_mode_possible(void)
+{
+       if (!is_gpio_valid(tck_gpio))
+               return 0;
+       if (!is_gpio_valid(tms_gpio))
+               return 0;
+       if (!is_gpio_valid(tdi_gpio))
+               return 0;
+       if (!is_gpio_valid(tdo_gpio))
+               return 0;
+       return 1;
+}
+
+static bool am335x_gpio_swd_mode_possible(void)
+{
+       if (!is_gpio_valid(swclk_gpio))
+               return 0;
+       if (!is_gpio_valid(swdio_gpio))
+               return 0;
+       return 1;
+}
+
+static int am335x_gpio_init(void)
+{
+       bitbang_interface = &am335x_gpio_bitbang;
+
+       LOG_INFO("am335x_gpio GPIO JTAG/SWD bitbang driver");
+
+       if (am335x_gpio_jtag_mode_possible()) {
+               if (am335x_gpio_swd_mode_possible())
+                       LOG_INFO("JTAG and SWD modes enabled");
+               else
+                       LOG_INFO("JTAG only mode enabled (specify swclk and 
swdio gpio to add SWD mode)");
+       } else if (am335x_gpio_swd_mode_possible()) {
+               LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo 
gpios to add JTAG mode)");
+       } else {
+               LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode 
and/or swclk and swdio gpio for SWD mode");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       fd_mem = open("/dev/mem", O_RDWR | O_SYNC);
+       if (fd_mem < 0) {
+               perror("open");
+               return ERROR_JTAG_INIT_FAILED;
+       }
+
+       /* Map Registers for Clock control of GPIO banks */
+       cm_per_base = mmap(0, AM335X_CM_PER_REGS_SIZE, PROT_READ | PROT_WRITE,
+               MAP_SHARED, fd_mem, AM335X_CM_PER_START_ADDR);
+       if (cm_per_base == MAP_FAILED) {
+               LOG_ERROR("Failed to mmap Clock Manager registers");
+               close(fd_mem);
+               return ERROR_JTAG_INIT_FAILED;
+       }
+       int ret;
+       /*
+        * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
+        * as outputs.  Drive TDI and TCK low, and TMS/TRST/SRST high.
+        */
+       if (am335x_gpio_jtag_mode_possible()) {
+
+               ret = setup_mmap_gpio(tdo_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               tdo_gpio_mode = gpio_mode_get(tdo_gpio);
+
+               ret = setup_mmap_gpio(tdi_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               tdi_gpio_mode = gpio_mode_get(tdi_gpio);
+
+               ret = setup_mmap_gpio(tck_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               tck_gpio_mode = gpio_mode_get(tck_gpio);
+
+               ret = setup_mmap_gpio(tms_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               tms_gpio_mode = gpio_mode_get(tms_gpio);
+
+               gpio_mode_set(tdo_gpio, INPUT);
+               gpio_mode_set(tdi_gpio, OUTPUT);
+               gpio_mode_set(tck_gpio, OUTPUT);
+               gpio_mode_set(tms_gpio, OUTPUT);
+
+               gpio_write(tdi_gpio, LOW);
+               gpio_write(tck_gpio, LOW);
+               gpio_write(tms_gpio, HIGH);
+
+       }
+       if (am335x_gpio_swd_mode_possible()) {
+               ret = setup_mmap_gpio(swclk_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               swclk_gpio_mode = gpio_mode_get(swclk_gpio);
+
+               ret = setup_mmap_gpio(swdio_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               swdio_gpio_mode = gpio_mode_get(swdio_gpio);
+
+               gpio_mode_set(swclk_gpio, OUTPUT);
+               gpio_mode_set(swdio_gpio, OUTPUT);
+
+               gpio_write(swdio_gpio, LOW);
+               gpio_write(swclk_gpio, LOW);
+       }
+       if (trst_gpio != -1) {
+               ret = setup_mmap_gpio(trst_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               trst_gpio_mode = gpio_mode_get(trst_gpio);
+               gpio_mode_set(trst_gpio, OUTPUT);
+               gpio_write(trst_gpio, HIGH);
+       }
+       if (srst_gpio != -1) {
+               ret = setup_mmap_gpio(srst_gpio);
+               if (ret != ERROR_OK)
+                       goto out_error;
+               srst_gpio_mode = gpio_mode_get(srst_gpio);
+               gpio_mode_set(srst_gpio, OUTPUT);
+               gpio_write(srst_gpio, HIGH);
+       }
+
+       LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
+                 "tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
+                 tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode);
+
+       if (swd_mode) {
+               am335x_gpio_bitbang.write = am335x_gpio_swd_write;
+               bitbang_switch_to_swd();
+       }
+
+       return ERROR_OK;
+out_error:
+       LOG_ERROR("Failed to setup a GPIO pin");
+       release_gpio_banks();
+       return ERROR_JTAG_INIT_FAILED;
+}
+
+static int am335x_gpio_quit(void)
+{
+       if (am335x_gpio_jtag_mode_possible()) {
+               gpio_mode_set(tdo_gpio, tdo_gpio_mode);
+               gpio_mode_set(tdi_gpio, tdi_gpio_mode);
+               gpio_mode_set(tck_gpio, tck_gpio_mode);
+               gpio_mode_set(tms_gpio, tms_gpio_mode);
+       }
+       if (am335x_gpio_swd_mode_possible()) {
+               gpio_mode_set(swclk_gpio, swclk_gpio_mode);
+               gpio_mode_set(swdio_gpio, swdio_gpio_mode);
+       }
+       if (trst_gpio != -1)
+               gpio_mode_set(trst_gpio, trst_gpio_mode);
+       if (srst_gpio != -1)
+               gpio_mode_set(srst_gpio, srst_gpio_mode);
+
+       release_gpio_banks();
+       return ERROR_OK;
+}
diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c
index 286a73a..c78d1ad 100644
--- a/src/jtag/interfaces.c
+++ b/src/jtag/interfaces.c
@@ -123,6 +123,9 @@ extern struct jtag_interface aice_interface;
 #if BUILD_BCM2835GPIO == 1
 extern struct jtag_interface bcm2835gpio_interface;
 #endif
+#if BUILD_AM335X_GPIO == 1
+extern struct jtag_interface am335x_gpio_interface;
+#endif
 #if BUILD_CMSIS_DAP == 1
 extern struct jtag_interface cmsis_dap_interface;
 #endif
@@ -228,6 +231,9 @@ struct jtag_interface *jtag_interfaces[] = {
 #if BUILD_BCM2835GPIO == 1
                &bcm2835gpio_interface,
 #endif
+#if BUILD_AM335X_GPIO == 1
+               &am335x_gpio_interface,
+#endif
 #if BUILD_CMSIS_DAP == 1
                &cmsis_dap_interface,
 #endif
diff --git a/tcl/interface/beaglebone.cfg b/tcl/interface/beaglebone.cfg
new file mode 100644
index 0000000..644cdc4
--- /dev/null
+++ b/tcl/interface/beaglebone.cfg
@@ -0,0 +1,31 @@
+# Config for using TI AM335X
+#
+# This is best used with a fast enough buffer but also
+# is suitable for direct connection if the target voltage
+# matches to host voltage and the cable is short enough.
+#
+#
+
+interface am335x_gpio
+
+# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET
+# These depend on system clock, calibrated for AM335X@1GHz
+# am335x_gpio_speed SPEED_COEFF SPEED_OFFSET
+am335x_gpio_speed_coeffs 230000 320
+
+# Each of the JTAG lines need a gpio number set: tck tms tdi tdo.
+# Example configuration:
+# am335x_gpio_jtag_nums 6 7 8 9
+
+# SWD interface pins: swclk swdio
+# Example configuration:
+am335x_gpio_swd_nums 70 71
+
+# am335x_gpio_trst_num 10
+# reset_config trst_only
+
+# am335x_gpio_srst_num 11
+# reset_config srst_only srst_push_pull
+
+# or if you have both connected,
+# reset_config trst_and_srst srst_push_pull

-- 


_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to