x86: Add Intel Tangier support
authorFelipe Balbi <felipe.balbi@linux.intel.com>
Thu, 6 Jul 2017 11:41:52 +0000 (14:41 +0300)
committerBin Meng <bmeng.cn@gmail.com>
Sun, 30 Jul 2017 02:30:25 +0000 (10:30 +0800)
Add Intel Tangier SoC support.

Intel Tangier SoC is a core part of Intel Merrifield platform. For
example, Intel Edison board is based on such platform.

The patch is based on work done by the following people (in alphabetical
order):
Aiden Park <aiden.park@intel.com>
Dukjoon Jeon <dukjoon.jeon@intel.com>
eric.park <eric.park@intel.com>
Fabien Chereau <fabien.chereau@intel.com>
Scott D Phillips <scott.d.phillips@intel.com>
Sebastien Colleur <sebastienx.colleur@intel.com>
Steve Sakoman <steve.sakoman@intel.com>
Vincent Tinelli <vincent.tinelli@intel.com>

Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Signed-off-by: Vincent Tinelli <vincent.tinelli@intel.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
arch/x86/Kconfig
arch/x86/cpu/Makefile
arch/x86/cpu/tangier/Kconfig [new file with mode: 0644]
arch/x86/cpu/tangier/Makefile [new file with mode: 0644]
arch/x86/cpu/tangier/car.S [new file with mode: 0644]
arch/x86/cpu/tangier/sdram.c [new file with mode: 0644]
arch/x86/cpu/tangier/tangier.c [new file with mode: 0644]
arch/x86/include/asm/sfi.h

index 0cd981e73e43f7293a83f71ea2056ac185c0f1ff..5c8dc822efbcf81031d1482edff3b8afe10af2ee 100644 (file)
@@ -114,6 +114,7 @@ source "arch/x86/cpu/ivybridge/Kconfig"
 source "arch/x86/cpu/qemu/Kconfig"
 source "arch/x86/cpu/quark/Kconfig"
 source "arch/x86/cpu/queensbay/Kconfig"
+source "arch/x86/cpu/tangier/Kconfig"
 
 # architecture-specific options below
 
index e1c84ce097addc330228cd3284b56333653e5193..999429e62b197c5d64c29302704239eb11a3d6f2 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_QEMU) += qemu/
 obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
 obj-$(CONFIG_INTEL_QUARK) += quark/
 obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
+obj-$(CONFIG_INTEL_TANGIER) += tangier/
 obj-y += lapic.o ioapic.o
 obj-y += irq.o
 ifndef CONFIG_$(SPL_)X86_64
