x86: tangier: Enable ACPI support for Intel Tangier
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Tue, 3 Oct 2017 11:55:07 +0000 (14:55 +0300)
committerBin Meng <bmeng.cn@gmail.com>
Sat, 7 Oct 2017 07:07:59 +0000 (15:07 +0800)
Intel Tangier SoC is a part of Intel Merrifield platform which doesn't
utilize ACPI by default. Here is an attempt to unleash ACPI flexibility
power on Intel Merrifield based platforms.

The change brings minimum support of the devices that found on
Intel Merrifield based end user device.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
arch/x86/cpu/tangier/Makefile
arch/x86/cpu/tangier/acpi.c [new file with mode: 0644]
arch/x86/include/asm/arch-tangier/acpi/global_nvs.asl [new file with mode: 0644]
arch/x86/include/asm/arch-tangier/acpi/platform.asl [new file with mode: 0644]
arch/x86/include/asm/arch-tangier/acpi/southcluster.asl [new file with mode: 0644]
arch/x86/include/asm/arch-tangier/global_nvs.h [new file with mode: 0644]

index d146b3f5c28deb00ff04b2869147d10b4c822fef..92cfa555ed4d7300b30b2bf93633965bc2aade9b 100644 (file)
@@ -5,3 +5,4 @@
 #
 
 obj-y += car.o tangier.o sdram.o
