aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/cpu/broadwell/pch.c')
-rw-r--r--arch/x86/cpu/broadwell/pch.c147
1 files changed, 144 insertions, 3 deletions
diff --git a/arch/x86/cpu/broadwell/pch.c b/arch/x86/cpu/broadwell/pch.c
index 82506ba35e..a48945adf1 100644
--- a/arch/x86/cpu/broadwell/pch.c
+++ b/arch/x86/cpu/broadwell/pch.c
@@ -20,7 +20,9 @@
20#include <asm/arch/pch.h> 20#include <asm/arch/pch.h>
21#include <asm/arch/pm.h> 21#include <asm/arch/pm.h>
22#include <asm/arch/rcb.h> 22#include <asm/arch/rcb.h>
23#include <asm/arch/serialio.h>
23#include <asm/arch/spi.h> 24#include <asm/arch/spi.h>
25#include <dm/uclass-internal.h>
24 26
25#define BIOS_CTRL 0xdc 27#define BIOS_CTRL 0xdc
26 28
@@ -456,6 +458,111 @@ static void systemagent_init(void)
456 cpu_set_power_limits(28); 458 cpu_set_power_limits(28);
457} 459}
458 460
461/* Enable LTR Auto Mode for D21:F1-F6 */
462static void serialio_d21_ltr(u32 bar0)
463{
464 /* 1. Program BAR0 + 808h[2] = 0b */
465 clrbits_le32(bar0 + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_LTR_MODE_MASK);
466
467 /* 2. Program BAR0 + 804h[1:0] = 00b */
468 clrbits_le32(bar0 + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
469
470 /* 3. Program BAR0 + 804h[1:0] = 11b */
471 setbits_le32(bar0 + SIO_REG_PPR_RST, SIO_REG_PPR_RST_ASSERT);
472
473 /* 4. Program BAR0 + 814h[31:0] = 00000000h */
474 writel(0, bar0 + SIO_REG_AUTO_LTR);
475}
476
477/* Select I2C voltage of 1.8V or 3.3V */
478static void serialio_i2c_voltage_sel(u32 bar0, uint voltage)
479{
480 clrsetbits_le32(bar0 + SIO_REG_PPR_GEN, SIO_REG_PPR_GEN_VOLTAGE_MASK,
481 SIO_REG_PPR_GEN_VOLTAGE(voltage));
482}
483
484/* Put Serial IO D21:F0-F6 device into desired mode */
485static void serialio_d21_mode(int sio_index, int int_pin, bool acpi_mode)
486{
487 u32 portctrl = SIO_IOBP_PORTCTRL_PM_CAP_PRSNT;
488
489 /* Snoop select 1 */
490 portctrl |= SIO_IOBP_PORTCTRL_SNOOP_SELECT(1);
491
492 /* Set interrupt pin */
493 portctrl |= SIO_IOBP_PORTCTRL_INT_PIN(int_pin);
494
495 if (acpi_mode) {
496 /* Enable ACPI interrupt mode */
497 portctrl |= SIO_IOBP_PORTCTRL_ACPI_IRQ_EN;
498 }
499
500 pch_iobp_update(SIO_IOBP_PORTCTRLX(sio_index), 0, portctrl);
501}
502
503/* Init sequence to be run once, done as part of D21:F0 (SDMA) init */
504static void serialio_init_once(bool acpi_mode)
505{
506 if (acpi_mode) {
507 /* Enable ACPI IRQ for IRQ13, IRQ7, IRQ6, IRQ5 in RCBA */
508 setbits_le32(RCB_REG(ACPIIRQEN),
509 1 << 13 | 1 << 7 | 1 << 6 | 1 << 5);
510 }
511
512 /* Program IOBP CB000154h[12,9:8,4:0] = 1001100011111b */
513 pch_iobp_update(SIO_IOBP_GPIODF, ~0x0000131f, 0x0000131f);
514
515 /* Program IOBP CB000180h[5:0] = 111111b (undefined register) */
516 pch_iobp_update(0xcb000180, ~0x0000003f, 0x0000003f);
517}
518
519/**
520 * pch_serialio_init() - set up serial I/O devices
521 *
522 * @return 0 if OK, -ve on error
523 */
524static int pch_serialio_init(void)
525{
526 struct udevice *dev, *hda;
527 bool acpi_mode = true;
528 u32 bar0, bar1;
529 int ret;
530
531 ret = uclass_find_first_device(UCLASS_I2C, &dev);
532 if (ret)
533 return ret;
534 bar0 = dm_pci_read_bar32(dev, 0);
535 if (!bar0)
536 return -EINVAL;
537 bar1 = dm_pci_read_bar32(dev, 1);
538 if (!bar1)
539 return -EINVAL;
540
541 serialio_init_once(acpi_mode);
542 serialio_d21_mode(SIO_ID_SDMA, SIO_PIN_INTB, acpi_mode);
543
544 serialio_d21_ltr(bar0);
545 serialio_i2c_voltage_sel(bar0, 1); /* Select 1.8V always */
546 serialio_d21_mode(SIO_ID_I2C0, SIO_PIN_INTC, acpi_mode);
547 setbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
548
549 clrbits_le32(bar1 + PCH_PCS, PCH_PCS_PS_D3HOT);
550
551 setbits_le32(bar0 + SIO_REG_PPR_CLOCK, SIO_REG_PPR_CLOCK_EN);
552
553 /* Manually find the High-definition audio, to turn it off */
554 ret = dm_pci_bus_find_bdf(PCI_BDF(0, 0x1b, 0), &hda);
555 if (ret)
556 return -ENOENT;
557 dm_pci_clrset_config8(hda, 0x43, 0, 0x6f);
558
559 /* Route I/O buffers to ADSP function */
560 dm_pci_clrset_config8(hda, 0x42, 0, 1 << 7 | 1 << 6);
561 log_debug("HDA disabled, I/O buffers routed to ADSP\n");
562
563 return 0;
564}
565
459static int broadwell_pch_init(struct udevice *dev) 566static int broadwell_pch_init(struct udevice *dev)
460{ 567{
461 int ret; 568 int ret;
@@ -482,6 +589,9 @@ static int broadwell_pch_init(struct udevice *dev)
482 return ret; 589 return ret;
483 pch_pm_init(dev); 590 pch_pm_init(dev);
484 pch_cg_init(dev); 591 pch_cg_init(dev);
592 ret = pch_serialio_init();
593 if (ret)
594 return ret;
485 systemagent_init(); 595 systemagent_init();
486 596
487 return 0; 597 return 0;
@@ -489,10 +599,16 @@ static int broadwell_pch_init(struct udevice *dev)
489 599
490static int broadwell_pch_probe(struct udevice *dev) 600static int broadwell_pch_probe(struct udevice *dev)
491{ 601{
492 if (!(gd->flags & GD_FLG_RELOC)) 602 if (CONFIG_IS_ENABLED(X86_32BIT_INIT)) {
493 return broadwell_pch_early_init(dev); 603 if (!(gd->flags & GD_FLG_RELOC))
494 else 604 return broadwell_pch_early_init(dev);
605 else
606 return broadwell_pch_init(dev);
607 } else if (IS_ENABLED(CONFIG_SPL) && !IS_ENABLED(CONFIG_SPL_BUILD)) {
495 return broadwell_pch_init(dev); 608 return broadwell_pch_init(dev);
609 } else {
610 return 0;
611 }
496} 612}
497 613
498static int broadwell_pch_get_spi_base(struct udevice *dev, ulong *sbasep) 614static int broadwell_pch_get_spi_base(struct udevice *dev, ulong *sbasep)
@@ -520,10 +636,35 @@ static int broadwell_get_gpio_base(struct udevice *dev, u32 *gbasep)
520 return 0; 636 return 0;
521} 637}
522 638
639static int broadwell_ioctl(struct udevice *dev, enum pch_req_t req, void *data,
640 int size)
641{
642 switch (req) {
643 case PCH_REQ_PMBASE_INFO: {
644 struct pch_pmbase_info *pm = data;
645 int ret;
646
647 /* Find the base address of the powermanagement registers */
648 ret = dm_pci_read_config16(dev, 0x40, &pm->base);
649 if (ret)
650 return ret;
651 pm->base &= 0xfffe;
652 pm->gpio0_en_ofs = GPE0_EN(0);
653 pm->pm1_sts_ofs = PM1_STS;
654 pm->pm1_cnt_ofs = PM1_CNT;
655
656 return 0;
657 }
658 default:
659 return -ENOSYS;
660 }
661}
662
523static const struct pch_ops broadwell_pch_ops = { 663static const struct pch_ops broadwell_pch_ops = {
524 .get_spi_base = broadwell_pch_get_spi_base, 664 .get_spi_base = broadwell_pch_get_spi_base,
525 .set_spi_protect = broadwell_set_spi_protect, 665 .set_spi_protect = broadwell_set_spi_protect,
526 .get_gpio_base = broadwell_get_gpio_base, 666 .get_gpio_base = broadwell_get_gpio_base,
667 .ioctl = broadwell_ioctl,
527}; 668};
528 669
529static const struct udevice_id broadwell_pch_ids[] = { 670static const struct udevice_id broadwell_pch_ids[] = {