diff --git a/arch/x86/cpu/tangier/Kconfig b/arch/x86/cpu/tangier/Kconfig
new file mode 100644 (file)
index 0000000..92d3352
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2017 Intel Corporation
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+config INTEL_TANGIER
+       bool
+       depends on INTEL_MID
+
+config SYS_CAR_ADDR
+       hex
+       default 0x19200000
+
+config SYS_CAR_SIZE
+       hex
+       default 0x4000
+       help
+         Space in bytes in eSRAM used as Cache-As-RAM (CAR).
+         Note this size must not exceed eSRAM's total size.
diff --git a/arch/x86/cpu/tangier/Makefile b/arch/x86/cpu/tangier/Makefile
new file mode 100644 (file)
index 0000000..d146b3f
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2017 Intel Corporation
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y += car.o tangier.o sdram.o
diff --git a/arch/x86/cpu/tangier/car.S b/arch/x86/cpu/tangier/car.S
new file mode 100644 (file)
index 0000000..6982106
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ * (C) Copyright 2010-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+.section .text
+
+.globl car_init
+car_init:
+       jmp     car_init_ret
diff --git a/arch/x86/cpu/tangier/sdram.c b/arch/x86/cpu/tangier/sdram.c
new file mode 100644 (file)
index 0000000..5743077
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/e820.h>
+#include <asm/global_data.h>
+#include <asm/sfi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * SFI tables are part of the first stage bootloader.
+ *
+ * U-Boot finds the System Table by searching 16-byte boundaries between
+ * physical address 0x000E0000 and 0x000FFFFF. U-Boot shall search this region
+ * starting at the low address and shall stop searching when the 1st valid SFI
+ * System Table is found.
+ */
+#define SFI_BASE_ADDR          0x000E0000
+#define SFI_LENGTH             0x00020000
+#define SFI_TABLE_LENGTH       16
+
+static int sfi_table_check(struct sfi_table_header *sbh)
+{
+       char chksum = 0;
+       char *pos = (char *)sbh;
+       u32 i;
+
+       if (sbh->len < SFI_TABLE_LENGTH)
+               return -ENXIO;
+
+       if (sbh->len > SFI_LENGTH)
+               return -ENXIO;
+
+       for (i = 0; i < sbh->len; i++)
+               chksum += *pos++;
+
+       if (chksum)
+               error("sfi: Invalid checksum\n");
+
+       /* Checksum is OK if zero */
+       return chksum ? -EILSEQ : 0;
+}
+
+static int sfi_table_is_type(struct sfi_table_header *sbh, const char *signature)
+{
+       return !strncmp(sbh->sig, signature, SFI_SIGNATURE_SIZE) &&
+              !sfi_table_check(sbh);
+}
+
+static struct sfi_table_simple *sfi_get_table_by_sig(unsigned long addr,
+                                                    const char *signature)
+{
+       struct sfi_table_simple *sb;
+       u32 i;
+
+       for (i = 0; i < SFI_LENGTH; i += SFI_TABLE_LENGTH) {
+               sb = (struct sfi_table_simple *)(addr + i);
+               if (sfi_table_is_type(&sb->header, signature))
+                       return sb;
+       }
+
+       return NULL;
+}
+
+static struct sfi_table_simple *sfi_search_mmap(void)
+{
+       struct sfi_table_header *sbh;
+       struct sfi_table_simple *sb;
+       u32 sys_entry_cnt;
+       u32 i;
+
+       /* Find SYST table */
+       sb = sfi_get_table_by_sig(SFI_BASE_ADDR, SFI_SIG_SYST);
+       if (!sb) {
+               error("sfi: failed to locate SYST table\n");
+               return NULL;
+       }
+
+       sys_entry_cnt = (sb->header.len - sizeof(*sbh)) / 8;
+
+       /* Search through each SYST entry for MMAP table */
+       for (i = 0; i < sys_entry_cnt; i++) {
+               sbh = (struct sfi_table_header *)(unsigned long)sb->pentry[i];
+
+               if (sfi_table_is_type(sbh, SFI_SIG_MMAP))
+                       return (struct sfi_table_simple *)sbh;
+       }
+
+       error("sfi: failed to locate SFI MMAP table\n");
+       return NULL;
+}
+
+#define sfi_for_each_mentry(i, sb, mentry)                             \
+       for (i = 0, mentry = (struct sfi_mem_entry *)sb->pentry;        \
+            i < SFI_GET_NUM_ENTRIES(sb, struct sfi_mem_entry);         \
+            i++, mentry++)                                             \
+
+static unsigned sfi_setup_e820(unsigned max_entries, struct e820entry *entries)
+{
+       struct sfi_table_simple *sb;
+       struct sfi_mem_entry *mentry;
+       unsigned long long start, end, size;
+       int type, total = 0;
+       u32 i;
+
+       sb = sfi_search_mmap();
+       if (!sb)
+               return 0;
+
+       sfi_for_each_mentry(i, sb, mentry) {
+               start = mentry->phys_start;
+               size = mentry->pages << 12;
+               end = start + size;
+
+               if (start > end)
+                       continue;
+
+               /* translate SFI mmap type to E820 map type */
+               switch (mentry->type) {
+               case SFI_MEM_CONV:
+                       type = E820_RAM;
+                       break;
+               case SFI_MEM_UNUSABLE:
+               case SFI_RUNTIME_SERVICE_DATA:
+                       continue;
+               default:
+                       type = E820_RESERVED;
+               }
+
+               if (total == E820MAX)
+                       break;
+               entries[total].addr = start;
+               entries[total].size = size;
+               entries[total].type = type;
+
+               total++;
+       }
+
+       return total;
+}
+
+static int sfi_get_bank_size(void)
+{
+       struct sfi_table_simple *sb;
+       struct sfi_mem_entry *mentry;
+       int bank = 0;
+       u32 i;
+
+       sb = sfi_search_mmap();
+       if (!sb)
+               return 0;
+
+       sfi_for_each_mentry(i, sb, mentry) {
+               if (mentry->type != SFI_MEM_CONV)
+                       continue;
+
+               gd->bd->bi_dram[bank].start = mentry->phys_start;
+               gd->bd->bi_dram[bank].size = mentry->pages << 12;
+               bank++;
+       }
+
+       return bank;
+}
+
+static phys_size_t sfi_get_ram_size(void)
+{
+       struct sfi_table_simple *sb;
+       struct sfi_mem_entry *mentry;
+       phys_size_t ram = 0;
+       u32 i;
+
+       sb = sfi_search_mmap();
+       if (!sb)
+               return 0;
+
+       sfi_for_each_mentry(i, sb, mentry) {
+               if (mentry->type != SFI_MEM_CONV)
+                       continue;
+
+               ram += mentry->pages << 12;
+       }
+
+       debug("sfi: RAM size %llu\n", ram);
+       return ram;
+}
+
+unsigned install_e820_map(unsigned max_entries, struct e820entry *entries)
+{
+       return sfi_setup_e820(max_entries, entries);
+}
+
+int dram_init_banksize(void)
+{
+       sfi_get_bank_size();
+       return 0;
+}
+
+int dram_init(void)
+{
+       gd->ram_size = sfi_get_ram_size();
+       return 0;
+}
diff --git a/arch/x86/cpu/tangier/tangier.c b/arch/x86/cpu/tangier/tangier.c
new file mode 100644 (file)
index 0000000..20d6c60
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 Intel Corporation
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/scu.h>
+#include <asm/u-boot-x86.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Miscellaneous platform dependent initializations
+ */
+int arch_cpu_init(void)
+{
+       return x86_cpu_init_f();
+}
+
+int checkcpu(void)
+{
+       return 0;
+}
+
+int print_cpuinfo(void)
+{
+       return default_print_cpuinfo();
+}
+
+void reset_cpu(ulong addr)
+{
+       scu_ipc_simple_command(IPCMSG_COLD_RESET, 0);
+}
index d6c44c978a9184fb788991d90755c3b0ecc4e6b2..6c6ebeade8c97a8e881090c3b4c01911abc783c5 100644 (file)
@@ -60,6 +60,25 @@ struct __packed sfi_mem_entry {
        u64     attrib;
 };
 
+/* Memory type definitions */
+enum sfi_mem_type {
+       SFI_MEM_RESERVED,
+       SFI_LOADER_CODE,
+       SFI_LOADER_DATA,
+       SFI_BOOT_SERVICE_CODE,
+       SFI_BOOT_SERVICE_DATA,
+       SFI_RUNTIME_SERVICE_CODE,
+       SFI_RUNTIME_SERVICE_DATA,
+       SFI_MEM_CONV,
+       SFI_MEM_UNUSABLE,
+       SFI_ACPI_RECLAIM,
+       SFI_ACPI_NVS,
+       SFI_MEM_MMIO,
+       SFI_MEM_IOPORT,
+       SFI_PAL_CODE,
+       SFI_MEM_TYPEMAX,
+};
+
 struct __packed sfi_cpu_table_entry {
        u32     apic_id;
 };