Beispiel #1
0
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, &reg16);
	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);
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}
Beispiel #5
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, &reg16);
	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);
}
Beispiel #6
0
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, &reg16);
	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;
}
Beispiel #7
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);
}
Beispiel #8
0
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, &reg16);
		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, &reg16);
		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);
}
Beispiel #9
0
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, &reg16);
	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, &reg16);
	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;
}