//------------------------------------------------------------------------------ // // Function: OEMReadDebugByte // // Input character/byte from debug serial port // INT OEMReadDebugByte() { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); UINT8 ch, status; status = INREG8(&pVRC5477Regs->UARTLSR0); if ((status & UART_LSR_DR) != 0) { ch = INREG8(&pVRC5477Regs->UARTRBR0); if ((status & UART_LSR_RFERR) != 0) ch = OEM_DEBUG_COM_ERROR; } else { ch = OEM_DEBUG_READ_NODATA; } return ch; }
//------------------------------------------------------------------------------ // VOID OALTimerSetCount(UINT32 count) { UINT32 retVal = 0; UINT32 setDelay = 0; SH4_TMU_REGS *pTMURegs = OALPAtoUA(SH4_REG_PA_TMU); // Stop Timer OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) & ~TMU_TSTR_STR0); // Update the count OUTREG32(&pTMURegs->TCNT0, count + setDelay - 1); // Start Timer OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) | TMU_TSTR_STR0); }
//------------------------------------------------------------------------------ // // Function: BSPIntrActiveIrq // // This function is called from interrupt handler to give BSP chance to // translate IRQ in case of secondary interrupt controller. // UINT32 BSPIntrActiveIrq(UINT32 irq) { UINT8 data; UINT32 doneIrq; OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+BSPIntrActiveIrq(%d)\r\n", irq)); switch(irq) { case IRQ_GPIO: // Check whether alarm happen if(OALRTCAlarmIntrHandler() == FALSE) { irq = OAL_INTR_IRQ_UNDEFINED; } // Acknowledge GPIO interrupt OUTREG32(&g_pVRC5477Regs->GIUINSTAT, 0xffffffff); // Re-enable IRQ_GPIO interrupt on VRC5477 doneIrq = IRQ_GPIO; OALIntrDoneIrqs(1, &doneIrq); break; case IRQ_INTC: // Read PIC1 interrupt OUTREG8(&g_pPIC1Regs->ctrl, 0x0E); data = INREG8(&g_pPIC1Regs->data) & 0x07; if (data != 2) { irq = IRQ_PIC_0 + data; SETREG8(&g_pPIC1Regs->mask, 1 << data); } else { // Read PIC2 interrupt OUTREG8(&g_pPIC2Regs->ctrl, 0x0E); data = INREG8(&g_pPIC2Regs->data) & 0x07; irq = IRQ_PIC_8 + data; SETREG8(&g_pPIC2Regs->mask, 1 << data); // End interrupt on PIC2 OUTREG8(&g_pPIC2Regs->ctrl, 0x20); } // End interrupt on PIC1 OUTREG8(&g_pPIC1Regs->ctrl, 0x20); // Re-enable IRQ_INTC interrupt on VRC5477 doneIrq = IRQ_INTC; OALIntrDoneIrqs(1, &doneIrq); break; } OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-BSPIntrActiveIrq(%d)\r\n", irq)); return irq; }
//------------------------------------------------------------------------------ // // Function: OALIntrDoneIrq/BSPIntrDoneIrq // // This function finish interrupt identified by IRQ. If implementation uses // platform callbacks it will call BSPIntrDoneIrq before IRQ is enabled in // hardware. The BSPIntrDoneIrq returns IRQ used for interrupt controller // chaining if it is suitable to finish it. In most cases implementation will // for both function will be similar to OALIntrEnableIrq/BSPIntrEnableIrq. // VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs) { UINT32 irq, i; SH4_RTC_REGS *pRTCRegs = OALPAtoUA(SH4_REG_PA_RTC); OALMSG(OAL_VERBOSE&&OAL_FUNC, (L"+OALIntrDoneIrqs(%d, 0x%08x)\r\n", count, pIrqs)); for(i = 0; i < count; i++) { #ifndef OAL_BSP_CALLBACKS irq = pIrqs[i]; #else irq = BSPIntrDoneIrq(pIrqs[i]); #endif if(irq == OAL_INTR_IRQ_UNDEFINED) continue; switch(irq) { case IRQ_RTC_ATI: // Clear alarm flag but do not reenable interrupt for the RTC Alarm // since that will happen the next time OEMSetAlarmTime is called OUTREG8(&pRTCRegs->RCR1, (INREG8(&pRTCRegs->RCR1) & ~(RTC_RCR1_AF))); break; default: OALMSG(OAL_ERROR, (L"ERROR: Unable to disable IRQ %d\r\n", irq)); } } OALMSG(OAL_VERBOSE&&OAL_FUNC, (L"-OALIntrDoneIrqs()\r\n")); }
static uint8_t read_reg(uint32_t reg, bool use_mmio) { if (use_mmio) return INREG8(reg); else return inb(reg); }
//------------------------------------------------------------------------------ // // Function: OALIntrEnableIrq/BSPIntrEnableIrq // // This function enable interrupt identified by IRQ. If implementation uses // platform callbacks it will call BSPIntrEnableIrq before IRQ is enabled in // hardware. The BSPIntrEnableIrq returns IRQ used for interrupt controller // chaining. // BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs) { UINT32 irq, i; BOOL retVal = TRUE; SH4_RTC_REGS *pRTCRegs = OALPAtoUA(SH4_REG_PA_RTC); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALIntrEnableIrqs(%d, 0x%08x)\r\n", count, pIrqs)); for(i = 0; i < count; i++) { #ifndef OAL_BSP_CALLBACKS irq = pIrqs[i]; #else // Give the BSP a chance to enable the irq irq = BSPIntrEnableIrq(pIrqs[i]); #endif if(irq == OAL_INTR_IRQ_UNDEFINED) continue; switch(irq) { case IRQ_RTC_ATI: OUTREG8(&pRTCRegs->RCR1, INREG8(&pRTCRegs->RCR1) | RTC_RCR1_AIE); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"INFO: IRQ_RTC_ATI Enabled\r\n")); break; default: OALMSG(OAL_ERROR, (L"ERROR: Unable to enable IRQ %d\r\n", irq)); retVal = FALSE; } } OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALIntrEnableIrqs(rc = %d)\r\n", retVal)); return retVal; }
//////////////////////////////////////////////////// // 功能: codec 寄存器读出 // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static unsigned char codec_reg_read(unsigned char addr) { AIC_RW_CODEC_START(); OUTREG16(AIC_RGADW, (addr << RGADW_ADDR_BIT)); return (INREG8(AIC_RGDAT)); }
//------------------------------------------------------------------------------ // // Function: OALIntrDisableIrq/BSPIntrDisableIrq // // This function disable interrupt identified by IRQ. If implementation uses // platform callbacks it will call BSPIntrDisableIrq before IRQ is disabled in // hardware. The BSPIntrEnableIrq returns IRQ used for interrupt controller // chaining if it is suitable to disable it. // VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs) { UINT32 irq, i; SH4_RTC_REGS *pRTCRegs = OALPAtoUA(SH4_REG_PA_RTC); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"+OALIntrDisableIrqs(%d, 0x%08x)\r\n", count, pIrqs)); for(i = 0; i < count; i++) { #ifndef OAL_BSP_CALLBACKS irq = pIrqs[i]; #else irq = BSPIntrDisableIrq(pIrqs[i]); #endif if(irq == OAL_INTR_IRQ_UNDEFINED) continue; switch(irq) { case IRQ_RTC_ATI: OUTREG8(&pRTCRegs->RCR1, INREG8(&pRTCRegs->RCR1) & ~RTC_RCR1_AIE); OALMSG(OAL_INTR&&OAL_VERBOSE, (L"INFO: IRQ_RTC_ATI Disabled\r\n")); break; default: OALMSG(OAL_ERROR, (L"ERROR: Unable to disable IRQ %d\r\n", irq)); } } OALMSG(OAL_INTR&&OAL_VERBOSE, (L"-OALIntrDisableIrqs()\r\n")); }
uint8 ReadReg8(uint32 addr) { if (gInfo.sharedInfo->chipType == S3_TRIO64) return ReadPIO(addr, 1); return INREG8(addr); }
uint8 ReadMiscOutReg() { if (gInfo.sharedInfo->chipType == S3_TRIO64) return ReadPIO_8(0x3cc); return INREG8(0x83cc); }
void serial_putc (const char c) { #if 1 if (c == '\n') serial_putc ('\r'); /* Wait for fifo to shift out some bytes */ while ( !(INREG8((DEBUG_UART_BASE + UART_ULSR_OFFSET))&ULSR_TDRQ ) ); OUTREG8((DEBUG_UART_BASE + UART_UTHR_OFFSET), c); #endif }
//------------------------------------------------------------------------------ // // Function: OEMWriteDebugByte // // Write byte to debug serial port. // VOID OEMWriteDebugByte(UINT8 ch) { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); // wait FIFO empty while (!(INREG8(&pVRC5477Regs->UARTLSR0) & UART_LSR_THRE)); // send OUTREG8(&pVRC5477Regs->UARTTHR0, ch); }
uint8 ReadSeqReg(uint8 index) { if (gInfo.sharedInfo->chipType == S3_TRIO64) { WritePIO_8(0x3c4, index); return ReadPIO_8(0x3c5); } OUTREG8(0x83c4, index); return INREG8(0x83c5); }
/* * This routine could be implemented by taking the addresses * written to the GATT, and flushing them individually. However * currently it just flushes the whole table. Which is probably * more efficent, since agp_memory blocks can be a large number of * entries. */ static void serverworks_tlbflush(struct agp_memory *temp) { OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 1); while(INREG8(serverworks_private.registers, SVWRKS_POSTFLUSH) == 1) cpu_relax(); OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 1); while(INREG32(serverworks_private.registers, SVWRKS_DIRFLUSH) == 1) cpu_relax(); }
//------------------------------------------------------------------------------ // Start timer 2 (parameter - interrupt interval in micro-seconds) //------------------------------------------------------------------------------ void SHxStartTimer2 (DWORD dwUSec) { DWORD dwCount; volatile SH4_TMU_REGS *pTMURegs = OALPAtoUA(SH4_REG_PA_TMU); if (!dwUSec) { // // Use default rate (1 MS) // dwUSec = 1000; } else if (dwUSec < 20) { // // Rate specified: at least 20us // dwUSec = 20; } dwCount = (dwUSec * g_oalTimer.countsPerMSec) / 1000; // // Init timer2 and enable timer2 interrupt // // make sure timer2 is topped OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) & ~TMU_TSTR_STR2); // initialize timer constant and count register OUTREG32(&pTMURegs->TCOR2, dwCount); OUTREG32(&pTMURegs->TCNT2, dwCount); // enable timer2 interrupts // Enable underflow interrupts OUTREG16(&pTMURegs->TCR2, INREG16(&pTMURegs->TCR2) | TMU_TCR_UNIE); // Clear any pending interrupts OUTREG16(&pTMURegs->TCR2, INREG16(&pTMURegs->TCR2) & ~TMU_TCR_UNF); // start timer2 OUTREG8(&pTMURegs->TSTR, INREG8(&pTMURegs->TSTR) | TMU_TSTR_STR2); }
//////////////////////////////////////////////////// // 功能: codec 寄存器清除 // 输入: // 输出: // 返回: // 说明: //////////////////////////////////////////////////// static void codec_reg_clear(unsigned char addr, unsigned char data) { unsigned int temp = addr << RGADW_ADDR_BIT; AIC_RW_CODEC_START(); OUTREG16(AIC_RGADW, temp); temp |= (INREG8(AIC_RGDAT) & (~data)); OUTREG32(AIC_RGADW, temp); OUTREG32(AIC_RGADW, (temp | AIC_RGADW_RGWR)); AIC_RW_CODEC_STOP(); }
//------------------------------------------------------------------------------ // // Function: VRC5477Uart1Init // // Initialize debug serial port // BOOL VRC5477Uart1Init(KITL_SERIAL_INFO *pInfo) { BOOL rc = FALSE; VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); UINT16 divider; UINT8 lcr; // Check if config paramters are supportable if ( pInfo->baudRate < 9600 || pInfo->baudRate > 115200 || pInfo->dataBits != 8 || pInfo->stopBits == 0 || pInfo->parity > 2 ) goto cleanUp; // Input frequency is 1.8462MHz divider = (1846200/pInfo->baudRate + 7)/16; // Get LCR lcr = UART_LCR_8BIT; if (pInfo->stopBits > 1) lcr |= UART_LCR_2STP; if (pInfo->parity > 0) { lcr |= UART_LCR_PE; if (pInfo->parity > 1) lcr |= UART_LCR_EP; } // Disable interrupts OUTREG8(&pVRC5477Regs->UARTIER1, 0); // Set baud rate OUTREG8(&pVRC5477Regs->UARTLCR1, UART_LCR_DLAB); OUTREG8(&pVRC5477Regs->UARTDLL1, (UINT8)divider); OUTREG8(&pVRC5477Regs->UARTDLM1, (UINT8)(divider >> 8)); // 8 bit, 1 stop bit, no parity OUTREG8(&pVRC5477Regs->UARTLCR1, lcr); // Enable&reset FIFOs OUTREG8(&pVRC5477Regs->UARTFCR1, UART_FCR_EN|UART_FCR_RRST|UART_FCR_TRST); // Set DTR&RTS signals OUTREG8(&pVRC5477Regs->UARTMCR1, UART_MCR_DTR|UART_MCR_RTS); // Clear comm errors INREG8(&pVRC5477Regs->UARTLSR1); // Best size is full KITL_MTU... pInfo->bestSize = KITL_MTU; // Done rc = TRUE; cleanUp: return rc; }
void WriteSeqReg(uint8 index, uint8 value, uint8 mask) { // Write a value to a Sequencer reg using a mask. The mask selects the // bits to be modified. if (gInfo.sharedInfo->chipType == S3_TRIO64) { WritePIO_8(0x3c4, index); WritePIO_8(0x3c5, (ReadPIO_8(0x3c5) & ~mask) | (value & mask)); } else { OUTREG8(0x83c4, index); OUTREG8(0x83c5, (INREG8(0x83c5) & ~mask) | (value & mask)); } }
//------------------------------------------------------------------------------ // // Function: VRC5477Uart1Send // UINT16 VRC5477Uart1Send(UINT8 *pData, UINT16 size) { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); // This should not happen, but to be sure if (size == 0) return 0; // Wait FIFO empty while (!(INREG8(&pVRC5477Regs->UARTLSR1) & UART_LSR_THRE)); // Send OUTREG8(&pVRC5477Regs->UARTTHR1, *pData); // We send only one char per call return 1; }
static int hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap) { u16 status; u8 pos, id; int ttl = 48; status = INREG16(hpa, PCI_STATUS); if (!(status & PCI_STATUS_CAP_LIST)) return 0; pos = INREG8(hpa, PCI_CAPABILITY_LIST); while (ttl-- && pos >= 0x40) { pos &= ~3; id = INREG8(hpa, pos + PCI_CAP_LIST_ID); if (id == 0xff) break; if (id == cap) return pos; pos = INREG8(hpa, pos + PCI_CAP_LIST_NEXT); } return 0; }
//------------------------------------------------------------------------------ // // Function: VRC5477Uart1Recv // UINT16 VRC5477Uart1Recv(UINT8 *pData, UINT16 size) { VRC5477_REGS *pVRC5477Regs = OALPAtoUA(VRC5477_REG_PA); UINT8 status; UINT16 count; count = 0; while (count < size) { // Get line status status = INREG8(&pVRC5477Regs->UARTLSR1); // If there ara no data, break loop if ((status & UART_LSR_DR) == 0) break; // On error clear FIFOs and break loop if ((status & 0x0E) != 0) { OUTREG8(&pVRC5477Regs->UARTFCR1, 0x07); count = 0; break; } // Get data *pData++ = INREG8(&pVRC5477Regs->UARTRBR1); count++; } return count; }
/* * This routine could be implemented by taking the addresses * written to the GATT, and flushing them individually. However * currently it just flushes the whole table. Which is probably * more efficent, since agp_memory blocks can be a large number of * entries. */ static void serverworks_tlbflush(struct agp_memory *temp) { unsigned long end; OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); end = jiffies + 3*HZ; while(INREG8(serverworks_private.registers, SVWRKS_POSTFLUSH) == 0x01) { if((signed)(end - jiffies) <= 0) { printk(KERN_ERR PFX "Posted write buffer flush took more" "then 3 seconds\n"); } } OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001); end = jiffies + 3*HZ; while(INREG32(serverworks_private.registers, SVWRKS_DIRFLUSH) == 0x00000001) { if((signed)(end - jiffies) <= 0) { printk(KERN_ERR PFX "TLB flush took more" "then 3 seconds\n"); } } }
void serial_waitfinish() { while(!(INREG8((DEBUG_UART_BASE + UART_ULSR_OFFSET)) & ULSR_TEMP ) ); }
int serial_tstc (void) { /* Data in rfifo */ return (INREG8((DEBUG_UART_BASE + UART_ULSR_OFFSET)) & ULSR_DRY ); }
int serial_getc (void) { while (!serial_tstc()); return INREG8((DEBUG_UART_BASE + UART_URBR_OFFSET)); }
static void SetClockRegisters(const DisplayModeEx& mode) { SharedInfo& si = *gInfo.sharedInfo; M64_Params& params = si.m64Params; int p; int postDiv; bool extendedDiv = false; uint32 pixelClock = mode.timing.pixel_clock; if (pixelClock > params.maxPixelClock) pixelClock = params.maxPixelClock; double q = ((pixelClock / 10.0) * params.refDivider) / (2.0 * params.refFreq); if (si.chipType >= MACH64_264VTB) { if (q > 255) { TRACE("SetClockRegisters(): Warning: q > 255\n"); q = 255; p = 0; postDiv = 1; } else if (q > 127.5) { p = 0; postDiv = 1; } else if (q > 85) { p = 1; postDiv = 2; } else if (q > 63.75) { p = 0; postDiv = 3; extendedDiv = true; } else if (q > 42.5) { p = 2; postDiv = 4; } else if (q > 31.875) { p = 2; postDiv = 6; extendedDiv = true; } else if (q > 21.25) { p = 3; postDiv = 8; } else if (q >= 10.6666666667) { p = 3; postDiv = 12; extendedDiv = true; } else { TRACE("SetClockRegisters(): Warning: q < 10.66666667\n"); p = 3; postDiv = 12; extendedDiv = true; } } else { if (q > 255) { TRACE("SetClockRegisters(): Warning: q > 255\n"); q = 255; p = 0; } else if (q > 127.5) p = 0; else if (q > 63.75) p = 1; else if (q > 31.875) p = 2; else if (q >= 16) p = 3; else { TRACE("SetClockRegisters(): Warning: q < 16\n"); p = 3; } postDiv = 1 << p; } uint8 fbDiv = uint8(q * postDiv); // With some chips such as those with ID's 4750 & 475A, the display has // ripples when using resolution 1440x900 at 60 Hz refresh rate. // Decrementing fbDiv by 1 seems to fix this problem. if (mode.timing.h_display == 1440 && pixelClock < 108000) fbDiv--; int clkNum = params.clockNumberToProgram; OUTREG8(CLOCK_CNTL, clkNum | CLOCK_STROBE); // Temporarily switch to accelerator mode. uint32 crtc_gen_cntl = INREG(CRTC_GEN_CNTL); if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN)) OUTREG(CRTC_GEN_CNTL, crtc_gen_cntl | CRTC_EXT_DISP_EN); // Reset VCLK generator. uint8 vclkCntl = Mach64_GetPLLReg(PLL_VCLK_CNTL); Mach64_SetPLLReg(PLL_VCLK_CNTL, vclkCntl | PLL_VCLK_RESET); // Set post-divider. uint8 tmp = Mach64_GetPLLReg(PLL_VCLK_POST_DIV); Mach64_SetPLLReg(PLL_VCLK_POST_DIV, (tmp & ~(0x03 << (2 * clkNum))) | (p << (2 * clkNum))); // Set feedback divider. Mach64_SetPLLReg(PLL_VCLK0_FB_DIV + clkNum, fbDiv); // Set extended post-divider. if (si.chipType >= MACH64_264VTB) { tmp = Mach64_GetPLLReg(PLL_XCLK_CNTL); if (extendedDiv) Mach64_SetPLLReg(PLL_XCLK_CNTL, tmp | (0x10 << clkNum)); else Mach64_SetPLLReg(PLL_XCLK_CNTL, tmp & ~(0x10 << clkNum)); } // End VCLK generator reset. Mach64_SetPLLReg(PLL_VCLK_CNTL, vclkCntl & ~PLL_VCLK_RESET); snooze(5000); INREG8(DAC_W_INDEX); // Clear DAC counter if (!(crtc_gen_cntl & CRTC_EXT_DISP_EN)) OUTREG(CRTC_GEN_CNTL, crtc_gen_cntl); // Restore register // Save parameters that will be used for computing the DSP parameters. params.vClkPostDivider = postDiv; params.vClkFeedbackDivider = fbDiv; return; }