From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: BALATON Zoltan <balaton@eik.bme.hu>,
qemu-devel@nongnu.org, qemu-ppc@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
Paolo Bonzini <pbonzini@redhat.com>,
Aleksandar Markovic <amarkovic@wavecomp.com>,
David Gibson <david@gibson.dropbear.id.au>
Subject: Re: [Qemu-devel] [PATCH v3 1/6] smbus: Add a helper to generate SPD EEPROM data
Date: Wed, 9 Jan 2019 11:52:35 +0100 [thread overview]
Message-ID: <6c6cdb4b-b15c-0152-2cfe-4ac813d15111@redhat.com> (raw)
In-Reply-To: <a977bd81f7c1f2896837671545fbb01ebf286f4a.1546532844.git.balaton@eik.bme.hu>
Hi Zoltan,
On 1/3/19 5:27 PM, BALATON Zoltan wrote:
> There are several boards with SPD EEPROMs that are now using
> duplicated or slightly different hard coded data. Add a helper to
> generate SPD data for a memory module of given type and size that
> could be used by these boards (either as is or with further changes if
> needed) which should help cleaning this up and avoid further duplication.
>
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
> v3: Fixed a tab indent
> v2: Added errp parameter to pass errors back to caller
>
> hw/i2c/smbus_eeprom.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++
> include/hw/i2c/smbus.h | 3 ++
> 2 files changed, 133 insertions(+)
>
> diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
> index f18aa3de35..bef24a1ca4 100644
> --- a/hw/i2c/smbus_eeprom.c
> +++ b/hw/i2c/smbus_eeprom.c
> @@ -23,6 +23,9 @@
> */
>
> #include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "qemu/units.h"
> +#include "qapi/error.h"
> #include "hw/hw.h"
> #include "hw/i2c/i2c.h"
> #include "hw/i2c/smbus.h"
> @@ -162,3 +165,130 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
> smbus_eeprom_init_one(smbus, 0x50 + i, eeprom_buf + (i * 256));
> }
> }
> +
> +/* Generate SDRAM SPD EEPROM data describing a module of type and size */
> +uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size,
> + Error **errp)
> +{
> + uint8_t *spd;
> + uint8_t nbanks;
> + uint16_t density;
> + uint32_t size;
> + int min_log2, max_log2, sz_log2;
> + int i;
> +
> + switch (type) {
> + case SDR:
> + min_log2 = 2;
> + max_log2 = 9;
> + break;
> + case DDR:
> + min_log2 = 5;
> + max_log2 = 12;
> + break;
> + case DDR2:
> + min_log2 = 7;
> + max_log2 = 14;
> + break;
> + default:
> + g_assert_not_reached();
> + }
> + size = ram_size >> 20; /* work in terms of megabytes */
> + if (size < 4) {
> + error_setg(errp, "SDRAM size is too small");
> + return NULL;
> + }
> + sz_log2 = 31 - clz32(size);
> + size = 1U << sz_log2;
> + if (ram_size > size * MiB) {
> + error_setg(errp, "SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, "
> + "truncating to %u MB", ram_size, size);
> + }
> + if (sz_log2 < min_log2) {
> + error_setg(errp,
> + "Memory size is too small for SDRAM type, adjusting type");
> + if (size >= 32) {
> + type = DDR;
> + min_log2 = 5;
> + max_log2 = 12;
> + } else {
> + type = SDR;
> + min_log2 = 2;
> + max_log2 = 9;
> + }
> + }
> +
> + nbanks = 1;
> + while (sz_log2 > max_log2 && nbanks < 8) {
> + sz_log2--;
> + nbanks++;
> + }
> +
> + if (size > (1ULL << sz_log2) * nbanks) {
> + error_setg(errp, "Memory size is too big for SDRAM, truncating");
> + }
> +
> + /* split to 2 banks if possible to avoid a bug in MIPS Malta firmware */
> + if (nbanks == 1 && sz_log2 > min_log2) {
> + sz_log2--;
> + nbanks++;
> + }
> +
> + density = 1ULL << (sz_log2 - 2);
> + switch (type) {
> + case DDR2:
> + density = (density & 0xe0) | (density >> 8 & 0x1f);
> + break;
> + case DDR:
> + density = (density & 0xf8) | (density >> 8 & 0x07);
> + break;
> + case SDR:
> + default:
> + density &= 0xff;
> + break;
> + }
> +
> + spd = g_malloc0(256);
I think this buffer is eeprom-dependant, not SPD related.
Wouldn't it be cleaner to pass the (previously created) buffer as
argument such:
/* return true on success */
bool spd_data_fill(void *buf, size_t bufsize,
enum sdram_type type, ram_addr_t ram_size,
Error **errp);
or return something else like ssize_t.
> + spd[0] = 128; /* data bytes in EEPROM */
> + spd[1] = 8; /* log2 size of EEPROM */
> + spd[2] = type;
> + spd[3] = 13; /* row address bits */
> + spd[4] = 10; /* column address bits */
> + spd[5] = (type == DDR2 ? nbanks - 1 : nbanks);
> + spd[6] = 64; /* module data width */
> + /* reserved / data width high */
> + spd[8] = 4; /* interface voltage level */
> + spd[9] = 0x25; /* highest CAS latency */
> + spd[10] = 1; /* access time */
> + /* DIMM configuration 0 = non-ECC */
> + spd[12] = 0x82; /* refresh requirements */
> + spd[13] = 8; /* primary SDRAM width */
> + /* ECC SDRAM width */
> + spd[15] = (type == DDR2 ? 0 : 1); /* reserved / delay for random col rd */
> + spd[16] = 12; /* burst lengths supported */
> + spd[17] = 4; /* banks per SDRAM device */
> + spd[18] = 12; /* ~CAS latencies supported */
> + spd[19] = (type == DDR2 ? 0 : 1); /* reserved / ~CS latencies supported */
> + spd[20] = 2; /* DIMM type / ~WE latencies */
> + /* module features */
> + /* memory chip features */
> + spd[23] = 0x12; /* clock cycle time @ medium CAS latency */
> + /* data access time */
> + /* clock cycle time @ short CAS latency */
> + /* data access time */
> + spd[27] = 20; /* min. row precharge time */
> + spd[28] = 15; /* min. row active row delay */
> + spd[29] = 20; /* min. ~RAS to ~CAS delay */
> + spd[30] = 45; /* min. active to precharge time */
> + spd[31] = density;
> + spd[32] = 20; /* addr/cmd setup time */
> + spd[33] = 8; /* addr/cmd hold time */
> + spd[34] = 20; /* data input setup time */
> + spd[35] = 8; /* data input hold time */
> +
> + /* checksum */
> + for (i = 0; i < 63; i++) {
> + spd[63] += spd[i];
> + }
> + return spd;
> +}
> diff --git a/include/hw/i2c/smbus.h b/include/hw/i2c/smbus.h
> index d8b1b9ee81..d3dd0fcb14 100644
> --- a/include/hw/i2c/smbus.h
> +++ b/include/hw/i2c/smbus.h
> @@ -93,4 +93,7 @@ void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf);
> void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
> const uint8_t *eeprom_spd, int size);
>
> +enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 };
> +uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp);
> +
> #endif
>
next prev parent reply other threads:[~2019-01-09 10:52 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-03 16:27 [Qemu-devel] [PATCH v3 0/6] Misc sam460ex related patches BALATON Zoltan
2019-01-03 16:27 ` [Qemu-devel] [PATCH v3 3/6] ppc4xx: Use ram_addr_t in ppc4xx_sdram_adjust() BALATON Zoltan
2019-01-03 16:27 ` [Qemu-devel] [PATCH v3 1/6] smbus: Add a helper to generate SPD EEPROM data BALATON Zoltan
2019-01-09 10:52 ` Philippe Mathieu-Daudé [this message]
2019-01-09 12:15 ` BALATON Zoltan
2019-01-09 12:47 ` Philippe Mathieu-Daudé
2019-01-09 17:31 ` BALATON Zoltan
2019-01-09 18:05 ` [Qemu-devel] [Qemu-ppc] " BALATON Zoltan
2019-01-09 18:13 ` Philippe Mathieu-Daudé
2019-01-03 16:27 ` [Qemu-devel] [PATCH v3 2/6] sam460ex: Clean up SPD EEPROM creation BALATON Zoltan
2019-01-03 16:27 ` [Qemu-devel] [PATCH v3 4/6] ppc4xx: Rename ppc4xx_sdram_t in ppc440_uc.c to ppc440_sdram_t BALATON Zoltan
2019-01-03 16:27 ` [Qemu-devel] [PATCH v3 6/6] sam460ex: Fix support for memory larger than 1GB BALATON Zoltan
2019-01-03 16:27 ` [Qemu-devel] [PATCH v3 5/6] ppc4xx: Pass array index to function instead of pointer into the array BALATON Zoltan
2019-01-09 3:23 ` [Qemu-devel] [PATCH v3 0/6] Misc sam460ex related patches David Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6c6cdb4b-b15c-0152-2cfe-4ac813d15111@redhat.com \
--to=philmd@redhat.com \
--cc=amarkovic@wavecomp.com \
--cc=balaton@eik.bme.hu \
--cc=david@gibson.dropbear.id.au \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).