+obj-$(CONFIG_GENERATE_ACPI_TABLE) += acpi.o
diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c
new file mode 100644 (file)
index 0000000..75e777d
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on acpi.c for other x86 platforms
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <dm/uclass-internal.h>
+#include <asm/acpi_table.h>
+#include <asm/ioapic.h>
+#include <asm/mpspec.h>
+#include <asm/tables.h>
+#include <asm/arch/global_nvs.h>
+
+void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs,
+                     void *dsdt)
+{
+       struct acpi_table_header *header = &(fadt->header);
+
+       memset((void *)fadt, 0, sizeof(struct acpi_fadt));
+
+       acpi_fill_header(header, "FACP");
+       header->length = sizeof(struct acpi_fadt);
+       header->revision = 6;
+
+       fadt->firmware_ctrl = (u32)facs;
+       fadt->dsdt = (u32)dsdt;
+       fadt->preferred_pm_profile = ACPI_PM_UNSPECIFIED;
+
+       fadt->iapc_boot_arch = ACPI_FADT_VGA_NOT_PRESENT |
+                              ACPI_FADT_NO_PCIE_ASPM_CONTROL;
+       fadt->flags =
+               ACPI_FADT_WBINVD |
+               ACPI_FADT_POWER_BUTTON | ACPI_FADT_SLEEP_BUTTON |
+               ACPI_FADT_SEALED_CASE | ACPI_FADT_HEADLESS |
+               ACPI_FADT_HW_REDUCED_ACPI;
+
+       fadt->minor_revision = 2;
+
+       fadt->x_firmware_ctl_l = (u32)facs;
+       fadt->x_firmware_ctl_h = 0;
+       fadt->x_dsdt_l = (u32)dsdt;
+       fadt->x_dsdt_h = 0;
+
+       header->checksum = table_compute_checksum(fadt, header->length);
+}
+
+u32 acpi_fill_madt(u32 current)
+{
+       current += acpi_create_madt_lapics(current);
+
+       current += acpi_create_madt_ioapic((struct acpi_madt_ioapic *)current,
+                       io_apic_read(IO_APIC_ID) >> 24, IO_APIC_ADDR, 0);
+
+       return current;
+}
+
+u32 acpi_fill_mcfg(u32 current)
+{
+       /* TODO: Derive parameters from SFI MCFG table */
+       current += acpi_create_mcfg_mmconfig
+               ((struct acpi_mcfg_mmconfig *)current,
+               0x3f500000, 0x0, 0x0, 0x0);
+
+       return current;
+}
+
+void acpi_create_gnvs(struct acpi_global_nvs *gnvs)
+{
+       struct udevice *dev;
+       int ret;
+
+       /* at least we have one processor */
+       gnvs->pcnt = 1;
+
+       /* override the processor count with actual number */
+       ret = uclass_find_first_device(UCLASS_CPU, &dev);
+       if (ret == 0 && dev != NULL) {
+               ret = cpu_get_count(dev);
+               if (ret > 0)
+                       gnvs->pcnt = ret;
+       }
+}
diff --git a/arch/x86/include/asm/arch-tangier/acpi/global_nvs.asl b/arch/x86/include/asm/arch-tangier/acpi/global_nvs.asl
new file mode 100644 (file)
index 0000000..b1f0f67
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on global_nvs.asl for other x86 platforms
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/acpi/global_nvs.h>
+
+OperationRegion(GNVS, SystemMemory, ACPI_GNVS_ADDR, ACPI_GNVS_SIZE)
+Field(GNVS, ByteAcc, NoLock, Preserve)
+{
+    Offset (0x00),
+    PCNT, 8,    /* processor count */
+}
diff --git a/arch/x86/include/asm/arch-tangier/acpi/platform.asl b/arch/x86/include/asm/arch-tangier/acpi/platform.asl
new file mode 100644 (file)
index 0000000..a57b7cb
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on platform.asl for other x86 platforms
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <asm/acpi/statdef.asl>
+
+/*
+ * The _PTS method (Prepare To Sleep) is called before the OS is
+ * entering a sleep state. The sleep state number is passed in Arg0.
+ */
+Method(_PTS, 1)
+{
+}
+
+/* The _WAK method is called on system wakeup */
+Method(_WAK, 1)
+{
+    Return (Package() {0, 0})
+}
+
+/* ACPI global NVS */
+#include "global_nvs.asl"
+
+Scope (\_SB)
+{
+    #include "southcluster.asl"
+}
diff --git a/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl b/arch/x86/include/asm/arch-tangier/acpi/southcluster.asl
new file mode 100644 (file)
index 0000000..e80ec0a
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on southcluster.asl for other x86 platforms
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+Device (PCI0)
+{
+    Name (_HID, EISAID("PNP0A08"))    /* PCIe */
+    Name (_CID, EISAID("PNP0A03"))    /* PCI */
+
+    Name (_ADR, 0)
+    Name (_BBN, 0)
+
+    Name (MCRS, ResourceTemplate()
+    {
+        /* Bus Numbers */
+        WordBusNumber(ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                0x0000, 0x0000, 0x00ff, 0x0000, 0x0100, , , PB00)
+
+        /* IO Region 0 */
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                0x0000, 0x0000, 0x0cf7, 0x0000, 0x0cf8, , , PI00)
+
+        /* PCI Config Space */
+        IO(Decode16, 0x0cf8, 0x0cf8, 0x0001, 0x0008)
+
+        /* IO Region 1 */
+        WordIO(ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                0x0000, 0x0d00, 0xffff, 0x0000, 0xf300, , , PI01)
+
+        /* GPIO Low Memory Region */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x000ddcc0, 0x000ddccf, 0x00000000,
+                0x00000010, , , GP00)
+
+        /* PSH Memory Region 0 */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x04819000, 0x04898fff, 0x00000000,
+                0x00080000, , , PSH0)
+
+        /* PSH Memory Region 1 */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x04919000, 0x04920fff, 0x00000000,
+                0x00008000, , , PSH1)
+
+        /* SST Memory Region */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x05e00000, 0x05ffffff, 0x00000000,
+                0x00200000, , , SST0)
+
+        /* PCI Memory Region */
+        DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+                Cacheable, ReadWrite,
+                0x00000000, 0x80000000, 0xffffffff, 0x00000000,
+                0x80000000, , , PMEM)
+    })
+
+    Method (_CRS, 0, Serialized)
+    {
+        Return (MCRS)
+    }
+
+    Method (_OSC, 4)
+    {
+        /* Check for proper GUID */
+        If (LEqual(Arg0, ToUUID("33db4d5b-1ff7-401c-9657-7441c03dd766"))) {
+            /* Let OS control everything */
+            Return (Arg3)
+        } Else {
+            /* Unrecognized UUID */
+            CreateDWordField(Arg3, 0, CDW1)
+            Or(CDW1, 4, CDW1)
+            Return (Arg3)
+        }
+    }
+
+    Device (SDHC)
+    {
+        Name (_ADR, 0x00010003)
+        Name (_DEP, Package (0x01)
+        {
+            GPIO
+        })
+        Name (PSTS, Zero)
+
+        Method (_STA)
+        {
+            Return (STA_VISIBLE)
+        }
+
+        Method (_PS3, 0, NotSerialized)
+        {
+        }
+
+        Method (_PS0, 0, NotSerialized)
+        {
+            If (PSTS == Zero)
+            {
+                If (^^GPIO.AVBL == One)
+                {
+                    ^^GPIO.WFD3 = One
+                    PSTS = One
+                }
+            }
+        }
+
+        /* BCM43340 */
+        Device (BRC1)
+        {
+            Name (_ADR, 0x01)
+            Name (_DEP, Package (0x01)
+            {
+                GPIO
+            })
+
+            Method (_STA)
+            {
+                Return (STA_VISIBLE)
+            }
+
+            Method (_RMV, 0, NotSerialized)
+            {
+                Return (Zero)
+            }
+
+            Method (_PS3, 0, NotSerialized)
+            {
+                If (^^^GPIO.AVBL == One)
+                {
+                    ^^^GPIO.WFD3 = Zero
+                    PSTS = Zero
+                }
+            }
+
+            Method (_PS0, 0, NotSerialized)
+            {
+                If (PSTS == Zero)
+                {
+                    If (^^^GPIO.AVBL == One)
+                    {
+                        ^^^GPIO.WFD3 = One
+                        PSTS = One
+                    }
+                }
+            }
+        }
+
+        Device (BRC2)
+        {
+            Name (_ADR, 0x02)
+            Method (_STA, 0, NotSerialized)
+            {
+                Return (STA_VISIBLE)
+            }
+
+            Method (_RMV, 0, NotSerialized)
+            {
+                Return (Zero)
+            }
+        }
+    }
+
+    Device (SPI5)
+    {
+        Name (_ADR, 0x00070001)
+        Name (RBUF, ResourceTemplate()
+        {
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 91 }
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 92 }
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 93 }
+            GpioIo(Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
+                "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 94 }
+        })
+
+        Method (_CRS, 0, NotSerialized)
+        {
+            Return (RBUF)
+        }
+
+        /*
+         * See
+         * http://www.kernel.org/doc/Documentation/acpi/gpio-properties.txt
+         * for more information about GPIO bindings.
+         */
+        Name (_DSD, Package () {
+            ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+            Package () {
+                Package () {
+                    "cs-gpios", Package () {
+                        ^SPI5, 0, 0, 0,
+                        ^SPI5, 1, 0, 0,
+                        ^SPI5, 2, 0, 0,
+                        ^SPI5, 3, 0, 0,
+                    },
+                },
+            }
+        })
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+    }
+
+    Device (I2C1)
+    {
+        Name (_ADR, 0x00080000)
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+    }
+
+    Device (GPIO)
+    {
+        Name (_ADR, 0x000c0000)
+
+        Method (_STA)
+        {
+            Return (STA_VISIBLE)
+        }
+
+        Name (AVBL, Zero)
+        Method (_REG, 2, NotSerialized)
+        {
+            If (Arg0 == 0x08)
+            {
+                AVBL = Arg1
+            }
+        }
+
+        OperationRegion (GPOP, GeneralPurposeIo, 0, 1)
+        Field (GPOP, ByteAcc, NoLock, Preserve)
+        {
+            Connection (
+                GpioIo(Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
+                    "\\_SB.PCI0.GPIO", 0, ResourceConsumer, , ) { 56 }
+            ),
+            WFD3, 1,
+        }
+    }
+
+    Device (PWM0)
+    {
+        Name (_ADR, 0x00170000)
+
+        Method (_STA, 0, NotSerialized)
+        {
+            Return (STA_VISIBLE)
+        }
+    }
+}
+
+Device (FLIS)
+{
+    Name (_HID, "PRP0001")
+    Name (_DDN, "Intel Merrifield Family-Level Interface Shim")
+    Name (RBUF, ResourceTemplate()
+    {
+        Memory32Fixed(ReadWrite, 0xFF0C0000, 0x00008000, )
+        PinGroup("spi5", ResourceProducer, ) { 90, 91, 92, 93, 94, 95, 96 }
+        PinGroup("uart0", ResourceProducer, ) { 115, 116, 117, 118 }
+        PinGroup("uart1", ResourceProducer, ) { 119, 120, 121, 122 }
+        PinGroup("uart2", ResourceProducer, ) { 123, 124, 125, 126 }
+        PinGroup("pwm0", ResourceProducer, ) { 144 }
+        PinGroup("pwm1", ResourceProducer, ) { 145 }
+        PinGroup("pwm2", ResourceProducer, ) { 132 }
+        PinGroup("pwm3", ResourceProducer, ) { 133 }
+    })
+
+    Method (_CRS, 0, NotSerialized)
+    {
+        Return (RBUF)
+    }
+
+    Name (_DSD, Package () {
+        ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+        Package () {
+            Package () {"compatible", "intel,merrifield-pinctrl"},
+        }
+    })
+
+    Method (_STA, 0, NotSerialized)
+    {
+        Return (STA_VISIBLE)
+    }
+}
diff --git a/arch/x86/include/asm/arch-tangier/global_nvs.h b/arch/x86/include/asm/arch-tangier/global_nvs.h
new file mode 100644 (file)
index 0000000..8ab5cf2
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * Partially based on global_nvs.h for other x86 platforms
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _GLOBAL_NVS_H_
+#define _GLOBAL_NVS_H_
+
+struct __packed acpi_global_nvs {
+       u8      pcnt;           /* processor count */
+
+       /*
+        * Add padding so sizeof(struct acpi_global_nvs) == 0x100.
+        * This must match the size defined in the global_nvs.asl.
+        */
+       u8      rsvd[255];
+};
+
+#endif /* _GLOBAL_NVS_H_ */