/* * Motorola Background Debug Mode Driver * Copyright (C) 1995 W. Eric Norum * Copyright (C) 1998-2008 Chris Johns * * 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * W. Eric Norum * Saskatchewan Accelerator Laboratory * University of Saskatchewan * 107 North Road * Saskatoon, Saskatchewan, CANADA * S7N 5C6 * * eric@skatter.usask.ca * * Coldfire support by: * Chris Johns * chris@contemporary.net.au */ /* * Coldfire P&E Interface. * * Parallel port bit assignments * * Data register * +---+---+---+---+---+---+---+---+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * +---+---+---+---+---+---+---+---+ * | | | | | | | | * | | | | | | | +--- Serial data to target * | | | | | | | Write 0 - Send `0' to target * | | | | | | | Write 1 - Send `1' to target * | | | | | | | * | | | | | | +------- Serial Data clock * | | | | | | 0 = clock low * | | | | | | 1 = clock high * | | | | | | * | | | | | +----------- Target Breakpoint * | | | | | 0 = brkp active (low) * | | | | | 1 = brkp negated (high) * | | | | | * | | | | +--------------- Target Reset * | | | | 0 = reset active (low) * | | | | 1 = reset negated (target active) * | | | | * | | | +------------------- Not Used * | | | * | | +----------------------- Not used * | | * | +--------------------------- TEA * | * +------------------------------- Not used * * Status register (bits 0-2 not used): * +---+---+---+---+---+---+---+---+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * +---+---+---+---+---+---+---+---+ * | | | | | * | | | | +--- PST1 * | | | | 1 - ??? * | | | | 0 - ??? * | | | | * | | | +------- Target power * | | | 1 - Target power is ON * | | | 0 - Target power is OFF * | | | * | | +----------- Not used * | | * | +--------------- Halted * | 1 - Target is halted (PST0 | PST1 | PST1 | PST3) * | 0 - Target is running * | * +------------------- Serial data from target (DSO) * 1 - `0' from target * 0 - `1' from target * * Control register (bits 4-7 not used): * +---+---+---+---+ * | 3 | 2 | 1 | 0 | * +---+---+---+---+ * | | | | * | | | +--- Target /PST0 * | | | Write 1 - /PST0 line LOW * | | | Write 0 - /PST0 line to go HIGH * | | | * | | +------- Target PST2 * | | Write 1 - /PST2 line high * | | Write 0 - /PST2 line low * | | * | +----------- Target /PST3 * | Write 0 - /PST3 line LOW * | Write 1 - /PST3 line to go HIGH * | * +--------------- Not Used */ #define CF_PE_DR_DATA_IN 0x01 #define CF_PE_DR_CLOCK_HIGH 0x02 #define CF_PE_DR_BKPT 0x04 #define CF_PE_DR_RESET 0x08 #define CF_PE_DR_TEA 0x40 #define CF_PE_DR_MASK (CF_PE_DR_DATA_IN | CF_PE_DR_CLOCK_HIGH \ | CF_PE_DR_BKPT | CF_PE_DR_RESET | CF_PE_DR_TEA) #define CF_PE_MAKE_POS_DR(flags) ((flags) & (CF_PE_DR_DATA_IN | CF_PE_DR_CLOCK_HIGH)) #define CF_PE_MAKE_NEG_DR(flags) ((~(flags)) & (CF_PE_DR_BKPT | CF_PE_DR_RESET | CF_PE_DR_TEA)) #define CF_PE_MAKE_DR(flags) ((CF_PE_MAKE_POS_DR(flags) | CF_PE_MAKE_NEG_DR(flags)) & \ CF_PE_DR_MASK) #define CF_PE_SR_PST1 0x08 #define CF_PE_SR_POWERED 0x10 #define CF_PE_SR_FROZEN 0x40 /* do not use this, require SIM setup */ #define CF_PE_SR_DATA_OUT 0x80 #define CF_PE_CR_NOT_PST0 0x01 #define CF_PE_CR_NOT_PST2 0x02 #define CF_PE_CR_NOT_PST3 0x04 /* * Coldfire system register mapping. See bdm.h for the user values. * * For a RCREG 0x1 is invalid. */ static int cf_sysreg_map[BDM_REG_DBMR + 1] = { 0x80f, /* BDM_REG_RPC */ -1, /* BDM_REG_PCC */ 0x80e, /* BDM_REG_SR */ -1, /* BDM_REG_USP */ -1, /* BDM_REG_SSP, use A7 */ -1, /* BDM_REG_SFC */ -1, /* BDM_REG_DFC */ -1, /* BDM_REG_ATEMP */ -1, /* BDM_REG_FAR */ 0x801, /* BDM_REG_VBR */ 0x2, /* BDM_REG_CACR */ 0x4, /* BDM_REG_ACR0 */ 0x5, /* BDM_REG_ACR1 */ 0xc04, /* BDM_REG_RAMBAR */ 0xc0f, /* BDM_REG_MBAR */ 0x0, /* BDM_REG_CSR */ 0x6, /* BDM_REG_AATR */ 0x7, /* BDM_REG_TDR */ 0x8, /* BDM_REG_PBR */ 0x9, /* BDM_REG_PBMR */ 0xc, /* BDM_REG_ABHR */ 0xd, /* BDM_REG_ABLR */ 0xe, /* BDM_REG_DBR */ 0xf /* BDM_REG_DBMR */ }; static int cf_pe_read_sysreg (struct BDM *self, struct BDMioctl *ioc, int mode); static int cf_pe_write_sysreg (struct BDM *self, struct BDMioctl *ioc, int mode); static int cf_pe_reset_chip (struct BDM *self); #define CF_REVISION_A (0) #define CF_REVISION_B (1) #define CF_REVISION_C (2) #define CF_REVISION_D (3) /* * Get direct target status, that is from the parallel port. */ static int cf_pe_get_direct_status (struct BDM *self) { unsigned char sr = inb (self->statusPort); int ret; if (self->cf_use_pst) { unsigned char cr = 0, pst = 0; ret = 0; if (!(sr & CF_PE_SR_POWERED)) ret = BDM_TARGETPOWER; else if ((inb (self->dataPort) & CF_PE_DR_RESET) == 0) ret = BDM_TARGETRESET; else if (sr & CF_PE_SR_FROZEN) { cr = inb(self->controlPort); pst = 0; if (sr & CF_PE_SR_PST1) pst |= 0x02; if ((cr & CF_PE_CR_NOT_PST0) == 0) pst |= 0x01; if ((cr & CF_PE_CR_NOT_PST2) == 0) pst |= 0x04; if ((cr & CF_PE_CR_NOT_PST3) == 0) pst |= 0x08; switch (pst) { case 0x00: /* continue execution */ case 0x01: /* begin execution of an instruction */ case 0x02: /* reserved */ case 0x03: /* entry into user mode */ case 0x04: /* begin execution of PULSE and WDDATA inst. */ case 0x05: /* begin execution of taken branch */ case 0x06: /* reserved */ case 0x07: /* begin execution of RTE instruction */ case 0x08: /* begin 1-byte transfer on DDATA */ case 0x09: /* begin 2-byte transfer on DDATA */ case 0x0A: /* begin 3-byte transfer on DDATA */ case 0x0B: /* begin 4-byte transfer on DDATA */ case 0x0C: /* Execption processing */ case 0x0D: /* emulator mode exception processing */ ret = 0; break; case 0x0E: /* processor stopped waiting for interrupt */ ret = BDM_TARGETSTOPPED; break; case 0x0F: /* processor halted */ ret = BDM_TARGETHALT; break; default: PRINTF ("PST is invalid (0x%x,sr=%x,cr=%x)\n", pst, sr, cr); break; } } if (self->debugFlag > 3) PRINTF (" cf_pe_get_direct_status -- Status:0x%x SR:%x CR:%x PST:%x\n", ret, sr, cr, pst); } else { if ((sr & CF_PE_SR_POWERED) == 0) ret = BDM_TARGETPOWER; else ret = (inb (self->dataPort) & CF_PE_DR_RESET ? 0 : BDM_TARGETRESET); if (self->debugFlag > 3) PRINTF (" cf_pe_get_direct_status -- Status:0x%x, sr:0x%x\n", ret, sr); } return ret; } /* * Invalidate the cache. */ static int cf_pe_invalidate_cache (struct BDM *self) { struct BDMioctl cacr_ioc; cacr_ioc.address = BDM_REG_CACR; if (cf_pe_read_sysreg (self, &cacr_ioc, BDM_SYS_REG_MODE_MAPPED) < 0) return BDM_TARGETNC; /* * Set the invalidate bit. */ if (cacr_ioc.value) { /* CCJ: Add version C as I think the version D was wrong. */ if ((self->cf_debug_ver == CF_REVISION_C) || (self->cf_debug_ver == CF_REVISION_D)) cacr_ioc.value |= 0x01040100; else cacr_ioc.value |= 0x01000100; if (self->debugFlag > 2) PRINTF (" cf_pe_invalidate_cache -- cacr:0x%08x\n", (int) cacr_ioc.value); if (cf_pe_write_sysreg (self, &cacr_ioc, BDM_SYS_REG_MODE_MAPPED) < 0) return BDM_TARGETNC; } return 0; } /* * PC read check. This is used to see if the processor has halted. */ static int cf_pe_pc_read_check (struct BDM *self) { struct BDMioctl pc_ioc; pc_ioc.address = BDM_REG_RPC; if (cf_pe_read_sysreg (self, &pc_ioc, BDM_SYS_REG_MODE_MAPPED) < 0) return BDM_TARGETNC; return 0; } /* * Get target status */ static int cf_pe_get_status (struct BDM *self) { int cf_last_running = self->cf_running; unsigned int status = cf_pe_get_direct_status (self); unsigned long csr; int ret; if (self->cf_use_pst) { return status; } if (status & (BDM_TARGETRESET | BDM_TARGETNC | BDM_TARGETPOWER)) { PRINTF (" cf_pe_get_status -- Status:0x%x\n", status); return status; } if (self->cf_running) { struct BDMioctl csr_ioc; csr_ioc.address = BDM_REG_CSR; if (cf_pe_read_sysreg (self, &csr_ioc, BDM_SYS_REG_MODE_MAPPED) < 0) return BDM_TARGETNC; csr = csr_ioc.value; } else csr = self->cf_csr; ret = ((csr & 0x0e000000 ? BDM_TARGETHALT : 0) | (csr & 0x0f000000 ? BDM_TARGETSTOPPED : 0)); /* * If we were running, and we have detected we have stopped * flush the cache. */ if (cf_last_running && !self->cf_running) cf_pe_invalidate_cache (self); if (self->debugFlag > 2) PRINTF (" cf_pe_get_status -- Status:0x%x, csr:0x%08x, cf_csr:0x%08x\n", ret, (int) csr, (int) self->cf_csr); return ret; } /* * Hardware initialization. */ static int cf_pe_init_hardware (struct BDM *self) { int status; /* * Set the control port to this value. It makes the pins * high allowing them to be pulled down and therefore * used as inputs. * * This value breaks on a DELL 500MHz Pentium III machine. The * only known work around is to add a second parallel port to the * machine. */ outb (0x00, self->controlPort); /* * Force breakpoint */ cf_pe_reset_chip (self); /* * We do not know which version of debug module we have so * default to 0 and do not use PST signals. This will cause the * CSR register to be read. */ self->cf_running = 1; self->cf_debug_ver = 0; self->cf_use_pst = 0; status = cf_pe_get_status (self); if (self->debugFlag) PRINTF (" cf_pe_init_hardware: status:%d\n", status); /* * By default we want to use PST lines. */ self->cf_use_pst = 1; /* * Process the result of the CSR read. */ self->cf_debug_ver = (self->cf_csr >> 20) & 0x0f; if (self->debugFlag) PRINTF (" cf_ps_init_hardware: debug version is %d, PST %s\n", self->cf_debug_ver, self->cf_use_pst ? "enabled" : "disabled"); return status; } /* * Clock a word to/from the target */ static void cf_pe_serial_clocker (struct BDM *self, unsigned short wval, int holdback) { unsigned long shiftRegister; unsigned char dataBit; unsigned int counter; shiftRegister = wval; counter = 17 - holdback; while (counter--) { dataBit = ((shiftRegister & 0x10000) ? CF_PE_DR_DATA_IN : 0); shiftRegister <<= 1; outb (CF_PE_MAKE_DR (dataBit), self->dataPort); if (self->delayTimer) bdm_delay (self->delayTimer << 1); outb (CF_PE_MAKE_DR (dataBit | CF_PE_DR_CLOCK_HIGH), self->dataPort); if (self->delayTimer) bdm_delay (self->delayTimer); outb (CF_PE_MAKE_DR (dataBit), self->dataPort); if (self->delayTimer) bdm_delay (self->delayTimer); if ((inb (self->statusPort) & CF_PE_SR_DATA_OUT) == 0) shiftRegister |= 1; } outb (CF_PE_MAKE_DR (0), self->dataPort); self->readValue = shiftRegister & 0x1FFFF; if (self->debugFlag > 2) PRINTF (" cf_pe_serial_clock -- send 0x%x receive 0x%x\n", wval, self->readValue); } static int cf_pe_serial_clock (struct BDM *self, unsigned short wval, int holdback) { unsigned int status = cf_pe_get_direct_status (self); if (status & BDM_TARGETRESET) return BDM_FAULT_RESET; if (status & BDM_TARGETNC) return BDM_FAULT_CABLE; if (status & BDM_TARGETPOWER) return BDM_FAULT_POWER; cf_pe_serial_clocker (self, wval, holdback); if (self->readValue & 0x10000) { if (self->readValue == 0x10001) { if (self->debugFlag > 1) PRINTF (" cf_pe_serial_clock -- failure BUS ERROR, send 0x%x receive 0x%x\n", wval, self->readValue); return BDM_FAULT_BERR; } else if (self->readValue != 0x10000) { int i; if (self->debugFlag > 1) PRINTF (" cf_pe_serial_clock -- failure NVC, send 0x%x receive 0x%x\n", wval, self->readValue); /* * Force TA on a Coldfire if supported. We cannot do much else if * the Coldfire does not support the Forced TA command. */ if (self->cf_debug_ver >= CF_REVISION_D) { if (self->debugFlag) PRINTF (" cf_pe_serial_clock -- forced ta\n"); cf_pe_serial_clocker (self, BDM_FORCED_TA_CMD, holdback); cf_pe_serial_clocker (self, BDM_NOP_CMD, 0); cf_pe_serial_clocker (self, BDM_NOP_CMD, 0); return BDM_FAULT_FORCED_TA; } return BDM_FAULT_NVC; for (i = 0; i < 4; i++) cf_pe_serial_clocker (self, BDM_NOP_CMD, 0); #if EXPERIMENTAL_RECOVER for (i = 17; i > 0; i--) if ((self->readValue & (1 << 16)) == 0) break; if (i && (i < 17)) cf_pe_serial_clocker (self, BDM_NOP_CMD, 17 - i); #endif } } return 0; } /* * Read system register */ static int cf_pe_read_sysreg (struct BDM *self, struct BDMioctl *ioc, int mode) { int err; unsigned short msw, lsw; int cmd; if (self->debugFlag > 2) PRINTF (" cf_pe_read_sysreg + Reg(%d):0x%x\n", mode, ioc->address); if ((mode == BDM_SYS_REG_MODE_MAPPED) && (ioc->address >= BDM_MAX_SYSREG)) return BDM_FAULT_NVC; /* * For the Coldfire we need to select the type of command * to use. */ if ((mode == BDM_SYS_REG_MODE_CONTROL) || ((mode == BDM_SYS_REG_MODE_MAPPED) && (ioc->address < BDM_REG_CSR))) { if (mode == BDM_SYS_REG_MODE_CONTROL) cmd = ioc->address & 0xffff; else cmd = cf_sysreg_map[ioc->address]; if (cmd == -1) { ioc->value = 0; if (self->debugFlag) PRINTF (" cf_pe_read_sysreg - Reg(%d):0x%x is not mapped; ignored\n", mode, ioc->address); return 0; } if (((err = cf_pe_serial_clock (self, BDM_RCREG_CMD, 0)) != 0) || ((err = cf_pe_serial_clock (self, 0, 0)) != 0) || ((err = cf_pe_serial_clock (self, cmd, 0)) != 0) || ((err = bdmBitBashFetchWord (self, &msw)) != 0) || ((err = bdmBitBashFetchWord (self, &lsw)) != 0)) return err; } else { if (mode == BDM_SYS_REG_MODE_DEBUG) { int r; cmd = ioc->address & 0xffff; /* * See if the register is actually mapped and therefore write only. */ for (r = BDM_REG_CSR; r < BDM_MAX_SYSREG; r++) { if (cf_sysreg_map[r] == (ioc->address & 0xffff)) { mode = BDM_SYS_REG_MODE_MAPPED; ioc->address = r; if (self->debugFlag > 2) PRINTF (" cf_pe_read_sysreg - remapped to Reg:0x%x\n", ioc->address); break; } } } else cmd = cf_sysreg_map[ioc->address]; if (cmd == -1) { ioc->value = 0; if (self->debugFlag) PRINTF (" cf_pe_read_sysreg - Reg(%d):0x%x is not mapped; ignored\n", mode, ioc->address); return 0; } cmd |= BDM_RDMREG_CMD; /* * Are the registers write only ? */ if ((mode == BDM_SYS_REG_MODE_MAPPED) && (ioc->address != BDM_REG_CSR)) { ioc->value = self->shadow_sysreg[ioc->address]; if (self->debugFlag > 1) PRINTF (" cf_pe_read_sysreg - Reg:0x%x is write only, 0x%08x\n", ioc->address, ioc->value); return 0; } if (((err = cf_pe_serial_clock (self, cmd, 0)) != 0) || ((err = bdmBitBashFetchWord (self, &msw)) != 0) || ((err = bdmBitBashFetchWord (self, &lsw)) != 0)) { PRINTF (" cf_pe_read_sysreg - Reg:0x%x failed with cmd 0x%02x, err = %d\n", ioc->address, cmd, err); return err; } } ioc->value = (msw << 16) | lsw; /* * Watch out here as this function is called from cf_pe_get_status. */ if (ioc->address == BDM_REG_CSR) { if (self->cf_running) { if (ioc->value & 0x0f000000) { /* * We could false trigger for some reason such as bit * errors on the serial stream. To check if we have * actually halted we should read the program counter * register. If we can then we have halted, else * we can only assume we are still running. * * We check the PC read twice to insure we are ok. * * This solution is provided by Motorola, more specifically * Joe Circello, the chief ColdFire architect, and Sue Cozart * for providing access to Joe. Thanks. (CCJ 15-05-2000) */ if ((cf_pe_pc_read_check (self) == 0) && (cf_pe_pc_read_check (self) == 0)) { self->cf_csr = ioc->value; self->cf_running = 0; /* * If we were running, and we have detected we have stopped * flush the cache. This should probably be somewhere else * if we are using PST, I am not sure yet : davidm */ cf_pe_invalidate_cache (self); } else { /* * We have not halted as the PC is not accessable. */ ioc->value &= ~0x0f000000; } } } else { self->cf_csr = ioc->value = (self->cf_csr & 0x0f000000) | ioc->value; } } if (ioc->address == BDM_REG_SR) ioc->value &= 0xffff; if (self->debugFlag > 1) PRINTF (" cf_pe_read_sysreg - Reg(%d):0x%x is 0x%08x\n", mode, ioc->address, ioc->value); return 0; } /* * Write system register */ static int cf_pe_write_sysreg (struct BDM *self, struct BDMioctl *ioc, int mode) { int err; int cmd; if ((mode == BDM_SYS_REG_MODE_MAPPED) && (ioc->address >= BDM_MAX_SYSREG)) return BDM_FAULT_NVC; if (self->debugFlag) PRINTF (" cf_pe_write_sysreg - Reg(%d):0x%x is 0x%x\n", mode, ioc->address, ioc->value); /* * For the Coldfire we need to select the type of command * to use. */ if ((mode == BDM_SYS_REG_MODE_CONTROL) || ((mode == BDM_SYS_REG_MODE_MAPPED) && (ioc->address < BDM_REG_CSR))) { if (mode == BDM_SYS_REG_MODE_CONTROL) cmd = ioc->address & 0xffff; else cmd = cf_sysreg_map[ioc->address]; if (cmd == -1) { ioc->value = 0; if (self->debugFlag) PRINTF (" cf_pe_write_sysreg - Reg(%d):0x%x is not mapped; ignored\n", mode, ioc->address); return 0; } if (((err = cf_pe_serial_clock (self, BDM_WCREG_CMD, 0)) != 0) || ((err = cf_pe_serial_clock (self, 0, 0)) != 0) || ((err = cf_pe_serial_clock (self, cmd, 0)) != 0) || ((err = cf_pe_serial_clock (self, ioc->value >> 16, 0)) != 0) || ((err = cf_pe_serial_clock (self, ioc->value, 0)) != 0)) return err; } else { if (mode == BDM_SYS_REG_MODE_DEBUG) cmd = ioc->address & 0xffff; else cmd = cf_sysreg_map[ioc->address]; if (cmd == -1) { if (self->debugFlag) PRINTF (" tblcf_write_sysreg - Reg(%d):0x%x is not mapped; ignored\n", mode, ioc->address); return 0; } cmd |= BDM_WDMREG_CMD; if (mode == BDM_SYS_REG_MODE_MAPPED) self->shadow_sysreg[ioc->address] = ioc->value; if (((err = cf_pe_serial_clock (self, cmd , 0)) != 0) || ((err = cf_pe_serial_clock (self, ioc->value >> 16, 0)) != 0) || ((err = cf_pe_serial_clock (self, ioc->value, 0)) != 0)) return err; } return 0; } /* * Generate a bus error as the access has failed. This is * not supported on the CPU32. */ static int cf_pe_gen_bus_error (struct BDM *self) { if (self->cf_debug_ver < CF_REVISION_D) { if (self->debugFlag) PRINTF (" cf_pe_gen_bus_error\n"); outb (CF_PE_MAKE_DR (CF_PE_DR_TEA), self->dataPort); udelay (400); outb (CF_PE_MAKE_DR (0), self->dataPort); return BDM_FAULT_BERR; } else { int err; if (self->debugFlag) PRINTF (" cf_pe_gen_bus_error - forced ta\n"); if (((err = cf_pe_serial_clock (self, BDM_FORCED_TA_CMD, 0)) != 0) || ((err = cf_pe_serial_clock (self, BDM_NOP_CMD, 0)) != 0)) return err; return BDM_FAULT_FORCED_TA; } } /* * Restart chip and stop on first instruction fetch. Easy for the * Coldfire, keep BKPT asserted during the first 16 clocks after * reset is negated. */ static int cf_pe_restart_chip (struct BDM *self) { if (self->debugFlag) PRINTF (" cf_pe_restart_chip\n"); cf_pe_reset_chip (self); self->cf_running = 1; if (cf_pe_get_status (self) & (BDM_TARGETHALT | BDM_TARGETSTOPPED)) return 0; return BDM_FAULT_RESPONSE; } /* * Restart chip and disable background debugging mode. On * a Coldfire exit reset without the BKPT being asserted. */ static int cf_pe_release_chip (struct BDM *self) { if (self->debugFlag) PRINTF (" cf_pe_release_chip\n"); outb (CF_PE_MAKE_DR (0), self->dataPort); bdm_sleep (250); outb (CF_PE_MAKE_DR (CF_PE_DR_RESET), self->dataPort); bdm_sleep (500); outb (CF_PE_MAKE_DR (0), self->dataPort); self->cf_running = 1; return 0; } /* * Restart chip, the coldfire is easier than the CPU32 to get into * BMD mode after reset. Just have the BKPT signal active when * reset is negated. */ static int cf_pe_reset_chip (struct BDM *self) { if (self->debugFlag) PRINTF (" cf_pe_reset_chip\n"); outb (CF_PE_MAKE_DR (0), self->dataPort); bdm_sleep (100); // outb (CF_PE_MAKE_DR (CF_PE_DR_RESET), self->dataPort); // bdm_sleep (100); outb (CF_PE_MAKE_DR (CF_PE_DR_RESET | CF_PE_DR_BKPT), self->dataPort); bdm_sleep (500); outb (CF_PE_MAKE_DR (CF_PE_DR_BKPT), self->dataPort); bdm_sleep (1500); outb (CF_PE_MAKE_DR (0), self->dataPort); bdm_sleep (500); self->cf_running = 1; return 0; } /* * Force the target into background debugging mode */ static int cf_pe_stop_chip (struct BDM *self) { int status, retries = 4; if (self->debugFlag) PRINTF (" cf_pe_stop_chip\n"); while (retries--) { outb (CF_PE_MAKE_DR (CF_PE_DR_BKPT), self->dataPort); bdm_sleep (10); status = cf_pe_get_status (self); outb (CF_PE_MAKE_DR (0), self->dataPort); if (status & (BDM_TARGETHALT | BDM_TARGETSTOPPED)) { return 0; } } return BDM_FAULT_RESPONSE; } /* * Restart target execution. */ static int cf_pe_run_chip (struct BDM *self) { struct BDMioctl sreg_ioc; struct BDMioctl pc_ioc; int err; if (self->debugFlag) PRINTF (" cf_pe_run_chip\n"); /* * Flush the cache to insure all changed data is read by the * processor. */ cf_pe_invalidate_cache (self); /* * Change the CSR:4 or the SSM bit to off then issue a go. */ sreg_ioc.address = BDM_REG_CSR; sreg_ioc.value = 0x00000000; if ((err = cf_pe_write_sysreg (self, &sreg_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; /* * Revision D hardware does not have a bit to mask interrupts so * we save the SR if we step and need to restore it now. * * The SR needs to be read back and the mask bits set as the * other SR bits may have changed. * * It appears that the V4 core has some pipelining in effect that * causes instruction fetches to already be cached. This could be * problem in certain instances for stepping. To resolve this, * we read the PC value, and then write it right back out. */ if ((self->cf_debug_ver == CF_REVISION_D) && self->cf_sr_masked) { sreg_ioc.address = BDM_REG_SR; if ((err = cf_pe_read_sysreg (self, &sreg_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; sreg_ioc.value &= ~0x0700; sreg_ioc.value |= self->cf_sr_mask_cache; if ((err = cf_pe_write_sysreg (self, &sreg_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; self->cf_sr_masked = 0; /* * Read the PC value and write it back out */ pc_ioc.address = BDM_REG_RPC; if ((err = cf_pe_read_sysreg (self, &pc_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; if ((err = cf_pe_write_sysreg (self, &pc_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; } /* * Now issue a GO command. */ err = cf_pe_serial_clock (self, BDM_GO_CMD, 0); if (err) { PRINTF (" cf_pe_run_chip - GO cmd failed, err = %d\n", err); return err; } self->cf_running = 1; return 0; } /* * Make the target execute a single instruction and * reenter background debugging mode */ static int cf_pe_step_chip (struct BDM *self) { struct BDMioctl sreg_ioc; struct BDMioctl csr_ioc; struct BDMioctl pc_ioc; int err; if (self->debugFlag) PRINTF (" cf_pe_step_chip\n"); /* * Flush the cache to insure all changed data is read by the * processor. */ cf_pe_invalidate_cache (self); /* * Change the CSR:4 or the SSM bit to on then issue a go. * Mask pending interrupt to stop stepping into an interrupt. */ csr_ioc.address = BDM_REG_CSR; csr_ioc.value = 0x00000030; if ((err = cf_pe_write_sysreg (self, &csr_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; /* * Revision D hardware does not have a bit to mask interrupts so * we save the SR when we step and then restore when we go * * The SR needs to be read back and the mask bits set as the * other SR bits may have changed. * * It appears that the V4 core has some pipelining in effect that * causes instruction fetches to already be cached. This could be * problem in certain instances for stepping. To resolve this, * we read the PC value, and then write it right back out. */ if ((self->cf_debug_ver == CF_REVISION_D) && !self->cf_sr_masked) { sreg_ioc.address = BDM_REG_SR; if ((err = cf_pe_read_sysreg (self, &sreg_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; self->cf_sr_mask_cache = sreg_ioc.value & 0x0700; sreg_ioc.value |= 0x0700; if ((err = cf_pe_write_sysreg (self, &sreg_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; self->cf_sr_masked = 1; /* * Read the PC value and write it back out */ pc_ioc.address = BDM_REG_RPC; if ((err=cf_pe_read_sysreg (self, &pc_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; if ((err=cf_pe_write_sysreg (self, &pc_ioc, BDM_SYS_REG_MODE_MAPPED)) < 0) return err; } /* * Now issue a GO command. */ err = cf_pe_serial_clock (self, BDM_GO_CMD, 0); if (err) { PRINTF (" cf_pe_step_chip - GO cmd failed, err = %d\n", err); return err; } self->cf_running = 0; self->cf_csr = 0x01000000; return 0; } #ifdef BDM_BIT_BASH_PORT /* * Bit Bash the BDM port. No status checks. I assume you know what is happening at * a low level with the BDM hardware if you are using this interface. */ static int cf_bit_bash (struct BDM *self, unsigned short mask, unsigned short bits) { unsigned char data_port = 0; self->bit_bash_bits &= ~mask; self->bit_bash_bits |= bits; if (self->bit_bash_bits & BDM_BB_RESET) data_port |= CF_PE_DR_RESET; if (self->bit_bash_bits & BDM_BB_BKPT) data_port |= CF_PE_DR_BKPT; if (self->bit_bash_bits & BDM_BB_DATA_IN) data_port |= CF_PE_DR_DATA_IN; if (self->bit_bash_bits & BDM_BB_CLOCK) data_port |= CF_PE_DR_CLOCK_HIGH; outb (CF_PE_MAKE_DR (data_port), self->dataPort); if (self->debugFlag) PRINTF (" cf_bit_bash: mask=%04x, bits=%04x, data reg=%02x\n", mask, bits, CF_PE_MAKE_DR (data_port)); return 0; } #endif /* * Initialise the BDM structure for a Coldfire in the P&E interface */ static int cf_pe_init_self (struct BDM *self) { int reg; self->processor = BDM_COLDFIRE; self->interface = BDM_COLDFIRE_PE; self->get_status = cf_pe_get_status; self->init_hardware = cf_pe_init_hardware; self->serial_clock = cf_pe_serial_clock; self->gen_bus_error = cf_pe_gen_bus_error; self->restart_chip = cf_pe_restart_chip; self->release_chip = cf_pe_release_chip; self->reset_chip = cf_pe_reset_chip; self->stop_chip = cf_pe_stop_chip; self->run_chip = cf_pe_run_chip; self->step_chip = cf_pe_step_chip; self->fill_buf = bdmBitBashFillBuf; self->send_buf = bdmBitBashSendBuf; self->read_sysreg = cf_pe_read_sysreg; self->read_proreg = bdmBitBashReadProcessorRegister; self->read_long_word = bdmBitBashReadLongWord; self->read_word = bdmBitBashReadWord; self->read_byte = bdmBitBashReadByte; self->write_sysreg = cf_pe_write_sysreg; self->write_proreg = bdmBitBashWriteProcessorRegister; self->write_long_word = bdmBitBashWriteLongWord; self->write_word = bdmBitBashWriteWord; self->write_byte = bdmBitBashWriteByte; for (reg = 0; reg < BDM_MAX_SYSREG; reg++) if (reg == BDM_REG_AATR) self->shadow_sysreg[reg] = 0x0005; else self->shadow_sysreg[reg] = 0; #ifdef BDM_BIT_BASH_PORT self->bit_bash = cf_bit_bash; self->bit_bash_bits = 0; #endif self->cf_debug_ver = 0; self->cf_use_pst = 1; self->cf_running = 1; self->cf_csr = 0; self->cf_sr_masked = 0; return 0; }