Re: [U-Boot] [PATCH 07/10] x86: Implement a cache for Memory Reference Code parameters

2015-01-05 Thread Simon Glass
Hi Bin,

On 5 January 2015 at 06:54, Bin Meng  wrote:
> Hi Simon,
>
> On Mon, Jan 5, 2015 at 9:49 AM, Simon Glass  wrote:
>> Hi Bin,
>>
>> On 4 January 2015 at 00:49, Bin Meng  wrote:
>>> Hi Simon,
>>>
>>> On Tue, Dec 30, 2014 at 9:12 AM, Simon Glass  wrote:
 The memory reference code takes a very long time to 'train' its SDRAM
 interface, around half a second. To avoid this delay on every boot we can
 store the parameters from the last training sessions to speed up the next.

 Add an implementation of this, storing the training data in CMOS RAM and
 SPI flash.
>>>
>>> Is storing mrc data to cmos ram not enough, so that we must store it
>>> to spi flash?
>>
>> It's about 3KB of data, so doesn't fit in CMOS.
>
> Sorry but I did not get into the details of the codes, but if CMOS
> cannot hold the whole MRC cache data, what information do we need save
> in the CMOS? Can we just save them into SPI flash all toghether
> without having CMOS?

The seed changes on every boot, even if the parameters end up being
the same. So in that case we would update the CMOS but not the SPI
flash. This is good, because the SPI flash has a limited life.

That said, I'm not sure how important this really is. I just don't
want to burn out the flash.

Regards,
Simon
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [PATCH 07/10] x86: Implement a cache for Memory Reference Code parameters

2015-01-05 Thread Bin Meng
Hi Simon,

On Mon, Jan 5, 2015 at 9:49 AM, Simon Glass  wrote:
> Hi Bin,
>
> On 4 January 2015 at 00:49, Bin Meng  wrote:
>> Hi Simon,
>>
>> On Tue, Dec 30, 2014 at 9:12 AM, Simon Glass  wrote:
>>> The memory reference code takes a very long time to 'train' its SDRAM
>>> interface, around half a second. To avoid this delay on every boot we can
>>> store the parameters from the last training sessions to speed up the next.
>>>
>>> Add an implementation of this, storing the training data in CMOS RAM and
>>> SPI flash.
>>
>> Is storing mrc data to cmos ram not enough, so that we must store it
>> to spi flash?
>
> It's about 3KB of data, so doesn't fit in CMOS.

Sorry but I did not get into the details of the codes, but if CMOS
cannot hold the whole MRC cache data, what information do we need save
in the CMOS? Can we just save them into SPI flash all toghether
without having CMOS?

[snip]

Regards,
Bin
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


Re: [U-Boot] [PATCH 07/10] x86: Implement a cache for Memory Reference Code parameters

2015-01-04 Thread Simon Glass
Hi Bin,

On 4 January 2015 at 00:49, Bin Meng  wrote:
> Hi Simon,
>
> On Tue, Dec 30, 2014 at 9:12 AM, Simon Glass  wrote:
>> The memory reference code takes a very long time to 'train' its SDRAM
>> interface, around half a second. To avoid this delay on every boot we can
>> store the parameters from the last training sessions to speed up the next.
>>
>> Add an implementation of this, storing the training data in CMOS RAM and
>> SPI flash.
>
> Is storing mrc data to cmos ram not enough, so that we must store it
> to spi flash?

It's about 3KB of data, so doesn't fit in CMOS.

