int do_irq(unsigned r0, unsigned r1, unsigned r2, unsigned r3) { int vec; int intno; int timerctrl; vec = in_w(HW_ICOLL_VECTOR); out_w(HW_ICOLL_VECTOR, 0); intno = in_w(HW_ICOLL_STAT); putchar('\n'); printk("CPSR(irq): %X\n", r0); printk("CPSR(blx): %X\n", r1); printk("irq no: %d\n", intno); printk("vecisr: %x\n", vec); timerctrl = in_w(HW_TIMROT_TIMCTRL1); printk("timer-ctrl: %016b\n", timerctrl); out_w(HW_TIMROT_TIMCTRL1, timerctrl); out_w(HW_TIMROT_TIMCTRL1_CLR, 1<<15); out_w(HW_ICOLL_LEVELACK, 0x1); // out_w(HW_ICOLL_LEVELACK, 0x2); // out_w(HW_ICOLL_LEVELACK, 0x4); // out_w(HW_ICOLL_LEVELACK, 0x8); }
int do_fiq(int r0, int r1, int r2, int r3) { static int rand = 0; int vec; rand++; void (*isr)(); isr = (void *)in_w(0x80000000); printk("isr:%d\n", isr); printk("lr:[%x]\n", r0); vec = in_w(0x80000070); printk("irq line: [%d]\n", vec); out_w(0x80000010, 0x1); printk("levelack!\n"); return 0; }
int hw_icoll_raw(int irq) { int irq_raw[4]; irq_raw[0] = in_w(HW_ICOLL_RAW0); irq_raw[1] = in_w(HW_ICOLL_RAW1); irq_raw[2] = in_w(HW_ICOLL_RAW2); irq_raw[3] = in_w(HW_ICOLL_RAW3); return irq_raw[irq/32] & (1 << (irq%32)); }
void sio_recv_frame(unsigned char *buf, int size) { while (size > 0) { /* Wait until there is data in the FIFO */ while (in_w(PL011_STAT) & 0x00000010U) { /* NOP */ } *buf = (unsigned char)in_w(PL011_IO); ++buf; --size; } }
ACPI_STATUS AcpiOsReadPort ( ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width) { switch (Width) { case 8: *Value = in_b((uint16_t)Address); break; case 16: *Value = in_h((uint16_t)Address); break; case 32: *Value = in_w((uint16_t)Address); break; default: return (AE_BAD_PARAMETER); } return (AE_OK); }
/* * Memory block inputs (32 bit) cnt : number of words */ EXPORT void InMemW(UW iob, W ix, UW *buf, W cnt) { UW port = iob + (ix * IOSTEP); while (--cnt >= 0) { *buf++ = in_w(port); } }
/* wait for data of SPI for PMIC communication */ LOCAL void pmicWait(void) { W i; for (i = 1000000; i > 0; i--) { if (in_w(SPn_RAW_STATUS(SP0)) & 0x0004) break; waitUsec(1); } if (!i) pmicInit(); return; }
void sio_send_frame(unsigned char const *buf, int size) { while (size > 0) { /* Wait until there is space in the FIFO */ while (in_w(PL011_STAT) & 0x00000020U) { /* NOP */ } out_w(PL011_IO, *buf); ++buf; --size; } }
/* I/O read */ EXPORT W readIO(UW addr, UW *data, W unit) { W n; UW pa; /* address misalignment is reported as error */ if (addr & (unit - 1)) return 0; /* I/O address check & conversion to physical address */ n = chkIOAddr(addr, &pa, unit); if (n < unit) return 0; switch(unit) { case 4: *data = in_w(pa); break; case 2: *data = in_h(pa); break; default: *data = in_b(pa); } return unit; }
/* read PMIC register */ EXPORT W pmicRead(W reg) { W dat; pmicCSassert(TRUE); /* CS assert */ out_w(SPn_FFCLR(SP0), ~0); /* status flag is cleared */ out_w(SPn_TX_DATA(SP0), (reg << 1) | 1); /* send register number */ out_w(SPn_CONTROL(SP0), 0x0009); /* send start */ pmicWait(); out_w(SPn_FFCLR(SP0), ~0); /* status flag is cleared */ out_w(SPn_CONTROL(SP0), 0x0005); /* start receive */ pmicWait(); dat = in_w(SPn_RX_DATA(SP0)); /* data received */ pmicCSassert(FALSE); /* CS de-assert */ return dat; }
/** Function 01h - Return VBE Mode Information * * Input: * AX = 4F01h * CX = Mode Number * ES:DI = Pointer to buffer in which to place ModeInfoBlock structure * Output: * AX = VBE Return Status * */ void vbe_biosfn_return_mode_information(uint16_t STACK_BASED *AX, uint16_t CX, uint16_t ES, uint16_t DI) { uint16_t result = 0x0100; #ifdef VBE_NEW_DYN_LIST uint16_t cur_info_ofs; #else ModeInfoListItem *cur_info; #endif Boolean using_lfb; uint8_t win_attr; #ifdef VGA_DEBUG printf("VBE vbe_biosfn_return_mode_information ES%x DI%x CX%x\n",ES,DI,CX); #endif using_lfb = ((CX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER); CX = (CX & 0x1ff); #ifdef VBE_NEW_DYN_LIST cur_info_ofs = mode_info_find_mode(CX, using_lfb); if (cur_info_ofs) { uint16_t i; #else cur_info = mode_info_find_mode(CX, using_lfb); if (cur_info != 0) { #endif #ifdef VGA_DEBUG printf("VBE found mode %x\n",CX); #endif memsetb(ES, DI, 0, 256); // The mode info size is fixed #ifdef VBE_NEW_DYN_LIST for (i = 0; i < sizeof(ModeInfoBlockCompact); i++) { uint8_t b; b = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info) + i/*(char *)(&(cur_info->info)) + i*/); write_byte(ES, DI + i, b); } #else memcpyb(ES, DI, 0xc000, &(cur_info->info), sizeof(ModeInfoBlockCompact)); #endif win_attr = read_byte(ES, DI + offsetof(ModeInfoBlock, WinAAttributes)); if (win_attr & VBE_WINDOW_ATTRIBUTE_RELOCATABLE) { write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr), (uint16_t)(dispi_set_bank_farcall)); // If BIOS not at 0xC000 -> boom write_word(ES, DI + offsetof(ModeInfoBlock, WinFuncPtr) + 2, 0xC000); } // Update the LFB physical address which may change at runtime out_w(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_FB_BASE_HI); write_word(ES, DI + offsetof(ModeInfoBlock, PhysBasePtr) + 2, in_w(VBE_DISPI_IOPORT_DATA)); result = 0x4f; } else { #ifdef VGA_DEBUG printf("VBE *NOT* found mode %x\n",CX); #endif result = 0x100; } *AX = result; } /** Function 02h - Set VBE Mode * * Input: * AX = 4F02h * BX = Desired Mode to set * ES:DI = Pointer to CRTCInfoBlock structure * Output: * AX = VBE Return Status * */ void vbe_biosfn_set_mode(uint16_t STACK_BASED *AX, uint16_t BX, uint16_t ES, uint16_t DI) { uint16_t result; #ifdef VBE_NEW_DYN_LIST uint16_t cur_info_ofs; #else ModeInfoListItem *cur_info; #endif Boolean using_lfb; uint8_t no_clear; uint8_t lfb_flag; using_lfb = ((BX & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER); lfb_flag = using_lfb ? VBE_DISPI_LFB_ENABLED : 0; no_clear = ((BX & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY) ? VBE_DISPI_NOCLEARMEM : 0; BX = (BX & 0x1ff); // check for non vesa mode if (BX < VBE_MODE_VESA_DEFINED) { uint8_t mode; dispi_set_enable(VBE_DISPI_DISABLED); // call the vgabios in order to set the video mode // this allows for going back to textmode with a VBE call (some applications expect that to work) mode = (BX & 0xff); biosfn_set_video_mode(mode); result = 0x4f; goto leave; } #ifdef VBE_NEW_DYN_LIST cur_info_ofs = mode_info_find_mode(BX, using_lfb); if (cur_info_ofs != 0) { uint16_t xres, yres; uint8_t bpp; xres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.XResolution) /*&cur_info->info.XResolution*/); yres = in_word(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.YResolution) /*&cur_info->info.YResolution*/); bpp = in_byte(VBE_EXTRA_PORT, cur_info_ofs + offsetof(ModeInfoListItem, info.BitsPerPixel) /*&cur_info->info.BitsPerPixel*/); #ifdef VGA_DEBUG printf("VBE found mode %x, setting:\n", BX); printf("\txres%x yres%x bpp%x\n", xres, yres, bpp); #endif #else cur_info = mode_info_find_mode(BX, using_lfb); if (cur_info != 0) { #ifdef VGA_DEBUG printf("VBE found mode %x, setting:\n", BX); printf("\txres%x yres%x bpp%x\n", cur_info->info.XResolution, cur_info->info.YResolution, cur_info->info.BitsPerPixel); #endif #endif // VBE_NEW_DYN_LIST // first disable current mode (when switching between vesa modi) dispi_set_enable(VBE_DISPI_DISABLED); #ifdef VBE_NEW_DYN_LIST if (bpp == 4) #else if (cur_info->info.BitsPerPixel == 4) #endif { biosfn_set_video_mode(0x6a); } #ifdef VBE_NEW_DYN_LIST dispi_set_bpp(bpp); dispi_set_xres(xres); dispi_set_yres(yres); #else dispi_set_bpp(cur_info->info.BitsPerPixel); dispi_set_xres(cur_info->info.XResolution); dispi_set_yres(cur_info->info.YResolution); #endif dispi_set_bank(0); dispi_set_enable(VBE_DISPI_ENABLED | no_clear | lfb_flag); vga_compat_setup(); write_word(BIOSMEM_SEG,BIOSMEM_VBE_MODE,BX); write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60 | no_clear)); result = 0x4f; } else { #ifdef VGA_DEBUG printf("VBE *NOT* found mode %x\n" , BX); #endif result = 0x100; } leave: *AX = result; } uint16_t vbe_biosfn_read_video_state_size(void) { return 9 * 2; } void vbe_biosfn_save_video_state(uint16_t ES, uint16_t BX) { uint16_t enable, i; outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE); enable = inw(VBE_DISPI_IOPORT_DATA); write_word(ES, BX, enable); BX += 2; if (!(enable & VBE_DISPI_ENABLED)) return; for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) { if (i != VBE_DISPI_INDEX_ENABLE) { outw(VBE_DISPI_IOPORT_INDEX, i); write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA)); BX += 2; } } }
void start_timer(unsigned r0, unsigned r1, unsigned r2, unsigned r3) { int val; int i; #define BIT(n) (1<<n) #define BITTST(val, n) ((val) & BIT(n)) #define TST(val, b) ((val) & (b)) hw_timer_rotary[0] = (void *)(0x80068000); /* have ROTCTRL */ hw_timer_rotary[1] = (void *)(0x80068050); hw_timer_rotary[2] = (void *)(0x80068080); hw_timer_rotary[3] = (void *)(0x800680C0); val = hw_timer_rotary[0]->HW_TIMROT_ROTCTRL[0]; printk("This SoC has:\n"); if(BITTST(val,25)) printk("timer 0\n"); if(BITTST(val,26)) printk("timer 1\n"); if(BITTST(val,27)) printk("timer 2\n"); if(BITTST(val,28)) printk("timer 3\n"); #define IRQ (1<<15) #define IRQ_EN (1<<14) #define MATCH_MODE (1<<11) #define POLARITY (1<<8) #define UPDATE (1<<7) #define RELOAD (1<<6) #define PRESCALE(n) ((n)<<4) #define DIV_BY_8 (0x3) #define SELECT(n) ((n)<<0) #define TICK_ALWAYS (0XF) #define SET 1 #define CLR 2 #define TOG 3 hw_timer_rotary[1]->HW_TIMROT_FIXED_COUNT[0] = 0x00011000; val = IRQ_EN | UPDATE | RELOAD | PRESCALE(TICK_ALWAYS) | SELECT(0xB); out_w(HW_TIMROT_TIMCTRL1, val); while(1){ static int random = 0; random++; printk("[%04d]wait timer1 irq\n", random); waitMsec(100); val = hw_timer_rotary[1]->HW_TIMROT_TIMCTRL[0]; printk("%016b\n", val); val = in_w(HW_TIMROT_RUNNING_COUNT1); printk("timer running @[0x%x]\n", val); val = in_w(HW_TIMROT_VERSION); printk("timer version @[%X]\n", val); if(random>300) break; } printk("Goodbye TIMER!\n"); }
/* * Interrupt handler definition */ SYSCALL ER _tk_def_int( UINT dintno, T_DINT *pk_dint ) { FP inthdr; INT vecno = dintno >> 5; INTMASKTBL *ptr; CHECK_PAR(vecno < MAX_INTVEC); if ( pk_dint != NULL ) { /* Set interrupt handler */ if ( vecno == VECNO_TLBMISS ) { CHECK_RSATR(pk_dint->intatr, 0); } else { CHECK_RSATR(pk_dint->intatr, TA_HLNG | TA_ASSPRC); } #if CHK_PAR if ( (pk_dint->intatr & TA_ASSPRC) != 0 ) { if ( !chk_assprc(pk_dint->assprc) ) { return E_PAR; } } #endif inthdr = pk_dint->inthdr; BEGIN_CRITICAL_SECTION; if ( (pk_dint->intatr & TA_HLNG) != 0 ) { hll_inthdr[vecno] = inthdr; inthdr = ( vecno == VECNO_DEFAULT )? defaulthdr_startup: inthdr_startup; } define_inthdr(vecno, inthdr); if ( (pk_dint->intatr & TA_ASSPRC) != 0 ) { if ( vecno < N_INTVEC) { ptr = &intmasktable[vecno]; if ( ptr->mask != 0) { if ( pk_dint->assprc & TP_PRC1 ) { out_w(ptr->maskaddr[1], in_w(ptr->maskaddr[1]) | ptr->mask); out_w(clraddr(ptr->maskaddr[0]), ptr->mask); } else if ( pk_dint->assprc & TP_PRC2 ) { out_w(ptr->maskaddr[0], in_w(ptr->maskaddr[0]) | ptr->mask); out_w(clraddr(ptr->maskaddr[1]), ptr->mask); } } } } END_CRITICAL_NO_DISPATCH; } else { /* Free interrupt handler */ switch ( vecno ) { case VECNO_TRAPA: inthdr = SaveMonHdr.trapa_hdr; break; case VECNO_BREAK: inthdr = SaveMonHdr.break_hdr; break; case VECNO_MONITOR: inthdr = SaveMonHdr.monitor_hdr; break; case VECNO_DEFAULT: inthdr = SaveMonHdr.default_hdr; break; case VECNO_TLBMISS: inthdr = SaveMonHdr.tlbmiss_hdr; break; default: inthdr = NULL; } BEGIN_CRITICAL_SECTION; define_inthdr(vecno, inthdr); if ( vecno < MAX_INTVEC ) { hll_inthdr[vecno] = NULL; } if ( vecno < N_INTVEC) { ptr = &intmasktable[vecno]; if ( ptr->mask != 0) { out_w(ptr->maskaddr[0], in_w(ptr->maskaddr[0]) | ptr->mask); out_w(ptr->maskaddr[1], in_w(ptr->maskaddr[1]) | ptr->mask); } } END_CRITICAL_NO_DISPATCH; } return E_OK; }