/*************************************** * 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_write_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; } _pci_conf_writen(linuxpd->pa.pa_tag,reg,val,1); return 0; }
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 sb_last_post_setting(void) { u8 rev = get_sb600_revision(); pcitag_t pcib_dev; PRINTF_DEBUG(); if(rev == REV_SB600_A11){ update_hpet_table(); } if(rev == REV_SB600_A12){ /* clear HPET ECC */ set_pm_enable_bits(0x9A, 1 << 7, 0 << 7); } if(rev >= REV_SB600_A13){ /* clear HPET ECC */ set_pm_enable_bits(0x9A, 1 << 7, 0 << 7); /* enable load new value for HPET */ set_pm_enable_bits(0x9F, 1 << 5, 1 << 5); /* make HPET revision id to be 0x01 */ set_pm_enable_bits(0x9E, (1 << 6) | (1 << 7), (1 << 6) | (1 << 7)); } if(ati_sb_cfg.hpet_en == SB_DISABLE){ update_hpet_table(); } /* RPR4.5 Master Latency Timer PCIB_PCI_config 0x0D/0x1B = 0x40 * Enables the PCIB to retain ownership of the bus on the * Primary side and on the Secondary side when GNT# is deasserted. */ pcib_dev = _pci_make_tag(0, 20, 4); _pci_conf_writen(pcib_dev, 0x0D, 0x40, 1); _pci_conf_writen(pcib_dev, 0x1B, 0x40, 1); return; }
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_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; }
/* * sb_sata_init : * sb sata init, for real device init and make it available */ void sb_sata_init(void) { pcitag_t sm_dev = _pci_make_tag(0, 20, 0); pcitag_t ide_dev = _pci_make_tag(0, 20, 1); pcitag_t sata_dev = _pci_make_tag(0, 18, 0); u32 port_phy; u8 port_bist; u32 reg04; u32 sata_bar5; u8 rev, class; /* enable the sata controller according to config */ if(ati_sb_cfg.sata_smbus == SB_ENABLE){ // enable set_sbcfg_enable_bits(sm_dev, 0xAD, 1 << 1, 0 << 1); }else{ // disable set_sbcfg_enable_bits(sm_dev, 0xAD, 1 << 1, 1 << 1); } /* enable proper SATA channel based on config : '0' none, '1' SATA1 */ if(ati_sb_cfg.sata_channel == SB_DISABLE){ // disable SATA1 set_sbcfg_enable_bits(sm_dev, 0xAD, 1 << 0, 0 << 0); }else{ // enable SATA1 & set power saving mode set_sbcfg_enable_bits(sm_dev, 0xAD, (1 << 0) | (1 << 5), (1 << 0) | (1 << 5)); } /* BIT4 : disable fast boot * BIT0 : enable write subsystem id */ set_sbcfg_enable_bits(sata_dev, 0x40, (1 << 0) | (1 << 4), (1 << 0) | (1 << 4)); /* disable SATA MSI cap */ set_sbcfg_enable_bits(sata_dev, 0x40, 1 << 23, 1 << 23); /* disable IDP cap */ if(rev <= REV_SB600_A21){ set_sbcfg_enable_bits(sata_dev, 0x40, 1 << 25, 1 << 25); } /* setting device class */ class = ati_sb_cfg.sata_class; if(class == 3){ /* IDE native mode setting */ set_sbcfg_enable_bits(ide_dev, 0x08, 0xFF << 8, 0x8F << 8); } /* SATA class mode setting */ _pci_conf_write(sata_dev, 0x08, sata_class_table[class]); /* disable SATA class write */ set_sbcfg_enable_bits(sata_dev, 0x40, 1 << 0, 0 << 0); /* program wdt with 16 retries before timer timeout */ set_sbcfg_enable_bits(sata_dev, 0x44, 0xff << 16, 0x10 << 16); if(rev == REV_SB600_A11){ /* PHY global tuning x86 to 0x2400 */ _pci_conf_writen(sata_dev, 0x86, 0x2400, 2); /* PHY tuning for ports */ port_phy = 0x00B420D8; port_bist = 0x00; }else{ /* PHY global tuning x86 to 0x2400 */ _pci_conf_writen(sata_dev, 0x86, 0x2c00, 2); if(rev == REV_SB600_A12){ port_phy = 0x00B4005A; port_bist = 0xB8; }else if(rev == REV_SB600_A13){ port_phy = 0x00B401DA; port_bist = 0xB8; if(ati_sb_cfg.sata_phy_avdd == SB_ENABLE){ // phy AVDD is 1.25V port_phy = 0x00B401D5; port_bist = 0x78; } }else{ port_phy = 0x00B401D6; port_bist = 0xB8; } } /* tuning 4 ports phy */ _pci_conf_write(sata_dev, 0x88, port_phy); _pci_conf_write(sata_dev, 0x8C, port_phy); _pci_conf_write(sata_dev, 0x90, port_phy); _pci_conf_write(sata_dev, 0x94, port_phy); _pci_conf_writen(sata_dev, 0xA5, port_bist, 1); _pci_conf_writen(sata_dev, 0xAD, port_bist, 1); _pci_conf_writen(sata_dev, 0xB5, port_bist, 1); _pci_conf_writen(sata_dev, 0xBD, port_bist, 1); /* port reset */ delay(1000); // delay 1ms /* get sata bar5 base address */ reg04 = _pci_conf_read(sata_dev, 0x04); if( (_pci_conf_read(sata_dev, 0x24) & 0xfffffff0) == 0 ){ _pci_conf_write(sata_dev, 0x24, TEMP_SATA_BAR5_BASE); sata_bar5 = TEMP_SATA_BAR5_BASE | 0xA0000000; }else{ sata_bar5 = (_pci_conf_read(sata_dev, 0x24) & 0xfffffff0) | 0xA0000000; } /* enable io/mem access */ set_sbcfg_enable_bits(sata_dev, 0x04, (1 << 0) | (1 << 1), (1 << 0) | (1 << 1)); /* RPR 6.10 Hide Support-Aggressive-Link-Power-Management Capability * in AHCI HBA Capabilities Register (For all SB600) * 1. SATA_PCI_config 0x40 [0] = 1 * Unlocks configuration register so that HBA AHCI Capabilities Register * can be modified. * 2. SATA_BAR5 + 0xFC [11] = 0 * (CFG_CAP_SALP Disabled) Clearing this bit has the following effects: * Support-Aggressive-Link-Power-Management Capability is hidden from * software in AHCI HBA Capabilities Register. * As a result,;software will not enable the HBA to aggressively enter * power-saving (Partial/Slumber) mode. * 6.12 Hiding Slumber and Partial State Capabilities in AHCI HBA Capabilities * Register * 2. SATA_BAR5 + 0xFC [27] = 1 (CFG_CAP_SALP Disabled) * 3. SATA_PCI_config 0x40 [0]= 0 * Clears the bit to lock configuration registers so that AHCI HBA * Capabilities Register is read-only. */ set_sbcfg_enable_bits(sata_dev, 0x40, 1 << 0, 1 << 0); *(volatile u32 *)(sata_bar5 + 0xFC) &= ~(1 << 11); *(volatile u32 *)(sata_bar5 + 0xFC) |= 1 << 27; if(ati_sb_cfg.sata_port_mult_cap != SB_ENABLE){ *(volatile u32 *)(sata_bar5 + 0xFC) &= ~(1 << 12); } if(rev >= REV_SB600_A21){ if(ati_sb_cfg.sata_hot_plug_cap != SB_ENABLE){ *(volatile u32 *)(sata_bar5 + 0xFC) &= ~(1 << 17); } } set_sbcfg_enable_bits(sata_dev, 0x40, 1 << 0, 0 << 0); /* RPR6.11 Disabling SATA Interface Partial/Slumber States Power Management * Transitions (For all SB600 ) * Port0: SATA_BAR5 + 0x12C[11:08] = 0x03 * Port1: SATA_BAR5 + 0x1AC[11:08] = 0x03 * Port2: SATA_BAR5 + 0x22C[11:08] = 0x03 * Port3: SATA_BAR5 + 0x2AC[11:08] = 0x03 * Setting PxSCTL (Port X Serial ATA Control) register bits[11:8] (PxSCTL.IPM) * to 0x03 will disable interface power management states, * both Partial and Slumber. HBA is not allowed to initiate these two states, * and HBA must PMNAK any request from device to enter these states. */ *(volatile u32 *)(sata_bar5 + 0x12C) |= 3 << 8; *(volatile u32 *)(sata_bar5 + 0x1AC) |= 3 << 8; *(volatile u32 *)(sata_bar5 + 0x22C) |= 3 << 8; *(volatile u32 *)(sata_bar5 + 0x2AC) |= 3 << 8; /* restore pci cmd */ _pci_conf_write(sata_dev, 0x04, reg04); return; }