Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:48

0001 /*
0002  * SPDX-License-Identifier: BSD-2-Clause
0003  *
0004  * Copyright (C) 2019 Chris Johns <chrisj@rtems.org>.  All rights reserved.
0005  * Copyright (C) 2015, Dutch & Dutch.  All rights reserved.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028 
0029 /*
0030  * This is a C version of the jbang code found in the jbang repo:
0031  *
0032  *   https://github.com/dutchanddutch/jbang.git
0033  *
0034  * Dutch & Dutch is 'zmatt' on the #beagle IRC channel. This work is all based
0035  * on zmatt's research and solution.
0036  *
0037  * Hardware Modification
0038  * ---------------------
0039  *
0040  * The TI designers did not bring the ARM signal DBGEN to a system control
0041  * register so software can not directly control it. The BBB has a pull down
0042  * resister (R25) on the TRSTn JTAG signal which means software cannot
0043  * reconfigure the TRSTn pin and control it. As a result software access to the
0044  * ARM's debug registers is locked out. You can access the registers if you
0045  * want too but hardware breakpoints and watchpoints are ignored. ARM uses
0046  * hardware breakpoints to single step instructions.
0047  *
0048  * You need to add at least one wire for this code to work and optionally a
0049  * second wire if you need to test this code to make sure it is working. The
0050  * wires are small and require a small amount of soldering and soldering skill.
0051  *
0052  * If you add the TDO link change 'has_tdo' to '1' to enable support. This
0053  * setting defaults to '0' to disable support.
0054  *
0055  * Steps:
0056  *
0057  *  1. Locate P2 on the bottom side of the board. It is the JTAG connector
0058  *     pads. If you look at the underside of the board with the SD card holder
0059  *     to the right the pads are top center left. There are 20 pads in two
0060  *     columns. The pads are numbered 1 at the top left then 2 top right, 3 is
0061  *     second top on the left, 4 is second top to the right, then the pin
0062  *     number increments as you move left then right down the pads.
0063  *
0064  *  2. Connect P2 to P5.
0065  *
0066  *  3. Optionally connect P7 to P13.
0067  *
0068  * The resulting wiring is:
0069  *
0070  *       1 ===  /--=== 2
0071  *       3 ===  |  === 4
0072  *       5 ===--/  === 6
0073  *       7 ===--\  === 8
0074  *       9 ===  |  === 10
0075  *      11 ===  |  === 12
0076  *      13 ===--/  === 14
0077  *      15 ===     === 16
0078  *      17 ===     === 18
0079  *      19 ===     === 20
0080  */
0081 
0082 #include <unistd.h>
0083 
0084 #include <rtems/bspIo.h>
0085 #include <rtems/debugger/rtems-debugger-bsp.h>
0086 
0087 #include "bspdebug.h"
0088 
0089 /*
0090  * Set to '1' to enable the traces.
0091  */
0092 #define trace     0
0093 #define trace_reg 0
0094 
0095 /*
0096  * TDO provided feedback for testing via EMU0.
0097  */
0098 #define has_tdo 0
0099 
0100 /*
0101  * Pins of interest.
0102  */
0103 #define AM335x_PIN_CONF_TMS   116
0104 #define AM335x_PIN_CONF_TDI   117
0105 #define AM335x_PIN_CONF_TDO   118
0106 #define AM335x_PIN_CONF_TCK   119
0107 #define AM335x_PIN_CONF_TRSTN 120
0108 #define AM335x_PIN_CONF_EMU0  121
0109 
0110 /*
0111  * Register base addresses.
0112  */
0113 #define AM335x_PRCM_CM_PER     (0x44E00000)
0114 #define AM335x_PRCM_WKUP       (AM335x_PRCM_CM_PER + 0x400)
0115 #define AM335x_CONTROL_MODULE  (0x44E10000)
0116 #define AM335x_CONF_PIN        (AM335x_CONTROL_MODULE + 0x800)
0117 #define AM335x_GPIO0           (0x44e07000)
0118 #define AM335x_GPIO1           (0x4804c000)
0119 #define AM335x_GPIO2           (0x481ac000)
0120 #define AM335x_GPIO3           (0x481ae000)
0121 #define AM335x_DEBUGSS_ETM     (0x4B140000)
0122 #define AM335x_DEBUGSS_DEBUG   (0x4B141000)
0123 #define AM335x_DEBUGSS_CTI     (0x4B142000)
0124 #define AM335x_DEBUGSS_ICE     (0x4B143000)
0125 #define AM335x_DEBUGSS_DRM     (0x4B160000)
0126 #define AM335x_DEBUGSS_ETB     (0x4B162000)
0127 
0128 /*
0129  * Power, Reset, Clock Management (PRCM)
0130  */
0131 #define AM335x_PRCM_CM_PER_GPIO3_CLKCTRL (0x0b4)
0132 #define AM335x_PRCM_WKUP_DEBUGSS_CLKCTRL (0x014)
0133 
0134 #define AM335x_PRCM_CM_MODULEMODE_MASK    (3)
0135 #define AM335x_PRCM_CM_MODULEMODE_DISABLE (0)
0136 #define AM335x_PRCM_CM_MODULEMODE_ENABLE  (2)
0137 #define AM335x_PRCM_CM_IDLEST_MASK        (3 << 16)
0138 #define AM335x_PRCM_CM_IDLEST_FUNC        (0 << 16)
0139 #define AM335x_PRCM_CM_IDLEST_TRANS       (1 << 16)
0140 #define AM335x_PRCM_CM_IDLEST_IDLE        (2 << 16)
0141 #define AM335x_PRCM_CM_IDLEST_DISABLED    (3 << 16)
0142 
0143 /*
0144  * Pin configurations.
0145  */
0146 #define AM335x_PIN_IN_OFFSET  (0x138)
0147 #define AM335x_PIN_SLEW_FAST  (0 << 6)
0148 #define AM335x_PIN_SLEW_SLOW  (1 << 6)
0149 #define AM335x_PIN_RX_DISABLE (0 << 5)
0150 #define AM335x_PIN_RX_ENABLE  (1 << 5)
0151 #define AM335x_PIN_PULL_DIS   (1 << 3)
0152 #define AM335x_PIN_PULL_EN    (0 << 3)
0153 #define AM335x_PIN_PULL_UP    ((1 << 4) | AM335x_PIN_PULL_EN)
0154 #define AM335x_PIN_PULL_DOWN  ((0 << 4) | AM335x_PIN_PULL_EN)
0155 
0156 /*
0157  * JTAG.
0158  */
0159 typedef enum {
0160   JTAG_RST,
0161   JTAG_COMMIT,
0162   JTAG_RUN,
0163   JTAG_DATA,
0164   JTAG_PAUSE
0165 } JTAG_STATE;
0166 
0167 #define AM335x_JTAG_MASK (0x0fffffff)
0168 #define AM335x_JTAG_ID   (0x0b94402f)
0169 
0170 /*
0171  * ICE Pick
0172  */
0173 #define AM335x_ICEPICK_IR_LEN         (6)
0174 #define AM335x_ICEPICK_IR_BYPASS      (0x3f) /* 0b11'1111 1 bit */
0175 #define AM335x_ICEPICK_IR_PUB_CONNECT (0x07) /* 0b00'0111 8-bit (3->4 bit indirect rw) */
0176 #define AM335x_ICEPICK_IR_ROUTER      (0x02) /* 0b00'0010 32-bit (7->24 bit indirect rw) */
0177 
0178 /*
0179  * DAP
0180  */
0181 #define AM335x_DAP_ID        (0x3ba00477)
0182 #define AM335x_DAP_IR_LEN    (4)
0183 #define AM335x_DAP_IR_ABORT  (0x08)  /* 0b'1000 */
0184 #define AM335x_DAP_IR_DPACC  (0x0a)  /* 0b'1010 */
0185 #define AM335x_DAP_IR_APACC  (0x0b)  /* 0b'1011 */
0186 #define AM335x_DAP_IR_IDCODE (0x0e)  /* 0b'1110 */
0187 
0188 /*
0189  *
0190  */
0191 #define AM335x_APB_DEBUG (0x80001000)
0192 
0193 /*
0194  * State of JTAG.
0195  */
0196 static JTAG_STATE jtag_state;
0197 
0198 /*
0199  * Initialisation of icepick registers.
0200  */
0201 static const uint32_t am335x_icepick_init_regs[2] = {
0202   0x60002000,  /* assert cortex-a8 DBGEN */
0203   0x2c002100,  /* link DAP into chain (takes effect at run) */
0204 };
0205 
0206 #define AM335x_ICEPICK_INIT_REGS \
0207   (sizeof(am335x_icepick_init_regs) / sizeof(am335x_icepick_init_regs[0]))
0208 
0209 /*
0210  * Low level trace.
0211  */
0212 static void dbg_printk(const char* format, ...) RTEMS_PRINTFLIKE(1, 2);
0213 
0214 static void
0215 dbg_printk(const char* format, ...)
0216 {
0217   va_list ap;
0218   va_start(ap, format);
0219   if (trace) {
0220     vprintk(format, ap);
0221   }
0222   va_end(ap);
0223 }
0224 
0225 static volatile uint32_t*
0226 arm_reg_addr(uint32_t base, uint32_t offset)
0227 {
0228   return (volatile uint32_t*) (base + offset);
0229 }
0230 
0231 static uint32_t
0232 arm_reg_read(uint32_t base, uint32_t offset)
0233 {
0234   volatile uint32_t* addr = arm_reg_addr(base, offset);
0235   uint32_t           val = *addr;
0236   if (trace_reg)
0237     printk("bbb: dbg: read: %08x -> %08x\n", (intptr_t) addr, val);
0238   return val;
0239 }
0240 
0241 static void
0242 arm_reg_write(uint32_t base, uint32_t offset, uint32_t val)
0243 {
0244   volatile uint32_t* addr = arm_reg_addr(base, offset);
0245   if (trace_reg)
0246     printk("bbb: dbg: read: %08x <- %08x\n", (intptr_t) addr, val);
0247   *addr = val;
0248 }
0249 
0250 static void
0251 arm_reg_set(uint32_t base, uint32_t offset, uint32_t mask, uint32_t val)
0252 {
0253   uint32_t rval = arm_reg_read(base, offset);
0254   rval &= ~mask;
0255   rval |= val;
0256   arm_reg_write(base, offset, rval);
0257 }
0258 
0259 static void
0260 am335x_pin_config(int pin, uint32_t setting)
0261 {
0262   arm_reg_write(AM335x_CONF_PIN, pin * sizeof(uint32_t), setting);
0263 }
0264 
0265 static void
0266 am335x_prcm_cm_enable(uint32_t clk)
0267 {
0268   arm_reg_set(AM335x_PRCM_CM_PER, clk,
0269               AM335x_PRCM_CM_MODULEMODE_MASK,
0270               AM335x_PRCM_CM_MODULEMODE_ENABLE);
0271 }
0272 
0273 static bool
0274 am335x_prcm_cm_ready(uint32_t clk)
0275 {
0276   uint32_t val = arm_reg_read(AM335x_PRCM_CM_PER, clk) & AM335x_PRCM_CM_IDLEST_MASK;
0277   return val == AM335x_PRCM_CM_IDLEST_FUNC;
0278 }
0279 
0280 static uint32_t
0281 bbb_sig_bank_addr(int pin)
0282 {
0283   static const uint32_t bank_addr[4] = {
0284     AM335x_GPIO0,
0285     AM335x_GPIO1,
0286     AM335x_GPIO2,
0287     AM335x_GPIO3
0288   };
0289   return bank_addr[(pin >> 5) & 3];
0290 }
0291 
0292 static void
0293 bbb_sig_set(int pin, int level)
0294 {
0295   uint32_t val = (0 | AM335x_PIN_PULL_UP| AM335x_PIN_SLEW_FAST |
0296                   ((level != 0) ? AM335x_PIN_RX_ENABLE : AM335x_PIN_RX_DISABLE));
0297   am335x_pin_config(pin, val);
0298 }
0299 
0300 static uint32_t
0301 bbb_sig_get(int pin)
0302 {
0303   uint32_t in = arm_reg_read(bbb_sig_bank_addr(pin), AM335x_PIN_IN_OFFSET);
0304   return (in >> (32 - (pin & 31))) & 1;
0305 }
0306 
0307 static void
0308 bbb_tdo_init(void)
0309 {
0310   if (has_tdo) {
0311     am335x_pin_config(AM335x_PIN_CONF_EMU0,
0312                       7 | AM335x_PIN_PULL_UP |
0313                       AM335x_PIN_RX_ENABLE | AM335x_PIN_SLEW_FAST);
0314     am335x_prcm_cm_enable(AM335x_PRCM_CM_PER_GPIO3_CLKCTRL);
0315     while (!am335x_prcm_cm_ready(AM335x_PRCM_CM_PER_GPIO3_CLKCTRL)) {}
0316   }
0317 }
0318 
0319 static uint32_t
0320 bbb_sig_tdo(void)
0321 {
0322   return has_tdo && bbb_sig_get(AM335x_PIN_CONF_EMU0) == 1 ? 1 : 0;
0323 }
0324 
0325 static void
0326 bbb_sig_trst(int level)
0327 {
0328   bbb_sig_set(AM335x_PIN_CONF_TRSTN, level);
0329 }
0330 
0331 static void
0332 bbb_sig_tck(int level)
0333 {
0334   bbb_sig_set(AM335x_PIN_CONF_TCK, level);
0335 }
0336 
0337 static void
0338 bbb_sig_tdi(int level)
0339 {
0340   bbb_sig_set(AM335x_PIN_CONF_TDI, level);
0341 }
0342 
0343 static void
0344 bbb_sig_tms(int level)
0345 {
0346   bbb_sig_set(AM335x_PIN_CONF_TMS, level);
0347 }
0348 
0349 static void
0350 bbb_nap(void)
0351 {
0352   volatile size_t count = 1000;
0353   while (count > 0)
0354     --count;
0355 }
0356 
0357 static void
0358 bbb_sig_tck_pulse(void)
0359 {
0360   bbb_nap();
0361   bbb_sig_tck(1);
0362   bbb_nap();
0363   bbb_sig_tck(0);
0364   bbb_nap();
0365 }
0366 
0367 static void
0368 bbb_jtag_cmd(size_t nbits, uint32_t data)
0369 {
0370   size_t b;
0371   for (b = 0; b < nbits; ++b, data >>= 1) {
0372     bbb_sig_tms(data & 1);
0373     bbb_sig_tck_pulse();
0374   }
0375 }
0376 
0377 static void
0378 bbb_hw_init(void)
0379 {
0380   dbg_printk("]] HW reset\n");
0381   /*
0382    * Set CM_WKUP_DEBUGSS_CLKCTRL bits[1:0] = 2h, explict enable (reset does
0383    * this so leave out).
0384    */
0385   am335x_prcm_cm_enable(AM335x_PRCM_WKUP_DEBUGSS_CLKCTRL);
0386   while (!am335x_prcm_cm_ready(AM335x_PRCM_WKUP_DEBUGSS_CLKCTRL)) {}
0387   bbb_tdo_init();
0388 }
0389 
0390 static void
0391 bbb_jtag_reset(void)
0392 {
0393   dbg_printk("]] JTAG reset\n");
0394   bbb_sig_trst(0);
0395   bbb_sig_tck(0);
0396   bbb_sig_tdi(1);
0397   bbb_jtag_cmd(7, 0x1f /* 0b1'1111 */);
0398 }
0399 
0400 static void
0401 bbb_jtag_commit(void)
0402 {
0403   if (jtag_state == JTAG_DATA) {
0404     dbg_printk("]] JTAG commit\n");
0405     bbb_jtag_cmd(2, 0x3 /* 0b11 */);
0406     jtag_state = JTAG_COMMIT;
0407   }
0408 }
0409 
0410 static void
0411 bbb_jtag_run(size_t ncycles)
0412 {
0413   dbg_printk("]] JTAG run: %zu\n", ncycles);
0414   bbb_jtag_commit();
0415   bbb_jtag_cmd(ncycles, 0);
0416   jtag_state = JTAG_RUN;
0417 }
0418 
0419 static uint32_t
0420 bbb_jtag_xfer(size_t nbits)
0421 {
0422   uint32_t in = 0;
0423   size_t   b;
0424   dbg_printk("]] JTAG xfer: %zu\n", nbits);
0425   for (b = 0; b < nbits; ++b) {
0426     bbb_sig_tck_pulse();
0427     in |= bbb_sig_tdo() << b;
0428   }
0429   dbg_printk("]] JTAG xfer: in: %08x\n", in);
0430   return in;
0431 }
0432 
0433 static uint32_t
0434 bbb_jtag_xfer_out(size_t nbits, uint32_t out)
0435 {
0436   uint32_t in = 0;
0437   size_t   b;
0438   dbg_printk("]] JTAG xfer out: %zu %08x\n", nbits, out);
0439   for (b = 0; b < nbits; ++b, out >>= 1) {
0440     bbb_sig_tck_pulse();
0441     bbb_sig_tdi(out & 1);
0442     in |= bbb_sig_tdo() << b;
0443   }
0444   dbg_printk("]] JTAG xfer out: in: %08x\n", in);
0445   return in;
0446 }
0447 
0448 static void
0449 bbb_jtag_dr(void)
0450 {
0451   dbg_printk("]] JTAG dr\n");
0452   bbb_jtag_commit();
0453   bbb_jtag_cmd(2, 0xb01);
0454   jtag_state = JTAG_DATA;
0455 }
0456 
0457 static uint32_t
0458 bbb_jtag_dr_out(size_t nbits, uint32_t out)
0459 {
0460   uint32_t in;
0461   dbg_printk("]] JTAG dr out\n");
0462   bbb_jtag_dr();
0463   in = bbb_jtag_xfer_out(nbits, out);
0464   bbb_jtag_commit();
0465   return in;
0466 }
0467 
0468 static void
0469 bbb_jtag_ir(void)
0470 {
0471   dbg_printk("]] JTAG ir\n");
0472   bbb_jtag_commit();
0473   bbb_jtag_cmd(3, 0x3 /* 0b011 */);
0474   jtag_state = JTAG_DATA;
0475 }
0476 
0477 static uint32_t
0478 bbb_jtag_ir_out(size_t nbits, uint32_t out)
0479 {
0480   uint32_t in;
0481   dbg_printk("]] JTAG ir out\n");
0482   bbb_jtag_ir();
0483   in = bbb_jtag_xfer_out(nbits, out);
0484   bbb_jtag_commit();
0485   return in;
0486 }
0487 
0488 static bool
0489 bbb_jtag_hw_init(void)
0490 {
0491   bool match = true;
0492   bbb_jtag_reset();
0493   bbb_sig_trst(1);
0494   bbb_jtag_run(100);
0495   if (has_tdo) {
0496     uint32_t id = bbb_jtag_dr_out(32, 0);
0497     match = (id & AM335x_JTAG_MASK) == AM335x_JTAG_ID;
0498     printk("bbb: dbg: JTAG Id: %08x (%s)\n",
0499            id, match ? "match" : "mismatch");
0500   }
0501   return match;
0502 }
0503 
0504 static bool
0505 bbb_icepick_init(void)
0506 {
0507   size_t r;
0508   bbb_jtag_ir_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_PUB_CONNECT);
0509   bbb_jtag_dr_out(8, 0x89 /* 0b'1000'1001 */);
0510   if (has_tdo && bbb_jtag_dr_out(8, 0) != 0x9 /* 0b1001 */) {
0511     printk("bbb: dbg: ICEPick connect failure\n");
0512     return false;
0513   }
0514   bbb_jtag_ir_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_ROUTER);
0515   for (r = 0; r < AM335x_ICEPICK_INIT_REGS; ++r) {
0516     uint32_t val = am335x_icepick_init_regs[r];
0517     bbb_jtag_dr_out(32, val | (1 << 31));
0518     if (has_tdo && ((bbb_jtag_dr_out(32, 0) >> 24) != (val >> 24))) {
0519       printk("bbb: dbg: ICEPick write failure\n");
0520       return false;
0521     }
0522   }
0523   bbb_jtag_ir_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_BYPASS);
0524   bbb_jtag_run(16);
0525   return true;
0526 }
0527 
0528 static void
0529 bbb_dap_ir(uint32_t reg)
0530 {
0531   static uint32_t last_ir = AM335x_DAP_IR_IDCODE;
0532   if (reg != last_ir) {
0533     last_ir = reg;
0534     bbb_jtag_ir();
0535     bbb_jtag_xfer_out(AM335x_DAP_IR_LEN, reg);
0536     bbb_jtag_xfer_out(AM335x_ICEPICK_IR_LEN, AM335x_ICEPICK_IR_BYPASS);
0537     bbb_jtag_commit();
0538   }
0539 }
0540 
0541 static uint32_t
0542 bbb_dap_op(uint32_t ir, uint32_t op, uint32_t arg)
0543 {
0544   uint32_t res;
0545   bbb_dap_ir(ir);
0546   bbb_jtag_dr();
0547   res = bbb_jtag_xfer_out(3, op);
0548   if (has_tdo && res != 0x2 /* 0b010 */) {
0549     printk("bbb: dbg: DAP status code: %08x\n", res);
0550   }
0551   res = bbb_jtag_xfer_out(32, arg);
0552   /*
0553    * ICEPick in bypass.
0554    */
0555   bbb_jtag_xfer(1);
0556   /*
0557    * No always needed, but it does not burt.
0558    */
0559   bbb_jtag_run(1);
0560   return res;
0561 }
0562 
0563 static uint32_t
0564 bbb_dap_csw(void)
0565 {
0566   return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x3 /* 0b011 */, 0);
0567 }
0568 
0569 static uint32_t
0570 bbb_dap_set_csw(uint32_t val)
0571 {
0572   return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x2 /* 0b010 */, val);
0573 }
0574 
0575 static uint32_t
0576 bbb_dap_set_sel(uint32_t val)
0577 {
0578   return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x4 /* 0b100 */, val);
0579 }
0580 
0581 static uint32_t
0582 bbb_dap_nop(void)
0583 {
0584   return bbb_dap_op(AM335x_DAP_IR_DPACC, 0x6 /* 0b110 */, 0);
0585 }
0586 
0587 static uint32_t
0588 bbb_ap_set_csw(uint32_t val)
0589 {
0590   return bbb_dap_op(AM335x_DAP_IR_APACC, 0x0 /* 0b000 */, val);
0591 }
0592 
0593 static uint32_t
0594 bbb_ap_set_addr(uint32_t val)
0595 {
0596   return bbb_dap_op(AM335x_DAP_IR_APACC, 0x2 /* 0b010 */, val);
0597 }
0598 
0599 static uint32_t
0600 bbb_ap_data(void)
0601 {
0602   return bbb_dap_op(AM335x_DAP_IR_APACC, 0x7 /* 0b111 */, 0);
0603 }
0604 
0605 static uint32_t
0606 bbb_ap_set_data(uint32_t val)
0607 {
0608   return bbb_dap_op(AM335x_DAP_IR_APACC, 0x6 /* 0b110 */, val);
0609 }
0610 
0611 static uint32_t
0612 bbb_dap_check(void)
0613 {
0614   uint32_t data = bbb_dap_csw();
0615   uint32_t csw = bbb_dap_nop();
0616   if (has_tdo && csw != 0xf0000000) {
0617     printk("bbb: dbg: DP-CSW unexpected value: %08x\n", csw);
0618   }
0619   return data;
0620 }
0621 
0622 static bool
0623 bbb_dap_init(void)
0624 {
0625   bool ok = true;
0626   if (has_tdo) {
0627     uint32_t id = bbb_jtag_dr_out(32, 0);
0628     ok = id == AM335x_DAP_ID;
0629     printk("bbb: dbg: DAP JTAG Id: %08x (%s)\n",
0630            id, ok ? "match" : "mismatch");
0631   }
0632   if (ok) {
0633     /*
0634      * Power up and clear errors.
0635      */
0636     bbb_dap_set_csw(0x50000032);
0637     bbb_dap_check();
0638     /*
0639      * Select and configure APB-AP.
0640      */
0641     bbb_dap_set_sel(1 << 24);
0642     bbb_ap_set_csw(0xe3000012);
0643   }
0644   return ok;
0645 }
0646 
0647 static uint32_t
0648 bbb_ap_read(uint32_t addr)
0649 {
0650   uint32_t data;
0651   bbb_ap_set_addr(addr);
0652   bbb_ap_data();
0653   data = bbb_dap_check();
0654   if (has_tdo) {
0655     dbg_printk("bbb: dbg: read 0x%08x -> 0x%08x\n", addr, data);
0656   }
0657   return data;
0658 }
0659 
0660 static uint32_t
0661 bbb_ap_write(uint32_t addr, uint32_t data)
0662 {
0663   bbb_ap_set_addr(addr);
0664   bbb_ap_set_data(data);
0665   return bbb_dap_check();
0666 }
0667 
0668 static void
0669 bbb_show_auth_status(uint32_t addr)
0670 {
0671   if (has_tdo) {
0672     const char* privs[] = {
0673       "public invasive debug",
0674       "public non-invasive debug",
0675       "secure invasive debug",
0676       "secure non-invasive debug",
0677     };
0678     uint32_t val = bbb_ap_read(addr + 0xfb8);
0679     size_t   s;
0680     printk("bbb: dbg: auth status: %08x\n", val);
0681     for (s = 0; s < (sizeof(privs) / sizeof(privs[0])); ++s, val >>= 2) {
0682       printk("bbb: dbg: %s: ", privs[s]);
0683       if ((val & 1) != 0)
0684         printk("granted");
0685       else if ((val & 2) != 0)
0686         printk("denied");
0687       printk("\n");
0688     }
0689   }
0690 }
0691 
0692 static uint32_t
0693 bbb_debug_rx(void)
0694 {
0695   /* debugger -> core */
0696   uint32_t data;
0697   asm volatile("mrc p14, 0, %0, c0, c5, 0" : "=r" (data));
0698   return data;
0699 }
0700 
0701 bool
0702 rtems_debugger_arm_debug_configure(void)
0703 {
0704   const uint32_t addr = (intptr_t) &rtems_debugger_arm_debug_configure;
0705   bbb_hw_init();
0706   if (!bbb_jtag_hw_init())
0707     return false;
0708   if (!bbb_icepick_init())
0709     return false;
0710   if (!bbb_dap_init())
0711     return false;
0712   bbb_show_auth_status(AM335x_APB_DEBUG);
0713   bbb_ap_read(AM335x_APB_DEBUG + 0x314);
0714   bbb_ap_read(AM335x_APB_DEBUG + 0x088);
0715   bbb_ap_write(AM335x_APB_DEBUG + 0x080, addr);
0716   usleep(1000);
0717   if (bbb_debug_rx() != addr) {
0718     printk("bbb: dbg: path test failure\n");
0719     return false;
0720   }
0721   return true;
0722 }
0723 
0724 void*
0725 bbb_arm_debug_registers(void)
0726 {
0727   return (void*) AM335x_DEBUGSS_DEBUG;
0728 }
0729 
0730 void*
0731 rtems_debugger_arm_debug_registers(void)
0732 {
0733   return bbb_arm_debug_registers();
0734 }