>
>> Signed-off-by: Simon Glass 
>> ---
>>
>>  arch/x86/cpu/ivybridge/Makefile|   1 +
>>  arch/x86/cpu/ivybridge/mrccache.c  | 156 ++
>>  arch/x86/cpu/ivybridge/sdram.c | 277 
>> +
>>  arch/x86/include/asm/arch-ivybridge/mrccache.h |  51 +
>>  arch/x86/include/asm/global_data.h |   3 +
>>  5 files changed, 488 insertions(+)
>>  create mode 100644 arch/x86/cpu/ivybridge/mrccache.c
>>  create mode 100644 arch/x86/include/asm/arch-ivybridge/mrccache.h
>>
>> diff --git a/arch/x86/cpu/ivybridge/Makefile 
>> b/arch/x86/cpu/ivybridge/Makefile
>> index 0c7efae..3576b83 100644
>> --- a/arch/x86/cpu/ivybridge/Makefile
>> +++ b/arch/x86/cpu/ivybridge/Makefile
>> @@ -14,6 +14,7 @@ obj-y += lpc.o
>>  obj-y += me_status.o
>>  obj-y += model_206ax.o
>>  obj-y += microcode_intel.o
>> +obj-y += mrccache.o
>>  obj-y += northbridge.o
>>  obj-y += pch.o
>>  obj-y += pci.o
>> diff --git a/arch/x86/cpu/ivybridge/mrccache.c 
>> b/arch/x86/cpu/ivybridge/mrccache.c
>> new file mode 100644
>> index 000..182c995
>> --- /dev/null
>> +++ b/arch/x86/cpu/ivybridge/mrccache.c
>> @@ -0,0 +1,156 @@
>> +/*
>> + * From Coreboot src/southbridge/intel/bd82x6x/mrccache.c
>> + *
>> + * Copyright (C) 2014 Google Inc.
>> + *
>> + * SPDX-License-Identifier:GPL-2.0
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +static struct mrc_data_container *next_mrc_block(
>> +   struct mrc_data_container *mrc_cache)
>> +{
>> +   /* MRC data blocks are aligned within the region */
>> +   u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->data_size;
>> +   if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
>> +   mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
>> +   mrc_size += MRC_DATA_ALIGN;
>> +   }
>> +
>> +   u8 *region_ptr = (u8 *)mrc_cache;
>> +   region_ptr += mrc_size;
>> +   return (struct mrc_data_container *)region_ptr;
>> +}
>> +
>> +static int is_mrc_cache(struct mrc_data_container *cache)
>> +{
>> +   return cache && (cache->signature == MRC_DATA_SIGNATURE);
>> +}
>> +
>> +/*
>> + * Find the largest index block in the MRC cache. Return NULL if none is
>> + * found.
>> + */
>> +struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry)
>> +{
>> +   struct mrc_data_container *cache, *next;
>> +   ulong base_addr, end_addr;
>> +   uint id;
>> +
>> +   base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
>> +   end_addr = base_addr + entry->length;
>> +   cache = NULL;
>> +
>> +   /* Search for the last filled entry in the region */
>> +   for (id = 0, next = (struct mrc_data_container *)base_addr;
>> +is_mrc_cache(next);
>> +id++) {
>> +   cache = next;
>> +   next = next_mrc_block(next);
>> +   if ((ulong)next >= end_addr)
>> +   break;
>> +   }
>> +
>> +   if (id-- == 0) {
>> +   debug("%s: No valid MRC cache found.\n", __func__);
>> +   return NULL;
>> +   }
>> +
>> +   /* Verify checksum */
>> +   if (cache->checksum != compute_ip_checksum(cache->data,
>> +  cache->data_size)) {
>> +   printf("%s: MRC cache checksum mismatch\n", __func__);
>> +   return NULL;
>> +   }
>> +
>> +   debug("%s: picked entry %u from cache block\n", __func__, id);
>> +
>> +   return cache;
>> +}
>> +
>> +/**
>> + * find_next_mrc_cache() - get next cache entry
>> + *
>> + * @entry: MRC cache flash area
>> + * @cache: Entry to start from
>> + *
>> + * @return next cache entry if found, NULL if we got to the end
>> + */
>> +static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry 
>> *entry,
>> +   struct mrc_data_container *cache)
>> +{
>> +   ulong base_addr, end_addr;
>> +
>> +   base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
>> +   end_addr = base_addr + entry->length;
>> +
>> +   cache = next_mrc_block(cache);
>> +   if ((ulong)cache >= end_addr) {
>> +   /* Crossed the boundary */
>> +   cache = NULL;
>> +   debug("%s: no available entries found\n", __func__);
>> +   } else {
>> +   debug("%s: pic

Re: [U-Boot] [PATCH 07/10] x86: Implement a cache for Memory Reference Code parameters

2015-01-03 Thread Bin Meng
Hi Simon,

On Tue, Dec 30, 2014 at 9:12 AM, Simon Glass  wrote:
> The memory reference code takes a very long time to 'train' its SDRAM
> interface, around half a second. To avoid this delay on every boot we can
> store the parameters from the last training sessions to speed up the next.
>
> Add an implementation of this, storing the training data in CMOS RAM and
> SPI flash.

Is storing mrc data to cmos ram not enough, so that we must store it
to spi flash?

> Signed-off-by: Simon Glass 
> ---
>
>  arch/x86/cpu/ivybridge/Makefile|   1 +
>  arch/x86/cpu/ivybridge/mrccache.c  | 156 ++
>  arch/x86/cpu/ivybridge/sdram.c | 277 
> +
>  arch/x86/include/asm/arch-ivybridge/mrccache.h |  51 +
>  arch/x86/include/asm/global_data.h |   3 +
>  5 files changed, 488 insertions(+)
>  create mode 100644 arch/x86/cpu/ivybridge/mrccache.c
>  create mode 100644 arch/x86/include/asm/arch-ivybridge/mrccache.h
>
> diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile
> index 0c7efae..3576b83 100644
> --- a/arch/x86/cpu/ivybridge/Makefile
> +++ b/arch/x86/cpu/ivybridge/Makefile
> @@ -14,6 +14,7 @@ obj-y += lpc.o
>  obj-y += me_status.o
>  obj-y += model_206ax.o
>  obj-y += microcode_intel.o
> +obj-y += mrccache.o
>  obj-y += northbridge.o
>  obj-y += pch.o
>  obj-y += pci.o
> diff --git a/arch/x86/cpu/ivybridge/mrccache.c 
> b/arch/x86/cpu/ivybridge/mrccache.c
> new file mode 100644
> index 000..182c995
> --- /dev/null
> +++ b/arch/x86/cpu/ivybridge/mrccache.c
> @@ -0,0 +1,156 @@
> +/*
> + * From Coreboot src/southbridge/intel/bd82x6x/mrccache.c
> + *
> + * Copyright (C) 2014 Google Inc.
> + *
> + * SPDX-License-Identifier:GPL-2.0
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +static struct mrc_data_container *next_mrc_block(
> +   struct mrc_data_container *mrc_cache)
> +{
> +   /* MRC data blocks are aligned within the region */
> +   u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->data_size;
> +   if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
> +   mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
> +   mrc_size += MRC_DATA_ALIGN;
> +   }
> +
> +   u8 *region_ptr = (u8 *)mrc_cache;
> +   region_ptr += mrc_size;
> +   return (struct mrc_data_container *)region_ptr;
> +}
> +
> +static int is_mrc_cache(struct mrc_data_container *cache)
> +{
> +   return cache && (cache->signature == MRC_DATA_SIGNATURE);
> +}
> +
> +/*
> + * Find the largest index block in the MRC cache. Return NULL if none is
> + * found.
> + */
> +struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry)
> +{
> +   struct mrc_data_container *cache, *next;
> +   ulong base_addr, end_addr;
> +   uint id;
> +
> +   base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
> +   end_addr = base_addr + entry->length;
> +   cache = NULL;
> +
> +   /* Search for the last filled entry in the region */
> +   for (id = 0, next = (struct mrc_data_container *)base_addr;
> +is_mrc_cache(next);
> +id++) {
> +   cache = next;
> +   next = next_mrc_block(next);
> +   if ((ulong)next >= end_addr)
> +   break;
> +   }
> +
> +   if (id-- == 0) {
> +   debug("%s: No valid MRC cache found.\n", __func__);
> +   return NULL;
> +   }
> +
> +   /* Verify checksum */
> +   if (cache->checksum != compute_ip_checksum(cache->data,
> +  cache->data_size)) {
> +   printf("%s: MRC cache checksum mismatch\n", __func__);
> +   return NULL;
> +   }
> +
> +   debug("%s: picked entry %u from cache block\n", __func__, id);
> +
> +   return cache;
> +}
> +
> +/**
> + * find_next_mrc_cache() - get next cache entry
> + *
> + * @entry: MRC cache flash area
> + * @cache: Entry to start from
> + *
> + * @return next cache entry if found, NULL if we got to the end
> + */
> +static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry 
> *entry,
> +   struct mrc_data_container *cache)
> +{
> +   ulong base_addr, end_addr;
> +
> +   base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
> +   end_addr = base_addr + entry->length;
> +
> +   cache = next_mrc_block(cache);
> +   if ((ulong)cache >= end_addr) {
> +   /* Crossed the boundary */
> +   cache = NULL;
> +   debug("%s: no available entries found\n", __func__);
> +   } else {
> +   debug("%s: picked next entry from cache block at %p\n",
> + __func__, cache);
> +   }
> +
> +   return cache;
> +}
> +
> +int mrccache_update(struct spi_flash *sf, struct fmap_entry *entry,
> +   struct mrc_data_container *cur)
>

