static int xicor_read(uint8_t addr) { while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) ; out64((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD)); out64((addr & 0xff), SMB_CSR(R_SMB_DATA)); out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE), SMB_CSR(R_SMB_START)); while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) ; out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE), SMB_CSR(R_SMB_START)); while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) ; if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { /* Clear error bit by writing a 1 */ out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); return -1; } return (in64(SMB_CSR(R_SMB_DATA)) & 0xff); }
int l1p_init() { // Restore A2 hardware thread priority ThreadPriority_Medium(); if(PhysicalThreadID() != 0) return 0; // Restore prefetcher state CoreState_t* cs = GetCoreStateByCore(PhysicalProcessorID()); if(cs->default_l1p_init) { out64((void *)L1P_CFG_SPEC, cs->default_l1p_cfgspec); out64((void *)L1P_CFG_PF_USR, cs->default_l1p_cfgpfusr); out64((void *)L1P_CFG_PF_SYS, cs->default_l1p_cfgpfsys); ppc_msync(); } else { ppc_msync(); cs->default_l1p_cfgspec = in64((void*)L1P_CFG_SPEC); cs->default_l1p_cfgpfusr = in64((void*)L1P_CFG_PF_USR); cs->default_l1p_cfgpfsys = in64((void*)L1P_CFG_PF_SYS); cs->default_l1p_init = 1; ppc_msync(); } return 0; }
/* * Bring up the timer at 100 Hz. */ void __init swarm_time_init(void) { unsigned int flags; int status; /* Set up the scd general purpose timer 0 to cpu 0 */ sb1250_time_init(); /* Establish communication with the Xicor 1241 RTC */ /* XXXKW how do I share the SMBus with the I2C subsystem? */ out64(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ)); out64(0, SMB_CSR(R_SMB_CONTROL)); if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) { printk("x1241: couldn't detect on SWARM SMBus 1\n"); } else { if (status & X1241REG_SR_RTCF) printk("x1241: battery failed -- time is probably wrong\n"); write_lock_irqsave (&xtime_lock, flags); xtime.tv_sec = get_swarm_time(); xtime.tv_usec = 0; write_unlock_irqrestore(&xtime_lock, flags); } }
void __hwmacro_setup(void) { //mask all interrupts out64(STD_LCL_EIMR_OR, 0xffffffffffffffffull); //Set all interrupts to active low, level sensitive by default out64(STD_LCL_EIPR_CLR, 0xffffffffffffffffull); out64(STD_LCL_EITR_CLR, 0xffffffffffffffffull); //set up the configured type out64(STD_LCL_EITR_OR, g_ext_irqs_type); //set up the configured polarity out64(STD_LCL_EIPR_OR, g_ext_irqs_polarity); //clear the status of all active-high interrupts (has no affect on //level sensitive interrupts) out64(STD_LCL_EISR_CLR, g_ext_irqs_polarity); //clear the status of all active-low interrupts (has no affect on //level sensitive interrupts) out64(STD_LCL_EISR_OR, ~g_ext_irqs_polarity); //unmask the interrupts that are to be enabled by default out64(STD_LCL_EIMR_CLR, g_ext_irqs_enable); //wait for the last operation to complete sync(); }
void sb1250_time_init(void) { int cpu = smp_processor_id(); int irq = K_INT_TIMER_0+cpu; /* Only have 4 general purpose timers */ if (cpu > 3) { BUG(); } if (!cpu) { /* Use our own gettimeoffset() routine */ do_gettimeoffset = sb1250_gettimeoffset; } sb1250_mask_irq(cpu, irq); /* Map the timer interrupt to ip[4] of this cpu */ out64(IMR_IP4_VAL, KSEG1 + A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + (irq<<3)); /* the general purpose timer ticks at 1 Mhz independent if the rest of the system */ /* Disable the timer and set up the count */ out64(0, KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); out64( #ifndef CONFIG_SIMULATION 1000000/HZ #else 50000/HZ #endif , KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); /* Set the timer running */ out64(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); sb1250_unmask_irq(cpu, irq); sb1250_steal_irq(irq); /* * This interrupt is "special" in that it doesn't use the request_irq * way to hook the irq line. The timer interrupt is initialized early * enough to make this a major pain, and it's also firing enough to * warrant a bit of special case code. sb1250_timer_interrupt is * called directly from irq_handler.S when IP[4] is set during an * interrupt */ }
static int xicor_write(uint8_t addr, int b) { while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) ; out64(addr, SMB_CSR(R_SMB_CMD)); out64((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA)); out64(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE, SMB_CSR(R_SMB_START)); while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) ; if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { /* Clear error bit by writing a 1 */ out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); return -1; } else { return 0; } }
void sb1250_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); int irq = K_INT_TIMER_0+cpu; /* Reset the timer */ out64(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); /* * CPU 0 handles the global timer interrupt job */ if (cpu == 0) { ll_timer_interrupt(irq, regs); } /* * every CPU should do profiling and process accouting */ ll_local_timer_interrupt(irq, regs); }
/* Set up the driver and register it, register the 2 1250 UART interrupts. This is called from tty_init, or as a part of the module init */ static int __init sb1250_duart_init(void) { int i; sb1250_duart_driver.magic = TTY_DRIVER_MAGIC; sb1250_duart_driver.driver_name = "serial"; #ifdef CONFIG_DEVFS_FS sb1250_duart_driver.name = "tts/%d"; #else sb1250_duart_driver.name = "ttyS"; #endif sb1250_duart_driver.major = TTY_MAJOR; sb1250_duart_driver.minor_start = SB1250_DUART_MINOR_BASE; sb1250_duart_driver.num = DUART_MAX_LINE; sb1250_duart_driver.type = TTY_DRIVER_TYPE_SERIAL; sb1250_duart_driver.subtype = SERIAL_TYPE_NORMAL; sb1250_duart_driver.init_termios = tty_std_termios; sb1250_duart_driver.flags = TTY_DRIVER_REAL_RAW; sb1250_duart_driver.refcount = &duart_refcount; sb1250_duart_driver.table = duart_table; sb1250_duart_driver.termios = duart_termios; sb1250_duart_driver.termios_locked = duart_termios_locked; sb1250_duart_driver.open = duart_open; sb1250_duart_driver.close = duart_close; sb1250_duart_driver.write = duart_write; sb1250_duart_driver.put_char = duart_put_char; sb1250_duart_driver.write_room = duart_write_room; sb1250_duart_driver.flush_chars = duart_flush_chars; sb1250_duart_driver.chars_in_buffer = duart_chars_in_buffer; sb1250_duart_driver.flush_buffer = duart_flush_buffer; sb1250_duart_driver.ioctl = duart_ioctl; sb1250_duart_driver.set_termios = duart_set_termios; sb1250_duart_driver.stop = duart_stop; sb1250_duart_driver.start = duart_start; sb1250_duart_driver.hangup = duart_hangup; sb1250_duart_driver.wait_until_sent = duart_wait_until_sent; sb1250_duart_callout_driver = sb1250_duart_driver; #ifdef CONFIG_DEVFS_FS sb1250_duart_callout_driver.name = "cua/%d"; #else sb1250_duart_callout_driver.name = "cua"; #endif sb1250_duart_callout_driver.major = TTYAUX_MAJOR; sb1250_duart_callout_driver.subtype = SERIAL_TYPE_CALLOUT; for (i=0; i<DUART_MAX_LINE; i++) { uart_state_t *port = uart_states + i; if (!sb1250_duart_present[i]) continue; init_duart_port(port, i); spin_lock_init(&port->outp_lock); duart_mask_ints(i, M_DUART_IMR_ALL); if (request_irq(K_INT_UART_0+i, duart_int, 0, "uart", port)) { panic("Couldn't get uart0 interrupt line"); } out64(M_DUART_RX_EN|M_DUART_TX_EN, IO_SPACE_BASE | A_DUART_CHANREG(i, R_DUART_CMD)); duart_set_cflag(i, DEFAULT_CFLAGS); } /* Interrupts are now active, our ISR can be called. */ if (tty_register_driver(&sb1250_duart_driver)) { printk(KERN_ERR "Couldn't register sb1250 duart serial driver\n"); } if (tty_register_driver(&sb1250_duart_callout_driver)) { printk(KERN_ERR "Couldn't register sb1250 duart callout driver\n"); } return 0; }