static void bfin_timer_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { switch (mode) { case CLOCK_EVT_MODE_PERIODIC: { unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); bfin_write_TCNTL(TMPWR); CSYNC(); bfin_write_TSCALE(TIME_SCALE - 1); bfin_write_TPERIOD(tcount); bfin_write_TCOUNT(tcount); CSYNC(); bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD); break; } case CLOCK_EVT_MODE_ONESHOT: bfin_write_TCNTL(TMPWR); CSYNC(); bfin_write_TSCALE(TIME_SCALE - 1); bfin_write_TPERIOD(0); bfin_write_TCOUNT(0); break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: bfin_write_TCNTL(0); CSYNC(); break; case CLOCK_EVT_MODE_RESUME: break; } }
static void time_sched_init(irq_handler_t timer_routine) { u32 tcount; /* power up the timer, but don't enable it just yet */ bfin_write_TCNTL(1); CSYNC(); /* * the TSCALE prescaler counter. */ bfin_write_TSCALE((TIME_SCALE - 1)); tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); bfin_write_TPERIOD(tcount); bfin_write_TCOUNT(tcount); /* now enable the timer */ CSYNC(); bfin_write_TCNTL(7); bfin_timer_irq.handler = (irq_handler_t)timer_routine; /* call setup_irq instead of request_irq because request_irq calls * kmalloc which has not been initialized yet */ setup_irq(IRQ_CORETMR, &bfin_timer_irq); }
void rthal_nmi_arm(unsigned long delay) { write_wdog(CTL, 0xad0); /* Disable */ CSYNC(); write_wdog(CNT, delay); write_wdog(CTL, 0x2); /* Enable, generate NMIs */ CSYNC(); }
static int bfin_timer_set_next_event(unsigned long cycles, struct clock_event_device *evt) { bfin_write_TCNTL(TMPWR); CSYNC(); bfin_write_TCOUNT(cycles); CSYNC(); bfin_write_TCNTL(TMPWR | TMREN); return 0; }
void rthal_nmi_release(void) { if (rthal_nmi_emergency == NULL) return; rthal_nmi_disarm(); CSYNC(); bfin_write_EVT2(rthal_old_nmi_handler); CSYNC(); rthal_nmi_emergency = NULL; }
int rthal_nmi_request(void (*emergency) (struct pt_regs *)) { if (rthal_nmi_emergency) return -EBUSY; rthal_nmi_disarm(); CSYNC(); rthal_nmi_emergency = emergency; rthal_old_nmi_handler = (void *)bfin_read_EVT2(); bfin_write_EVT2(&rthal_nmi_handler); CSYNC(); return 0; }
static void __init bfin_timer_init(void) { /* power up the timer, but don't enable it just yet */ bfin_write_TCNTL(TMPWR); CSYNC(); /* * the TSCALE prescaler counter. */ bfin_write_TSCALE(TIME_SCALE - 1); bfin_write_TPERIOD(0); bfin_write_TCOUNT(0); CSYNC(); }
void kgdb_disable_hw_debug(struct pt_regs *regs) { /* Disable hardware debugging while we are in kgdb */ bfin_write_WPIACTL(0); bfin_write_WPDACTL(0); CSYNC(); }
static int coreb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int ret = 0; switch (cmd) { case CMD_COREB_START: bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() & ~0x0020); break; case CMD_COREB_STOP: bfin_write_SICA_SYSCR(bfin_read_SICA_SYSCR() | 0x0020); bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080); break; case CMD_COREB_RESET: bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | 0x0080); break; default: ret = -EINVAL; break; } CSYNC(); return ret; }
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs; struct irq_desc *desc = irq_desc + irq; unsigned short pending, other_ints; old_regs = set_irq_regs(regs); /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ if (irq >= NR_IRQS) desc = &bad_irq_desc; irq_enter(); generic_handle_irq(irq); /* If we're the only interrupt running (ignoring IRQ15 which is for syscalls), lower our priority to IRQ14 so that softirqs run at that level. If there's another, lower-level interrupt, irq_exit will defer softirqs to that. */ CSYNC(); pending = bfin_read_IPEND() & ~0x8000; other_ints = pending & (pending - 1); if (other_ints == 0) lower_to_irq14(); irq_exit(); set_irq_regs(old_regs); }
int irq_init(void) { #ifdef SIC_IMASK0 bfin_write_SIC_IMASK0(0); bfin_write_SIC_IMASK1(0); # ifdef SIC_IMASK2 bfin_write_SIC_IMASK2(0); # endif #elif defined(SICA_IMASK0) bfin_write_SICA_IMASK0(0); bfin_write_SICA_IMASK1(0); #else bfin_write_SIC_IMASK(0); #endif bfin_write_EVT2(evt_default); /* NMI */ bfin_write_EVT5(evt_default); /* hardware error */ bfin_write_EVT6(evt_default); /* core timer */ bfin_write_EVT7(evt_default); bfin_write_EVT8(evt_default); bfin_write_EVT9(evt_default); bfin_write_EVT10(evt_default); bfin_write_EVT11(evt_default); bfin_write_EVT12(evt_default); bfin_write_EVT13(evt_default); bfin_write_EVT14(evt_default); bfin_write_EVT15(evt_default); bfin_write_ILAT(0); CSYNC(); return 0; }
int irq_init(void) { #ifdef SIC_IMASK0 bfin_write_SIC_IMASK0(0); bfin_write_SIC_IMASK1(0); # ifdef SIC_IMASK2 bfin_write_SIC_IMASK2(0); # endif #elif defined(SICA_IMASK0) bfin_write_SICA_IMASK0(0); bfin_write_SICA_IMASK1(0); #elif defined(SIC_IMASK) bfin_write_SIC_IMASK(0); #endif /* Set up a dummy NMI handler if needed. */ if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_BYPASS || ANOMALY_05000219) bfin_write_EVT2(evt_nmi); /* NMI */ bfin_write_EVT5(evt_default); /* hardware error */ bfin_write_EVT6(evt_default); /* core timer */ bfin_write_EVT7(evt_default); bfin_write_EVT8(evt_default); bfin_write_EVT9(evt_default); bfin_write_EVT10(evt_default); bfin_write_EVT11(evt_default); bfin_write_EVT12(evt_default); bfin_write_EVT13(evt_default); bfin_write_EVT14(evt_default); bfin_write_EVT15(evt_default); bfin_write_ILAT(0); CSYNC(); /* enable hardware error irq */ irq_flags = 0x3f; local_irq_enable(); return 0; }
int kgdb_arch_handle_exception(int exceptionVector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *linux_regs) { long addr; long breakno; char *ptr; int newPC; int wp_status; switch (remcom_in_buffer[0]) { case 'c': case 's': if (kgdb_contthread && kgdb_contthread != current) { strcpy(remcom_out_buffer, "E00"); break; } kgdb_contthread = NULL; /* try to read optional parameter, pc unchanged if no parm */ ptr = &remcom_in_buffer[1]; if (kgdb_hex2long(&ptr, &addr)) { linux_regs->retx = addr; } newPC = linux_regs->retx; /* clear the trace bit */ linux_regs->syscfg &= 0xfffffffe; /* set the trace bit if we're stepping */ if (remcom_in_buffer[0] == 's') { linux_regs->syscfg |= 0x1; debugger_step = 1; } wp_status = bfin_read_WPSTAT(); CSYNC(); if (exceptionVector == VEC_WATCH) { for (breakno = 0; breakno < 6; ++breakno) { if (wp_status & (1 << breakno)) { breakinfo->skip = 1; break; } } } kgdb_correct_hw_break(); bfin_write_WPSTAT(0); return 0; } /* switch */ return -1; /* this means that we do not want to exit from the handler */ }
void __init setup_core_timer(void) { u32 tcount; /* power up the timer, but don't enable it just yet */ bfin_write_TCNTL(1); CSYNC(); /* the TSCALE prescaler counter */ bfin_write_TSCALE(TIME_SCALE - 1); tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1); bfin_write_TPERIOD(tcount); bfin_write_TCOUNT(tcount); /* now enable the timer */ CSYNC(); bfin_write_TCNTL(7); }
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs; struct irq_desc *desc = irq_desc + irq; #ifndef CONFIG_IPIPE unsigned short pending, other_ints; #endif old_regs = set_irq_regs(regs); /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ if (irq >= NR_IRQS) desc = &bad_irq_desc; irq_enter(); #ifdef CONFIG_DEBUG_STACKOVERFLOW /* Debugging check for stack overflow: is there less than STACK_WARN free? */ { long sp; sp = __get_SP() & (THREAD_SIZE-1); if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { dump_stack(); printk(KERN_EMERG "%s: possible stack overflow while handling irq %i " " only %ld bytes free\n", __func__, irq, sp - sizeof(struct thread_info)); } } #endif generic_handle_irq(irq); #ifndef CONFIG_IPIPE /* * If we're the only interrupt running (ignoring IRQ15 which * is for syscalls), lower our priority to IRQ14 so that * softirqs run at that level. If there's another, * lower-level interrupt, irq_exit will defer softirqs to * that. If the interrupt pipeline is enabled, we are already * running at IRQ14 priority, so we don't need this code. */ CSYNC(); pending = bfin_read_IPEND() & ~0x8000; other_ints = pending & (pending - 1); if (other_ints == 0) lower_to_irq14(); #endif /* !CONFIG_IPIPE */ irq_exit(); set_irq_regs(old_regs); }
void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) { unsigned long ctrl; int i; for (i = 0; i < MAX_CPLBS; i++) { bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr); bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data); } ctrl = bfin_read_IMEM_CONTROL(); ctrl |= IMC | ENICPLB; /* CSYNC to ensure load store ordering */ CSYNC(); bfin_write_IMEM_CONTROL(ctrl); SSYNC(); }
static void maybe_lower_to_irq14(void) { unsigned short pending, other_ints; /* * If we're the only interrupt running (ignoring IRQ15 which * is for syscalls), lower our priority to IRQ14 so that * softirqs run at that level. If there's another, * lower-level interrupt, irq_exit will defer softirqs to * that. If the interrupt pipeline is enabled, we are already * running at IRQ14 priority, so we don't need this code. */ CSYNC(); pending = bfin_read_IPEND() & ~0x8000; other_ints = pending & (pending - 1); if (other_ints == 0) lower_to_irq14(); }
int do_dcache_dump(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { u32 way, bank, subbank, set; u32 status, addr; u32 dmem_ctl = bfin_read_DMEM_CONTROL(); for (bank = 0; bank < 2; ++bank) { if (!(dmem_ctl & (1 << (DMC1_P - bank)))) continue; for (way = 0; way < 2; ++way) for (subbank = 0; subbank < 4; ++subbank) { printf("%i:%i:%i:\t", bank, way, subbank); for (set = 0; set < 64; ++set) { if (ctrlc()) return 1; /* retrieve a cache tag */ bfin_write_DTEST_COMMAND( way << 26 | bank << 23 | subbank << 16 | set << 5 ); CSYNC(); status = bfin_read_DTEST_DATA0(); /* construct the address using the tag */ addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5); /* show it */ if (set && !(set % 4)) puts("\n\t"); printf("%c%08x%c%08x%c ", (status & 0x1 ? '[' : '{'), status, (status & 0x2 ? 'd' : ' '), addr, (status & 0x1 ? ']' : '}')); } puts("\n"); } } return 0; }
void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) { unsigned long ctrl; int i; for (i = 0; i < MAX_CPLBS; i++) { bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr); bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data); } ctrl = bfin_read_DMEM_CONTROL(); /* * Anomaly notes: * 05000287 - We implement workaround #2 - Change the DMEM_CONTROL * register, so that the port preferences for DAG0 and DAG1 are set * to port B */ ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0); /* CSYNC to ensure load store ordering */ CSYNC(); bfin_write_DMEM_CONTROL(ctrl); SSYNC(); }
void rthal_nmi_disarm(void) { write_wdog(CTL, 0xad0); /* Disable */ CSYNC(); }
void kgdb_correct_hw_break(void) { int breakno; int correctit; uint32_t wpdactl = bfin_read_WPDACTL(); correctit = 0; for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) { if (breakinfo[breakno].type == 1) { switch (breakno) { case 0: if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) { correctit = 1; wpdactl &= ~(WPIREN01|EMUSW0); wpdactl |= WPIAEN0|WPICNTEN0; bfin_write_WPIA0(breakinfo[breakno].addr); bfin_write_WPIACNT0(breakinfo[breakno].skip); } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) { correctit = 1; wpdactl &= ~WPIAEN0; } break; case 1: if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) { correctit = 1; wpdactl &= ~(WPIREN01|EMUSW1); wpdactl |= WPIAEN1|WPICNTEN1; bfin_write_WPIA1(breakinfo[breakno].addr); bfin_write_WPIACNT1(breakinfo[breakno].skip); } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) { correctit = 1; wpdactl &= ~WPIAEN1; } break; case 2: if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) { correctit = 1; wpdactl &= ~(WPIREN23|EMUSW2); wpdactl |= WPIAEN2|WPICNTEN2; bfin_write_WPIA2(breakinfo[breakno].addr); bfin_write_WPIACNT2(breakinfo[breakno].skip); } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) { correctit = 1; wpdactl &= ~WPIAEN2; } break; case 3: if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) { correctit = 1; wpdactl &= ~(WPIREN23|EMUSW3); wpdactl |= WPIAEN3|WPICNTEN3; bfin_write_WPIA3(breakinfo[breakno].addr); bfin_write_WPIACNT3(breakinfo[breakno].skip); } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) { correctit = 1; wpdactl &= ~WPIAEN3; } break; case 4: if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) { correctit = 1; wpdactl &= ~(WPIREN45|EMUSW4); wpdactl |= WPIAEN4|WPICNTEN4; bfin_write_WPIA4(breakinfo[breakno].addr); bfin_write_WPIACNT4(breakinfo[breakno].skip); } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) { correctit = 1; wpdactl &= ~WPIAEN4; } break; case 5: if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) { correctit = 1; wpdactl &= ~(WPIREN45|EMUSW5); wpdactl |= WPIAEN5|WPICNTEN5; bfin_write_WPIA5(breakinfo[breakno].addr); bfin_write_WPIACNT5(breakinfo[breakno].skip); } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) { correctit = 1; wpdactl &= ~WPIAEN5; } break; } } } if (correctit) { wpdactl &= ~WPAND; wpdactl |= WPPWR; /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/ bfin_write_WPDACTL(wpdactl); CSYNC(); /*kgdb_show_info();*/ } }
/* Initiate the event table handler */ void __init trap_init(void) { CSYNC(); bfin_write_EVT3(trap); CSYNC(); }
void bfin_correct_hw_break(void) { int breakno; unsigned int wpiactl = 0; unsigned int wpdactl = 0; int enable_wp = 0; for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) if (breakinfo[breakno].enabled) { enable_wp = 1; switch (breakno) { case 0: wpiactl |= WPIAEN0|WPICNTEN0; bfin_write_WPIA0(breakinfo[breakno].addr); bfin_write_WPIACNT0(breakinfo[breakno].count + breakinfo->skip); break; case 1: wpiactl |= WPIAEN1|WPICNTEN1; bfin_write_WPIA1(breakinfo[breakno].addr); bfin_write_WPIACNT1(breakinfo[breakno].count + breakinfo->skip); break; case 2: wpiactl |= WPIAEN2|WPICNTEN2; bfin_write_WPIA2(breakinfo[breakno].addr); bfin_write_WPIACNT2(breakinfo[breakno].count + breakinfo->skip); break; case 3: wpiactl |= WPIAEN3|WPICNTEN3; bfin_write_WPIA3(breakinfo[breakno].addr); bfin_write_WPIACNT3(breakinfo[breakno].count + breakinfo->skip); break; case 4: wpiactl |= WPIAEN4|WPICNTEN4; bfin_write_WPIA4(breakinfo[breakno].addr); bfin_write_WPIACNT4(breakinfo[breakno].count + breakinfo->skip); break; case 5: wpiactl |= WPIAEN5|WPICNTEN5; bfin_write_WPIA5(breakinfo[breakno].addr); bfin_write_WPIACNT5(breakinfo[breakno].count + breakinfo->skip); break; case 6: wpdactl |= WPDAEN0|WPDCNTEN0|WPDSRC0; wpdactl |= breakinfo[breakno].dataacc << WPDACC0_OFFSET; bfin_write_WPDA0(breakinfo[breakno].addr); bfin_write_WPDACNT0(breakinfo[breakno].count + breakinfo->skip); break; case 7: wpdactl |= WPDAEN1|WPDCNTEN1|WPDSRC1; wpdactl |= breakinfo[breakno].dataacc << WPDACC1_OFFSET; bfin_write_WPDA1(breakinfo[breakno].addr); bfin_write_WPDACNT1(breakinfo[breakno].count + breakinfo->skip); break; } } /* Should enable WPPWR bit first before set any other * WPIACTL and WPDACTL bits */ if (enable_wp) { bfin_write_WPIACTL(WPPWR); CSYNC(); bfin_write_WPIACTL(wpiactl|WPPWR); bfin_write_WPDACTL(wpdactl); CSYNC(); } }