
Hi Andy,
On Tue, Apr 18, 2017 at 10:21 PM, Andy Shevchenko andriy.shevchenko@linux.intel.com wrote:
From: Felipe Balbi felipe.balbi@linux.intel.com
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
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 | 1 + arch/x86/cpu/Makefile | 1 + arch/x86/cpu/tangier/Kconfig | 20 ++++ arch/x86/cpu/tangier/Makefile | 1 + arch/x86/cpu/tangier/car.S | 13 +++ arch/x86/cpu/tangier/sdram.c | 234 +++++++++++++++++++++++++++++++++++++ arch/x86/cpu/tangier/tangier.c | 36 ++++++ arch/x86/include/asm/dma-mapping.h | 41 +++++++ 8 files changed, 347 insertions(+) create mode 100644 arch/x86/cpu/tangier/Kconfig create mode 100644 arch/x86/cpu/tangier/Makefile create mode 100644 arch/x86/cpu/tangier/car.S create mode 100644 arch/x86/cpu/tangier/sdram.c create mode 100644 arch/x86/cpu/tangier/tangier.c create mode 100644 arch/x86/include/asm/dma-mapping.h
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9ead3ebccf..31f2d154d4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -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
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 92a9023b0b..6f3535d216 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -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 index 0000000000..3545886a65 --- /dev/null +++ b/arch/x86/cpu/tangier/Kconfig @@ -0,0 +1,20 @@ +# +# Copyright (C) 2015 Intel, Inc +# +# 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 index 0000000000..d937737057 --- /dev/null +++ b/arch/x86/cpu/tangier/Makefile @@ -0,0 +1 @@ +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 index 0000000000..6982106c19 --- /dev/null +++ b/arch/x86/cpu/tangier/car.S @@ -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 index 0000000000..da046559a1 --- /dev/null +++ b/arch/x86/cpu/tangier/sdram.c @@ -0,0 +1,234 @@ +/*
- Copyright (c) 2011 The Chromium OS Authors.
- (C) Copyright 2010,2011
- Graeme Russ, graeme.russ@gmail.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <malloc.h> +#include <asm/bootparam.h> +#include <asm/e820.h> +#include <asm/global_data.h> +#include <asm/processor.h> +#include <asm/sections.h> +#include <asm/sfi.h> +#include <asm/u-boot-x86.h>
Can you double check if all these header files are needed here?
+DECLARE_GLOBAL_DATA_PTR;
+/* 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,
+};
Should this be moved to sfi.h?
+#define SFI_BASE_ADDR 0x000E0000 +#define SFI_LENGTH 0x00020000 +#define SFI_TABLE_LENGTH 16
Can you add some comments here? I guess U-Boot on tangier is not the 1st stage bootloader. It boots from the 1st stage bootloader and get memory information via SFI table which 1st stage bootloader provides?
+static int sfi_table_check(struct sfi_table_header *sbh) +{
char chksum = 0;
char *pos = (char *)sbh;
int i;
if (sbh->len < SFI_TABLE_LENGTH)
return -1;
if (sbh->len > SFI_LENGTH)
return -1;
for (i = 0; i < sbh->len; i++)
chksum += *pos++;
if (chksum)
error("sfi: Invalid checksum\n");
/* Checksum is OK if zero */
return chksum;
+}
+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 = NULL;
int 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))
break;
}
if (i >= SFI_LENGTH || !sb)
return NULL;
return sb;
+}
+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("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("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;
int 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;
int i;
sb = sfi_search_mmap();
if (!sb)
return -ENXIO;
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;
int 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("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) +{
int ret;
ret = sfi_get_bank_size();
if (ret < 0)
return ret;
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 index 0000000000..c06767b915 --- /dev/null +++ b/arch/x86/cpu/tangier/tangier.c @@ -0,0 +1,36 @@ +/*
- Copyright (c) 2011 The Chromium OS Authors.
- (C) Copyright 2008
- Graeme Russ, graeme.russ@gmail.com.
- 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);
+} diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h new file mode 100644 index 0000000000..7de4c08e36 --- /dev/null +++ b/arch/x86/include/asm/dma-mapping.h @@ -0,0 +1,41 @@ +/*
- (C) Copyright 2007
- Stelian Pop stelian@popies.net
- Lead Tech Design <www.leadtechdesign.com>
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __ASM_X86_DMA_MAPPING_H +#define __ASM_X86_DMA_MAPPING_H
+#define dma_mapping_error(x, y) 0
+enum dma_data_direction {
DMA_BIDIRECTIONAL = 0,
DMA_TO_DEVICE = 1,
DMA_FROM_DEVICE = 2,
+};
+static inline void *dma_alloc_coherent(size_t len, unsigned long *handle) +{
*handle = (unsigned long)memalign(ARCH_DMA_MINALIGN, len);
return (void *)*handle;
+}
+static inline void dma_free_coherent(void *addr) +{
free(addr);
+}
+static inline unsigned long dma_map_single(volatile void *vaddr, size_t len,
enum dma_data_direction dir)
+{
return (unsigned long)vaddr;
+}
+static inline void dma_unmap_single(volatile void *vaddr, size_t len,
unsigned long paddr)
+{ +}
+#endif /* __ASM_X86_DMA_MAPPING_H */
Why is this dma-mapping.h file needed? For x86, all memory are coherent, which is indicated in your implementation as well (malloc/free are used)
Regards, Bin