blob: f58f48a7b83609acf18e29cb2749d7114069cf8c [file] [log] [blame]
/*
* Copyright 2013, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "mosys/log.h"
#include "mosys/platform.h"
#include "lib/ddr3.h"
#include "lib/math.h"
#include "lib/spd.h"
#include "peach.h"
/* Treat the chips on each channel as a logical DIMM */
#define PEACH_PIT_DIMM_COUNT 2
/* FIXME: double-check that these are final values... */
static const uint8_t samsung_ddr3_1600_1rank_spd[SPD_MAX_LENGTH] = {
[DDR3_SPD_REG_SIZE_CRC] = 0x92,
[DDR3_SPD_REG_REVISION] = 0x12,
[DDR3_SPD_REG_DEVICE_TYPE] = 0x0b,
[DDR3_SPD_REG_MODULE_TYPE] = 0x03,
[DDR3_SPD_REG_DENSITY_BANKS] = 0x04, /* 8 banks * 512Mbits = 4Gb */
[DDR3_SPD_REG_ADDRESSING] = 0x32, /* 15 rows, 10 cols */
[DDR3_SPD_REG_VOLTAGE] = 0x02, /* 1.35V */
[DDR3_SPD_REG_MODULE_ORG] = 0x02, /* 1 ranks, x16 */
[DDR3_SPD_REG_MODULE_BUS_WIDTH] = 0x02, /* 32-bit channel */
/* DDR3-1600 = (1/8)ns * 10 = 1.25ns */
[DDR3_SPD_REG_MTB_DIVIDEND] = 1,
[DDR3_SPD_REG_MTB_DIVISOR] = 8,
[DDR3_SPD_REG_TCK_MIN] = 10,
/* 5, 6, 7, 8, 9, 10, 11 */
[DDR3_SPD_REG_CAS_LAT_LSB] = 0xfc,
[DDR3_SPD_REG_CAS_LAT_MSB] = 0x00,
/* CL-tRCD-tRP: 11-11-11 */
[DDR3_SPD_REG_TAA_MIN] = 0x6e, /* 13.75ns */
[DDR3_SPD_REG_TWR_MIN] = 0x78, /* 15ns */
[DDR3_SPD_REG_TRCD_MIN] = 0x6e, /* 13.75ns */
/* Samsung is bank 1, number 78 (JEP-106) */
[DDR3_SPD_REG_MODULE_MANUF_JEDEC_ID_LSB] = 0,
[DDR3_SPD_REG_MODULE_MANUF_JEDEC_ID_MSB] = 78,
[DDR3_SPD_REG_MODULE_MANUF_SERIAL_0] = 0x00000000,
[DDR3_SPD_REG_MODULE_MANUF_SERIAL_1] = 0x00000000,
[DDR3_SPD_REG_MODULE_MANUF_SERIAL_2] = 0x00000000,
[DDR3_SPD_REG_MODULE_MANUF_SERIAL_3] = 0x00000000,
[DDR3_SPD_REG_MODULE_PART_NUM_0] = 'K',
[DDR3_SPD_REG_MODULE_PART_NUM_1] = '4',
[DDR3_SPD_REG_MODULE_PART_NUM_2] = 'B',
[DDR3_SPD_REG_MODULE_PART_NUM_3] = '4',
[DDR3_SPD_REG_MODULE_PART_NUM_4] = 'G',
[DDR3_SPD_REG_MODULE_PART_NUM_5] = '1',
[DDR3_SPD_REG_MODULE_PART_NUM_6] = '6',
[DDR3_SPD_REG_MODULE_PART_NUM_7] = '4',
[DDR3_SPD_REG_MODULE_PART_NUM_8] = '6',
[DDR3_SPD_REG_MODULE_PART_NUM_9] = 'B',
[DDR3_SPD_REG_MODULE_PART_NUM_10] = '-',
[DDR3_SPD_REG_MODULE_PART_NUM_11] = 'H',
[DDR3_SPD_REG_MODULE_PART_NUM_12] = 'Y',
[DDR3_SPD_REG_MODULE_PART_NUM_13] = 'K',
[DDR3_SPD_REG_MODULE_PART_NUM_14] = '0',
[DDR3_SPD_REG_MODULE_PART_NUM_15] = 0,
[DDR3_SPD_REG_MODULE_PART_NUM_16] = 0,
[DDR3_SPD_REG_MODULE_PART_NUM_17] = 0,
};
/*
* dimm_count - return total number of dimm slots
*
* @intf: platform interface
*
* returns dimm slot count
*/
static int dimm_count(struct platform_intf *intf)
{
return PEACH_PIT_DIMM_COUNT;
}
static int spd_read(struct platform_intf *intf,
int dimm, int reg, int len, uint8_t *buf)
{
int rc = 0;
switch (peach_board_config) {
case PEACH_PIT_CONFIG_REV_0_0:
case PEACH_PIT_CONFIG_REV_3_0:
case PEACH_PIT_CONFIG_REV_4_0:
case PEACH_PIT_CONFIG_REV_5_0:
case PEACH_PIT_CONFIG_REV_6_0:
case PEACH_PIT_CONFIG_REV_7_0:
case PEACH_PIT_CONFIG_REV_9_0:
case PEACH_PIT_CONFIG_REV_A_0:
case PEACH_PIT_CONFIG_REV_B_0:
case PEACH_PIT_CONFIG_REV_C_0:
case PEACH_PIT_CONFIG_REV_D_0:
case PEACH_PIT_CONFIG_REV_D_1:
case PEACH_PIT_CONFIG_REV_E_0:
case PEACH_PIT_CONFIG_REV_E_1:
case PEACH_PIT_CONFIG_REV_F_0:
case PEACH_PIT_CONFIG_REV_F_1:
case PEACH_PIT_CONFIG_REV_10_0:
case PEACH_PIT_CONFIG_REV_10_1:
case PEACH_PI_CONFIG_REV_8_4:
case PEACH_PI_CONFIG_REV_9_4:
case PEACH_PI_CONFIG_REV_D_4:
case PEACH_PI_CONFIG_REV_D_5:
case PEACH_PI_CONFIG_REV_E_4:
case PEACH_PI_CONFIG_REV_E_5:
case PEACH_PI_CONFIG_REV_F_4:
case PEACH_PI_CONFIG_REV_F_5:
case PEACH_PI_CONFIG_REV_10_4:
case PEACH_PI_CONFIG_REV_10_5:
memcpy(buf, &samsung_ddr3_1600_1rank_spd[reg], len);
rc = len;
break;
case PEACH_PIT_CONFIG_REV_7_2:
case PEACH_PIT_CONFIG_REV_9_2:
case PEACH_PIT_CONFIG_REV_A_2:
case PEACH_PIT_CONFIG_REV_B_2:
case PEACH_PIT_CONFIG_REV_C_2:
case PEACH_PIT_CONFIG_REV_D_2:
case PEACH_PIT_CONFIG_REV_D_3:
case PEACH_PIT_CONFIG_REV_E_2:
case PEACH_PIT_CONFIG_REV_E_3:
case PEACH_PIT_CONFIG_REV_F_2:
case PEACH_PIT_CONFIG_REV_F_3:
case PEACH_PIT_CONFIG_REV_10_2:
case PEACH_PIT_CONFIG_REV_10_3:
case PEACH_PI_CONFIG_REV_A_6:
case PEACH_PI_CONFIG_REV_B_6:
case PEACH_PI_CONFIG_REV_C_6:
case PEACH_PI_CONFIG_REV_D_6:
case PEACH_PI_CONFIG_REV_D_7:
case PEACH_PI_CONFIG_REV_E_6:
case PEACH_PI_CONFIG_REV_E_7:
case PEACH_PI_CONFIG_REV_F_6:
case PEACH_PI_CONFIG_REV_F_7:
case PEACH_PI_CONFIG_REV_10_6:
case PEACH_PI_CONFIG_REV_10_7:
/* 4GB models have the second rank populated */
memcpy(buf, &samsung_ddr3_1600_1rank_spd[reg], len);
buf[DDR3_SPD_REG_MODULE_ORG] &= ~__mask(5, 3);
buf[DDR3_SPD_REG_MODULE_ORG] |= 1 << 3;
rc = len;
break;
default:
rc = -1;
break;
}
return rc;
}
static struct memory_spd_cb spd_cb = {
.read = spd_read,
};
struct memory_cb peach_memory_cb = {
.dimm_count = dimm_count,
.spd = &spd_cb,
};