static void enable_clock_gating(struct udevice *pch) { u32 reg32; u16 reg16; setbits_le32(RCB_REG(0x2234), 0xf); dm_pci_read_config16(pch, GEN_PMCON_1, ®16); reg16 |= (1 << 2) | (1 << 11); dm_pci_write_config16(pch, GEN_PMCON_1, reg16); pch_iobp_update(pch, 0xEB007F07, ~0UL, (1 << 31)); pch_iobp_update(pch, 0xEB004000, ~0UL, (1 << 7)); pch_iobp_update(pch, 0xEC007F07, ~0UL, (1 << 31)); pch_iobp_update(pch, 0xEC004000, ~0UL, (1 << 7)); reg32 = readl(RCB_REG(CG)); reg32 |= (1 << 31); reg32 |= (1 << 29) | (1 << 28); reg32 |= (1 << 27) | (1 << 26) | (1 << 25) | (1 << 24); reg32 |= (1 << 16); reg32 |= (1 << 17); reg32 |= (1 << 18); reg32 |= (1 << 22); reg32 |= (1 << 23); reg32 &= ~(1 << 20); reg32 |= (1 << 19); reg32 |= (1 << 0); reg32 |= (0xf << 1); writel(reg32, RCB_REG(CG)); setbits_le32(RCB_REG(0x38c0), 0x7); setbits_le32(RCB_REG(0x36d4), 0x6680c004); setbits_le32(RCB_REG(0x3564), 0x3); }
static int lpc_init_extra(struct udevice *dev) { struct udevice *pch = dev->parent; const void *blob = gd->fdt_blob; int node; debug("pch: lpc_init\n"); dm_pci_write_bar32(pch, 0, 0); dm_pci_write_bar32(pch, 1, 0xff800000); dm_pci_write_bar32(pch, 2, 0xfec00000); dm_pci_write_bar32(pch, 3, 0x800); dm_pci_write_bar32(pch, 4, 0x900); node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_PCH); if (node < 0) return -ENOENT; /* Set the value for PCI command register. */ dm_pci_write_config16(pch, PCI_COMMAND, 0x000f); /* IO APIC initialization. */ pch_enable_apic(pch); pch_enable_serial_irqs(pch); /* Setup the PIRQ. */ pch_pirq_init(pch); /* Setup power options. */ pch_power_options(pch); /* Initialize power management */ switch (pch_silicon_type(pch)) { case PCH_TYPE_CPT: /* CougarPoint */ cpt_pm_init(pch); break; case PCH_TYPE_PPT: /* PantherPoint */ ppt_pm_init(pch); break; default: printf("Unknown Chipset: %s\n", pch->name); return -ENOSYS; } /* Initialize the real time clock. */ pch_rtc_init(pch); /* Initialize the High Precision Event Timers, if present. */ enable_hpet(); /* Initialize Clock Gating */ enable_clock_gating(pch); pch_disable_smm_only_flashing(pch); pch_fixups(pch); return 0; }
/** * lpc_early_init() - set up LPC serial ports and other early things * * @dev: LPC device * @return 0 if OK, -ve on error */ static int lpc_early_init(struct udevice *dev) { struct reg_info { u32 base; u32 size; } values[4], *ptr; int count; int i; count = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset, "intel,gen-dec", (u32 *)values, sizeof(values) / sizeof(u32)); if (count < 0) return -EINVAL; /* Set COM1/COM2 decode range */ dm_pci_write_config16(dev->parent, LPC_IO_DEC, 0x0010); /* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */ dm_pci_write_config16(dev->parent, LPC_EN, KBC_LPC_EN | MC_LPC_EN | GAMEL_LPC_EN | COMA_LPC_EN); /* Write all registers but use 0 if we run out of data */ count = count * sizeof(u32) / sizeof(values[0]); for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) { u32 reg = 0; if (i < count) reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16); dm_pci_write_config32(dev->parent, LPC_GENX_DEC(i), reg); } enable_spi_prefetch(dev->parent); /* This is already done in start.S, but let's do it in C */ enable_port80_on_lpc(dev->parent); set_spi_speed(); return 0; }
int board_early_init_f(void) { struct udevice *pch; int ret; ret = uclass_first_device(UCLASS_PCH, &pch); if (ret) return ret; if (!pch) return -ENODEV; /* Initialize LPC interface to turn on superio chipset decode range */ dm_pci_write_config16(pch, LPC_IO_DEC, COMA_DEC_RANGE | COMB_DEC_RANGE); dm_pci_write_config16(pch, LPC_EN, KBC_LPC_EN | COMA_LPC_EN); dm_pci_write_config32(pch, LPC_GEN1_DEC, GEN_DEC_RANGE_256B | (SIO1007_IOPORT3 & 0xff00) | GEN_DEC_RANGE_EN); dm_pci_write_config32(pch, LPC_GEN2_DEC, GEN_DEC_RANGE_16B | SIO1007_RUNTIME_IOPORT | GEN_DEC_RANGE_EN); /* Enable legacy serial port at 0x3f8 */ sio1007_enable_serial(SIO1007_IOPORT3, 0, UART0_BASE, UART0_IRQ); /* Enable SIO1007 runtime I/O port at 0x180 */ sio1007_enable_runtime(SIO1007_IOPORT3, SIO1007_RUNTIME_IOPORT); /* * On Cougar Canyon 2 board, the RS232 transiver connected to serial * port 0 (0x3f8) is controlled by a GPIO pin (GPIO10) on the SIO1007. * Set the pin value to 1 to enable the RS232 transiver. */ sio1007_gpio_config(SIO1007_IOPORT3, 0, GPIO_DIR_OUTPUT, GPIO_POL_NO_INVERT, GPIO_TYPE_PUSH_PULL); sio1007_gpio_set_value(SIO1007_RUNTIME_IOPORT, 0, 1); return 0; }
static void common_sata_init(struct udevice *dev, unsigned int port_map) { u32 reg32; u16 reg16; /* Set IDE I/O Configuration */ reg32 = SIG_MODE_PRI_NORMAL | FAST_PCB1 | FAST_PCB0 | PCB1 | PCB0; dm_pci_write_config32(dev, IDE_CONFIG, reg32); /* Port enable */ dm_pci_read_config16(dev, 0x92, ®16); reg16 &= ~0x3f; reg16 |= port_map; dm_pci_write_config16(dev, 0x92, reg16); /* SATA Initialization register */ port_map &= 0xff; dm_pci_write_config32(dev, 0x94, ((port_map ^ 0x3f) << 24) | 0x183); }
static int pch_power_options(struct udevice *dev) { int pwr_on_after_power_fail = MAINBOARD_POWER_OFF; const char *state; u32 enable[4]; u16 reg16; int ret; dm_pci_read_config16(dev, GEN_PMCON_3, ®16); reg16 &= 0xfffe; switch (pwr_on_after_power_fail) { case MAINBOARD_POWER_OFF: reg16 |= 1; state = "off"; break; case MAINBOARD_POWER_ON: reg16 &= ~1; state = "on"; break; case MAINBOARD_POWER_KEEP: reg16 &= ~1; state = "state keep"; break; default: state = "undefined"; } dm_pci_write_config16(dev, GEN_PMCON_3, reg16); debug("Set power %s after power failure.\n", state); /* GPE setup based on device tree configuration */ ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "intel,gpe0-en", enable, ARRAY_SIZE(enable)); if (ret) return -EINVAL; enable_all_gpe(enable[0], enable[1], enable[2], enable[3]); /* SMI setup based on device tree configuration */ enable_alt_smi(dev, fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "intel,alt-gp-smi-enable", 0)); return 0; }
static void bd82x6x_sata_enable(struct udevice *dev) { const void *blob = gd->fdt_blob; int node = dev->of_offset; unsigned port_map; const char *mode; u16 map = 0; /* * Set SATA controller mode early so the resource allocator can * properly assign IO/Memory resources for the controller. */ mode = fdt_getprop(blob, node, "intel,sata-mode", NULL); if (mode && !strcmp(mode, "ahci")) map = 0x0060; port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); map |= (port_map ^ 0x3f) << 8; dm_pci_write_config16(dev, 0x90, map); }
static void bd82x6x_sata_init(struct udevice *dev, struct udevice *pch) { unsigned int port_map, speed_support, port_tx; const void *blob = gd->fdt_blob; int node = dev->of_offset; const char *mode; u32 reg32; u16 reg16; debug("SATA: Initializing...\n"); /* SATA configuration */ port_map = fdtdec_get_int(blob, node, "intel,sata-port-map", 0); speed_support = fdtdec_get_int(blob, node, "sata_interface_speed_support", 0); mode = fdt_getprop(blob, node, "intel,sata-mode", NULL); if (!mode || !strcmp(mode, "ahci")) { u32 abar; debug("SATA: Controller in AHCI mode\n"); /* Set timings */ dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | IDE_PPE0 | IDE_IE0 | IDE_TIME0); dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); /* Sync DMA */ dm_pci_write_config16(dev, IDE_SDMA_CNT, IDE_PSDE0); dm_pci_write_config16(dev, IDE_SDMA_TIM, 0x0001); common_sata_init(dev, 0x8000 | port_map); /* Initialize AHCI memory-mapped space */ abar = dm_pci_read_bar32(dev, 5); debug("ABAR: %08X\n", abar); /* CAP (HBA Capabilities) : enable power management */ reg32 = readl(abar + 0x00); reg32 |= 0x0c006000; /* set PSC+SSC+SALP+SSS */ reg32 &= ~0x00020060; /* clear SXS+EMS+PMS */ /* Set ISS, if available */ if (speed_support) { reg32 &= ~0x00f00000; reg32 |= (speed_support & 0x03) << 20; } writel(reg32, abar + 0x00); /* PI (Ports implemented) */ writel(port_map, abar + 0x0c); (void) readl(abar + 0x0c); /* Read back 1 */ (void) readl(abar + 0x0c); /* Read back 2 */ /* CAP2 (HBA Capabilities Extended)*/ reg32 = readl(abar + 0x24); reg32 &= ~0x00000002; writel(reg32, abar + 0x24); /* VSP (Vendor Specific Register */ reg32 = readl(abar + 0xa0); reg32 &= ~0x00000005; writel(reg32, abar + 0xa0); } else if (!strcmp(mode, "combined")) { debug("SATA: Controller in combined mode\n"); /* No AHCI: clear AHCI base */ dm_pci_write_bar32(dev, 5, 0x00000000); /* And without AHCI BAR no memory decoding */ dm_pci_read_config16(dev, PCI_COMMAND, ®16); reg16 &= ~PCI_COMMAND_MEMORY; dm_pci_write_config16(dev, PCI_COMMAND, reg16); dm_pci_write_config8(dev, 0x09, 0x80); /* Set timings */ dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | IDE_ISP_5_CLOCKS | IDE_RCT_4_CLOCKS); dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | IDE_PPE0 | IDE_IE0 | IDE_TIME0); /* Sync DMA */ dm_pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0); dm_pci_write_config16(dev, IDE_SDMA_TIM, 0x0200); common_sata_init(dev, port_map); } else { debug("SATA: Controller in plain-ide mode\n"); /* No AHCI: clear AHCI base */ dm_pci_write_bar32(dev, 5, 0x00000000); /* And without AHCI BAR no memory decoding */ dm_pci_read_config16(dev, PCI_COMMAND, ®16); reg16 &= ~PCI_COMMAND_MEMORY; dm_pci_write_config16(dev, PCI_COMMAND, reg16); /* * Native mode capable on both primary and secondary (0xa) * OR'ed with enabled (0x50) = 0xf */ dm_pci_write_config8(dev, 0x09, 0x8f); /* Set timings */ dm_pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE | IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | IDE_PPE0 | IDE_IE0 | IDE_TIME0); dm_pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE | IDE_SITRE | IDE_ISP_3_CLOCKS | IDE_RCT_1_CLOCKS | IDE_IE0 | IDE_TIME0); /* Sync DMA */ dm_pci_write_config16(dev, IDE_SDMA_CNT, IDE_SSDE0 | IDE_PSDE0); dm_pci_write_config16(dev, IDE_SDMA_TIM, 0x0201); common_sata_init(dev, port_map); } /* Set Gen3 Transmitter settings if needed */ port_tx = fdtdec_get_int(blob, node, "intel,sata-port0-gen3-tx", 0); if (port_tx) pch_iobp_update(pch, SATA_IOBP_SP0G3IR, 0, port_tx); port_tx = fdtdec_get_int(blob, node, "intel,sata-port1-gen3-tx", 0); if (port_tx) pch_iobp_update(pch, SATA_IOBP_SP1G3IR, 0, port_tx); /* Additional Programming Requirements */ sir_write(dev, 0x04, 0x00001600); sir_write(dev, 0x28, 0xa0000033); reg32 = sir_read(dev, 0x54); reg32 &= 0xff000000; reg32 |= 0x5555aa; sir_write(dev, 0x54, reg32); sir_write(dev, 0x64, 0xcccc8484); reg32 = sir_read(dev, 0x68); reg32 &= 0xffff0000; reg32 |= 0xcccc; sir_write(dev, 0x68, reg32); reg32 = sir_read(dev, 0x78); reg32 &= 0x0000ffff; reg32 |= 0x88880000; sir_write(dev, 0x78, reg32); sir_write(dev, 0x84, 0x001c7000); sir_write(dev, 0x88, 0x88338822); sir_write(dev, 0xa0, 0x001c7000); sir_write(dev, 0xc4, 0x0c0c0c0c); sir_write(dev, 0xc8, 0x0c0c0c0c); sir_write(dev, 0xd4, 0x10000000); pch_iobp_update(pch, 0xea004001, 0x3fffffff, 0xc0000000); pch_iobp_update(pch, 0xea00408a, 0xfffffcff, 0x00000100); }
static int pch_power_options(struct udevice *pch) { const void *blob = gd->fdt_blob; int node = pch->of_offset; u8 reg8; u16 reg16, pmbase; u32 reg32; const char *state; int pwr_on; int nmi_option; int ret; /* * Which state do we want to goto after g3 (power restored)? * 0 == S0 Full On * 1 == S5 Soft Off * * If the option is not existent (Laptops), use Kconfig setting. * TODO([email protected]): Make this configurable */ pwr_on = MAINBOARD_POWER_ON; dm_pci_read_config16(pch, GEN_PMCON_3, ®16); reg16 &= 0xfffe; switch (pwr_on) { case MAINBOARD_POWER_OFF: reg16 |= 1; state = "off"; break; case MAINBOARD_POWER_ON: reg16 &= ~1; state = "on"; break; case MAINBOARD_POWER_KEEP: reg16 &= ~1; state = "state keep"; break; default: state = "undefined"; } reg16 &= ~(3 << 4); /* SLP_S4# Assertion Stretch 4s */ reg16 |= (1 << 3); /* SLP_S4# Assertion Stretch Enable */ reg16 &= ~(1 << 10); reg16 |= (1 << 11); /* SLP_S3# Min Assertion Width 50ms */ reg16 |= (1 << 12); /* Disable SLP stretch after SUS well */ dm_pci_write_config16(pch, GEN_PMCON_3, reg16); debug("Set power %s after power failure.\n", state); /* Set up NMI on errors. */ reg8 = inb(0x61); reg8 &= 0x0f; /* Higher Nibble must be 0 */ reg8 &= ~(1 << 3); /* IOCHK# NMI Enable */ reg8 |= (1 << 2); /* PCI SERR# Disable for now */ outb(reg8, 0x61); reg8 = inb(0x70); /* TODO([email protected]): Make this configurable */ nmi_option = NMI_OFF; if (nmi_option) { debug("NMI sources enabled.\n"); reg8 &= ~(1 << 7); /* Set NMI. */ } else { debug("NMI sources disabled.\n"); /* Can't mask NMI from PCI-E and NMI_NOW */ reg8 |= (1 << 7); } outb(reg8, 0x70); /* Enable CPU_SLP# and Intel Speedstep, set SMI# rate down */ dm_pci_read_config16(pch, GEN_PMCON_1, ®16); reg16 &= ~(3 << 0); /* SMI# rate 1 minute */ reg16 &= ~(1 << 10); /* Disable BIOS_PCI_EXP_EN for native PME */ #if DEBUG_PERIODIC_SMIS /* Set DEBUG_PERIODIC_SMIS in pch.h to debug using periodic SMIs */ reg16 |= (3 << 0); /* Periodic SMI every 8s */ #endif dm_pci_write_config16(pch, GEN_PMCON_1, reg16); /* Set the board's GPI routing. */ ret = pch_gpi_routing(pch); if (ret) return ret; dm_pci_read_config16(pch, 0x40, &pmbase); pmbase &= 0xfffe; writel(pmbase + GPE0_EN, fdtdec_get_int(blob, node, "intel,gpe0-enable", 0)); writew(pmbase + ALT_GP_SMI_EN, fdtdec_get_int(blob, node, "intel,alt-gp-smi-enable", 0)); /* Set up power management block and determine sleep mode */ reg32 = inl(pmbase + 0x04); /* PM1_CNT */ reg32 &= ~(7 << 10); /* SLP_TYP */ reg32 |= (1 << 0); /* SCI_EN */ outl(reg32, pmbase + 0x04); /* Clear magic status bits to prevent unexpected wake */ setbits_le32(RCB_REG(0x3310), (1 << 4) | (1 << 5) | (1 << 0)); clrbits_le32(RCB_REG(0x3f02), 0xf); return 0; }