[U-Boot] [PATCH 07/10] x86: Implement a cache for Memory Reference Code parameters

2014-12-29 Thread Simon Glass
The memory reference code takes a very long time to 'train' its SDRAM
interface, around half a second. To avoid this delay on every boot we can
store the parameters from the last training sessions to speed up the next.

Add an implementation of this, storing the training data in CMOS RAM and
SPI flash.

Signed-off-by: Simon Glass 
---

 arch/x86/cpu/ivybridge/Makefile|   1 +
 arch/x86/cpu/ivybridge/mrccache.c  | 156 ++
 arch/x86/cpu/ivybridge/sdram.c | 277 +
 arch/x86/include/asm/arch-ivybridge/mrccache.h |  51 +
 arch/x86/include/asm/global_data.h |   3 +
 5 files changed, 488 insertions(+)
 create mode 100644 arch/x86/cpu/ivybridge/mrccache.c
 create mode 100644 arch/x86/include/asm/arch-ivybridge/mrccache.h

diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile
index 0c7efae..3576b83 100644
--- a/arch/x86/cpu/ivybridge/Makefile
+++ b/arch/x86/cpu/ivybridge/Makefile
@@ -14,6 +14,7 @@ obj-y += lpc.o
 obj-y += me_status.o
 obj-y += model_206ax.o
 obj-y += microcode_intel.o
