/*************************************** * Legacy devices are mapped to LPC space. * serial port 0 * KBC Port * ACPI Micro-controller port * LPC ROM size, * NOTE: Call me ASAP, because I will reset LPC ROM size! * NOTE : by general, it is called after HT emulation ***************************************/ void sb600_lpc_init(void) { u8 reg8; u32 reg32; pcitag_t sm_dev = _pci_make_tag(0, 20, 0); pcitag_t lpc_dev = _pci_make_tag(0, 20, 3); /* Enable lpc controller */ reg32 = _pci_conf_read(sm_dev, 0x64); reg32 |= 0x00100000; _pci_conf_write(sm_dev, 0x64, reg32); /* Serial 0 : 0x3f8~0x3ff */ reg8 = _pci_conf_readn(lpc_dev, 0x44, 1); reg8 |= (1 << 6); _pci_conf_writen(lpc_dev, 0x44, reg8, 1); /* PS/2 keyboard, ACPI : 0x60/0x64 & 0x62/0x66 */ reg8 = _pci_conf_readn(lpc_dev, 0x47, 1); reg8 |= (1 << 5) | (1 << 6); _pci_conf_writen(lpc_dev, 0x47, reg8, 1); /* SuperIO, LPC ROM */ reg8 = _pci_conf_readn(lpc_dev, 0x48, 1); reg8 |= (1 << 1) | (1 << 0); /* enable Super IO config port 2e-2h, 4e-4f */ reg8 |= (1 << 3) | (1 << 4); /* enable for LPC ROM address range1&2, Enable 512KB rom access at 0xFFF80000 - 0xFFFFFFFF */ reg8 |= 1 << 6; /* enable for RTC I/O range */ _pci_conf_writen(lpc_dev, 0x48, reg8, 1); /* hardware should enable LPC ROM by pin strapes */ /* rom access at 0xFFF80000/0xFFF00000 - 0xFFFFFFFF */ /* See detail in BDG-215SB600-03.pdf page 15. */ _pci_conf_writen(lpc_dev, 0x68, 0x000e, 2); /* enable LPC ROM range, 0xfff8: 512KB, 0xfff0: 1MB; */ _pci_conf_writen(lpc_dev, 0x6c, 0xfff0, 2); /* enable LPC ROM range, 0xfff8: 512KB, 0xfff0: 1MB */ }
void ExitMBPnP(void) { pcitag_t tag; char confval,val; tag=_pci_make_tag(VTSB_BUS,VTSB_DEV, VTSB_ISA_FUNC); confval=_pci_conf_readn(tag,SUPERIO_CFG_REG,1); _pci_conf_writen(tag,SUPERIO_CFG_REG,confval&~2,1); }
int pci_read_config_byte(struct pci_device *linuxpd, int reg, u8 *val) { if (reg < 0 || reg >= 0x100) { printf ("pci_write_config_word: bad reg %x\n", reg); return -1; } *val=_pci_conf_readn(linuxpd->pa.pa_tag,reg,1); return 0; }
int pci_read_config_word(struct pci_device *linuxpd, int reg, u16 *val) { if ((reg & 1) || reg < 0 || reg >= 0x100) { printf ("pci_read_config_word: bad reg %x\n", reg); return -1; } *val=_pci_conf_readn(linuxpd->pa.pa_tag,reg,2); return 0; }
/* Get SB ASIC Revision.*/ u8 get_sb600_revision(void) { pcitag_t sb_dev = _pci_make_tag(0, 0x14, 0); u8 rev; u32 reg32; rev = _pci_conf_readn(sb_dev, 0x08, 1); if(rev >= REV_SB600_A13){ reg32 = _pci_conf_read(sb_dev, 0x70); reg32 |= 1 << 8; _pci_conf_write(sb_dev, 0x70, reg32); rev = _pci_conf_readn(sb_dev, 0x08, 1); reg32 &= ~(1 << 8); _pci_conf_write(sb_dev, 0x70, reg32); } return rev; }
void sb600_pci_port80(void) { u8 byte; u32 dev; /* P2P Bridge */ dev = _pci_make_tag(0, 20, 4); // pay attention to the seq of this two regs. byte = _pci_conf_readn(dev, 0x40, 1); byte |= 1 << 5; // enable PCI bridge substractive decode _pci_conf_writen(dev, 0x40, byte, 1); byte = _pci_conf_readn(dev, 0x4B, 1); byte |= 1 << 7; // enable substractive decode function _pci_conf_writen(dev, 0x4B, byte, 1); byte = _pci_conf_readn(dev, 0x1C, 1); byte |= 0xF << 4; // manually define the IO base of PCI bridge? _pci_conf_writen(dev, 0x1C, byte, 1); byte = _pci_conf_readn(dev, 0x1D, 1); byte |= 0xF << 4; // manually define the IO limit of PCI bridge _pci_conf_writen(dev, 0x1D, byte, 1); byte = _pci_conf_readn(dev, 0x04, 1); byte |= 1 << 0; // enable IO space _pci_conf_writen(dev, 0x04, byte, 1); /* LPC bridge */ dev = _pci_make_tag(0, 20, 3); byte = _pci_conf_readn(dev, 0x4A, 1); byte &= ~(1 << 5); /* disable lpc port 80 */ _pci_conf_writen(dev, 0x4A, byte, 1); }
void sb600_lpc_port80(void) { u8 byte; u32 dev; u32 reg32; /* enable lpc controller */ dev = _pci_make_tag(0, 20, 0); reg32 = _pci_conf_read(dev, 0x64); reg32 |= 0x00100000; /* lpcEnable */ _pci_conf_write(dev, 0x64, reg32); /* enable prot80 LPC decode in pci function 3 configuration space. */ dev = _pci_make_tag(0, 20, 3); byte = _pci_conf_readn(dev, 0x4a, 1); byte |= 1 << 5; /* enable port 80 */ _pci_conf_writen(dev, 0x4a, byte, 1); }
void sb_last_init(void) { pcitag_t sm_dev; u16 sm_id; DEBUG_INFO("\n+++++++++++++++++SB LAST STAGE : start with type(0x%x), revision(0x%x)++++++++++++++++++++++++++\n", get_sb600_platform(), get_sb600_revision()); /* judge the device : liujl ??? */ sm_dev = _pci_make_tag(0, 20, 0); sm_id = _pci_conf_readn(sm_dev, 0x02, 2); if(sm_id != SB600_DEVICE_ID){ if(sm_id != 0x43C5){ DEBUG_INFO("SB LAST STAGE : out with ID mismatch (0x%x) match(0x%x)\n", sm_id, SB600_DEVICE_ID); //while(1); } } DEBUG_INFO("SB LAST STAGE : ID judge 0x%x\n", sm_id); sb_last_post_setting(); sb_last_c3_popup_setting(); sb_last_c3_popup_next_setting(); sb_last_p4_init(); sb_last_am97_init(); sb_last_sata_unconnected_shutdown_clock(); sb_last_cmos_init(); // sb_last_sata_cache(); // sb_last_sata_init(); sb_last_init_pci_autoclock_run(); sb_last_smi_service_check(); DEBUG_INFO("---------------------------------- SB LAST STAGE DONE---------------------------------------\n"); return; }
void sb_last_init_pci_autoclock_run(void) { u32 val; pcitag_t dev = _pci_make_tag(0, 20, 4); PRINTF_DEBUG(); _pci_conf_write(dev, 0x4C, ati_sb_cfg.clkrun_ctrl); val = _pci_conf_readn(dev, 0x50, 2); val &= 0x3F; val |= ati_sb_cfg.clkrun_ow << 6; _pci_conf_writen(dev, 0x50, val, 2); if(ati_sb_cfg.clkrun_ctrl == 1){ set_sbcfg_enable_bits(dev, 0x64, 1 << 15, 1 << 15); } return; }
/* * sata_drive_detect : * detect the sata drive and put it into proper config */ static void sata_drive_detecting(void) { int ports = 4, count; int timeout; u32 base, reg32, reg04; u32 val; pcitag_t sata_dev = _pci_make_tag(0, 18, 0); PRINTF_DEBUG(); reg04 = _pci_conf_read(sata_dev, 0x04); /* force memory and io enabled */ set_sbcfg_enable_bits(sata_dev, 0x04, 0x03 << 0, 0x03 << 0); /* ahci base addr */ base = (_pci_conf_read(sata_dev, 0x24) & 0xfffffff0) | 0xA0000000; DEBUG_INFO("ahci base addr is %x \n", base); /* 4/PM 3/SM 2/PS 1/SS */ while(ports){ count = 3; while(count){ /* judge is the phy and communication is ok */ delay(1000); // delay 1 ms reg32 = *(volatile u32 *)(base + 0x128); DEBUG_INFO("sata status : reg128 0x%x\n", reg32); if((reg32 & 0x0000000F) == 0x03){ goto drive_is_stable; } /* test if bsy bit is set, it means the drive is connected */ reg32 = *(volatile u32 *)(base + 0x120); if((reg32 & 0x80) == 0){ val = *(volatile u32 *)(base + 0x128); if((val & 0x0f) != 0x1){ goto drive_is_stable; } } count--; } /* now drive is not stable even after waitting for 1 sec,so downgrade to GEN 1 */ reg32 = *(volatile u32 *)(base + 0x12C); if((reg32 & 0x0f) == 0x10){ goto drive_is_stable; // jump if already GEN1 } /* store the sata status */ ati_sb_cfg.sb600_sata_sts |= (0x8 << ports); /* set to GEN1 : reset the status*/ reg32 = *(volatile u32 *)(base + 0x12C); reg32 = (reg32 & 0x0f) | 0x10; *(volatile u32 *)(base + 0x12C) = reg32; reg32 |= 0x01; *(volatile u32 *)(base + 0x12C) = reg32; // force 00B delay(1000); //wait 1 ms reg32 = *(volatile u32 *)(base + 0x12C); reg32 &= 0xfe; *(volatile u32 *)(base + 0x12C) = reg32; /* re detect the device again */ ports--; continue; drive_is_stable: reg32 = *(volatile u32 *)(base + 0x128); if ((reg32 & 0x0f) == 0x3){ u16 sata_bar; sata_bar = _pci_conf_readn(sata_dev, 0x10, 2); if(ports & 0x01){ sata_bar = _pci_conf_readn(sata_dev, 0x18, 2); } sata_bar &= ~(7); sata_bar += 0x06; if(ports <= 2){ val |= 0xA0; }else{ val |= 0xB0; } linux_outb(val, sata_bar); sata_bar++; timeout = 3000; while(timeout--){ val = linux_inb(sata_bar); val &= 0x88000000; if(val == 0x00){ break; } delay(10 * 1000); } /* update the status */ ati_sb_cfg.sb600_sata_sts ^= (1 << (4 - ports)); } base += 0x80; // increase status offset by 80h for next port --ports; } /* while(i) */ /* restore PCI conf cmd */ _pci_conf_write(sata_dev, 0x04, reg04); return; }
/* Get SB ASIC platform Revision.*/ u8 get_sb600_platform(void) { pcitag_t sb_dev = _pci_make_tag(0, 0x14, 0); return _pci_conf_readn(sb_dev, 0x34, 1); }