From: David Gibson <david@gibson.dropbear.id.au>
To: BALATON Zoltan <balaton@eik.bme.hu>
Cc: qemu-devel@nongnu.org, qemu-ppc@nongnu.org,
Peter Maydell <peter.maydell@linaro.org>,
Paolo Bonzini <pbonzini@redhat.com>,
Aleksandar Markovic <amarkovic@wavecomp.com>
Subject: Re: [Qemu-devel] [PATCH 1/8] smbus: Add a helper to generate SPD EEPROM data
Date: Wed, 2 Jan 2019 15:09:00 +1100 [thread overview]
Message-ID: <20190102040900.GL27457@umbus.fritz.box> (raw)
In-Reply-To: <fc40f941cf84750609e1093eca98fd9248a0981e.1546394798.git.balaton@eik.bme.hu>
[-- Attachment #1: Type: text/plain, Size: 6830 bytes --]
On Wed, Jan 02, 2019 at 03:06:38AM +0100, 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>
> ---
> hw/i2c/smbus_eeprom.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++
> include/hw/i2c/smbus.h | 3 ++
> 2 files changed, 131 insertions(+)
>
> diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
> index f18aa3de35..a1f51eb921 100644
> --- a/hw/i2c/smbus_eeprom.c
> +++ b/hw/i2c/smbus_eeprom.c
> @@ -23,6 +23,8 @@
> */
>
> #include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "qemu/units.h"
> #include "hw/hw.h"
> #include "hw/i2c/i2c.h"
> #include "hw/i2c/smbus.h"
> @@ -162,3 +164,129 @@ 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)
> +{
> + 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:
> + error_report("Unknown SDRAM type");
> + abort();
The error handling might work a little cleaner if you give this
function an Error ** parameter, then just pass in &error_abort from
the callers.
> + }
> + size = ram_size >> 20; /* work in terms of megabytes */
> + if (size < 4) {
> + error_report("SDRAM size is too small");
> + return NULL;
> + }
> + sz_log2 = 31 - clz32(size);
> + size = 1U << sz_log2;
> + if (ram_size > size * MiB) {
> + warn_report("SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, "
> + "truncating to %u MB", ram_size, size);
> + }
> + if (sz_log2 < min_log2) {
> + warn_report("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;
> + }
What do these various fall back cases represent? Are they bugs in the
callers, or a user configuration error?
If the first, we should just assert or abort. If the second I think
we should still die with a fatal error - allowing broken
configurations to work with just a warning is kind of begging to
maintain nasty compatiliby cruft in the future.
> + }
> +
> + nbanks = 1;
> + while (sz_log2 > max_log2 && nbanks < 8) {
> + sz_log2--;
> + nbanks++;
> + }
> +
> + if (size > (1ULL << sz_log2) * nbanks) {
> + warn_report("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);
> + 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..0adc2991b5 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);
> +
> #endif
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2019-01-02 4:40 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-02 2:06 [Qemu-devel] [PATCH 0/8] Misc sam460ex related patches BALATON Zoltan
2019-01-02 2:06 ` [Qemu-devel] [PATCH 3/8] ppc4xx: Disable debug logging by default BALATON Zoltan
2019-01-02 4:27 ` David Gibson
2019-01-02 2:06 ` [Qemu-devel] [PATCH 5/8] ppc4xx: Rename ppc4xx_sdram_t in ppc440_uc.c to ppc440_sdram_t BALATON Zoltan
2019-01-02 4:15 ` David Gibson
2019-01-02 2:06 ` [Qemu-devel] [PATCH 6/8] ppc4xx: Pass array index to function instead of pointer into the array BALATON Zoltan
2019-01-02 4:17 ` David Gibson
2019-01-02 2:06 ` [Qemu-devel] [PATCH 8/8] MAINTAINERS: Add more files to sam460ex BALATON Zoltan
2019-01-02 4:29 ` David Gibson
2019-01-02 2:06 ` [Qemu-devel] [PATCH 2/8] sam460ex: Clean up SPD EEPROM creation BALATON Zoltan
2019-01-02 4:11 ` David Gibson
2019-01-02 12:49 ` BALATON Zoltan
2019-01-03 1:54 ` David Gibson
2019-01-02 2:06 ` [Qemu-devel] [PATCH 1/8] smbus: Add a helper to generate SPD EEPROM data BALATON Zoltan
2019-01-02 4:09 ` David Gibson [this message]
2019-01-02 12:36 ` BALATON Zoltan
2019-01-03 1:54 ` David Gibson
2019-01-02 2:06 ` [Qemu-devel] [PATCH 7/8] sam460ex: Fix support for memory larger than 1GB BALATON Zoltan
2019-01-02 2:06 ` [Qemu-devel] [PATCH 4/8] ppc4xx: Use ram_addr_t in ppc4xx_sdram_adjust() BALATON Zoltan
2019-01-02 4:15 ` David Gibson
2019-01-03 14:03 ` BALATON Zoltan
2019-01-04 5:17 ` David Gibson
2019-01-07 22:00 ` BALATON Zoltan
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=20190102040900.GL27457@umbus.fritz.box \
--to=david@gibson.dropbear.id.au \
--cc=amarkovic@wavecomp.com \
--cc=balaton@eik.bme.hu \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.