+obj-y += mrccache.o
 obj-y += northbridge.o
 obj-y += pch.o
 obj-y += pci.o
diff --git a/arch/x86/cpu/ivybridge/mrccache.c 
b/arch/x86/cpu/ivybridge/mrccache.c
new file mode 100644
index 000..182c995
--- /dev/null
+++ b/arch/x86/cpu/ivybridge/mrccache.c
@@ -0,0 +1,156 @@
+/*
+ * From Coreboot src/southbridge/intel/bd82x6x/mrccache.c
+ *
+ * Copyright (C) 2014 Google Inc.
+ *
+ * SPDX-License-Identifier:GPL-2.0
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct mrc_data_container *next_mrc_block(
+   struct mrc_data_container *mrc_cache)
+{
+   /* MRC data blocks are aligned within the region */
+   u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->data_size;
+   if (mrc_size & (MRC_DATA_ALIGN - 1UL)) {
+   mrc_size &= ~(MRC_DATA_ALIGN - 1UL);
+   mrc_size += MRC_DATA_ALIGN;
+   }
+
+   u8 *region_ptr = (u8 *)mrc_cache;
+   region_ptr += mrc_size;
+   return (struct mrc_data_container *)region_ptr;
+}
+
+static int is_mrc_cache(struct mrc_data_container *cache)
+{
+   return cache && (cache->signature == MRC_DATA_SIGNATURE);
+}
+
+/*
+ * Find the largest index block in the MRC cache. Return NULL if none is
+ * found.
+ */
+struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry)
+{
+   struct mrc_data_container *cache, *next;
+   ulong base_addr, end_addr;
+   uint id;
+
+   base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
+   end_addr = base_addr + entry->length;
+   cache = NULL;
+
+   /* Search for the last filled entry in the region */
+   for (id = 0, next = (struct mrc_data_container *)base_addr;
+is_mrc_cache(next);
+id++) {
+   cache = next;
+   next = next_mrc_block(next);
+   if ((ulong)next >= end_addr)
+   break;
+   }
+
+   if (id-- == 0) {
+   debug("%s: No valid MRC cache found.\n", __func__);
+   return NULL;
+   }
+
+   /* Verify checksum */
+   if (cache->checksum != compute_ip_checksum(cache->data,
+  cache->data_size)) {
+   printf("%s: MRC cache checksum mismatch\n", __func__);
+   return NULL;
+   }
+
+   debug("%s: picked entry %u from cache block\n", __func__, id);
+
+   return cache;
+}
+
+/**
+ * find_next_mrc_cache() - get next cache entry
+ *
+ * @entry: MRC cache flash area
+ * @cache: Entry to start from
+ *
+ * @return next cache entry if found, NULL if we got to the end
+ */
+static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry *entry,
+   struct mrc_data_container *cache)
+{
+   ulong base_addr, end_addr;
+
+   base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
+   end_addr = base_addr + entry->length;
+
+   cache = next_mrc_block(cache);
+   if ((ulong)cache >= end_addr) {
+   /* Crossed the boundary */
+   cache = NULL;
+   debug("%s: no available entries found\n", __func__);
+   } else {
+   debug("%s: picked next entry from cache block at %p\n",
+ __func__, cache);
+   }
+
+   return cache;
+}
+
+int mrccache_update(struct spi_flash *sf, struct fmap_entry *entry,
+   struct mrc_data_container *cur)
+{
+   struct mrc_data_container *cache;
+   ulong offset;
+   ulong base_addr;
+   int ret;
+
+   /* Find the last used block */
+   base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset;
+   debug("Updating MRC cache data\n");
+   cache = mrccache_find_current(entry);
+   if (cache && (cache->data_size == cur->data_size) &&
+   (!memcmp(cache, cur, cache->data_size + sizeof(*cur {
+