From 1cc98c78e8cc78900b548ad2447a6ef2891d30e7 Mon Sep 17 00:00:00 2001 From: fandongdong Date: Fri, 26 Oct 2012 13:34:17 +0800 Subject: [PATCH] Add the type 16 and type 17 of smbios for PMON Now the type 16 of smbios support Physical Memory Array and the type 17 of smbios support Memory Device. Targets: Bonito3aserver Bonito3a780e Bonito3b780e --- Targets/Bonito3a780e/Bonito/start.S | 65 ++++- Targets/Bonito3aserver/Bonito/start.S | 63 +++++ Targets/Bonito3b780e/Bonito/start.S | 64 +++++ pmon/common/smbios/smbios.c | 368 +++++++++++++++++++++++++- pmon/common/smbios/smbios_types.h | 35 ++- 5 files changed, 568 insertions(+), 27 deletions(-) diff --git a/Targets/Bonito3a780e/Bonito/start.S b/Targets/Bonito3a780e/Bonito/start.S index fe052a74..daa151cf 100644 --- a/Targets/Bonito3a780e/Bonito/start.S +++ b/Targets/Bonito3a780e/Bonito/start.S @@ -1648,6 +1648,8 @@ TM_over: ########################################## bootnow: + bal spd_info_store + nop; TTYDBG("Copy PMON to execute location...\r\n") #ifdef DEBUG_LOCORE TTYDBG(" start = 0x") @@ -1892,7 +1894,68 @@ TM_over: jr ra nop END(CPU_TLBInit) - + + LEAF(spd_info_store) + move t8,ra + + TTYDBG("\r\n spd_info_store begain.\r\n") + + dli t5, 0xffffffff8fffa000; + + dli t7, 0xa1; + dli t6, 0xa9; + + 4: + move a0, t7 + dli a1, 0x2; + //GET_I2C_NODE_ID_a2 + bal i2cread; + nop; + + dli t3, 0x80 + bltu v0, t3, 2f + nop; + move t3, t5; + daddiu t3, 0x100; + move t4, t5; + 1: + sb zero,0(t4); + daddiu t4, 0x1; + bltu t4, t3, 1b + nop; + + b 3f + nop; + + 2: + move t4, t5; + dli t0, 0x0; //used as counter + 1: + move a0, t7; + move a1, t0; + //GET_I2C_NODE_ID_a2 + bal i2cread; + nop; + + sb v0, 0(t4); + + dli a1, 0x100 + daddiu t4, 0x1; + daddiu t0, 0x1; + bne t0, a1, 1b; + nop + 3: + daddiu t5, 0x100; + daddiu t7, 0x2; + + bltu t7, t6, 4b + nop + + TTYDBG("\r\n spd_info_store done.\r\n") + + jr t8 + nop + END(spd_info_store) LEAF(stringserial) move a2, ra #ifdef ROM_EXCEPTION diff --git a/Targets/Bonito3aserver/Bonito/start.S b/Targets/Bonito3aserver/Bonito/start.S index 29ee1f52..690990b1 100644 --- a/Targets/Bonito3aserver/Bonito/start.S +++ b/Targets/Bonito3aserver/Bonito/start.S @@ -1969,6 +1969,8 @@ WatchDog_Close; ########################################## bootnow: + bal spd_info_store + nop; TTYDBG("Copy PMON to execute location...\r\n") #ifdef DEBUG_LOCORE TTYDBG(" start = 0x") @@ -2226,6 +2228,67 @@ LEAF(CPU_TLBInit) jr ra nop END(CPU_TLBInit) + LEAF(spd_info_store) + move t8,ra + + TTYDBG("\r\n spd_info_store begain.\r\n") + + dli t5, 0xffffffff8fffa000; + + dli t7, 0xa1; + dli t6, 0xb0; + + 4: + move a0, t7 + dli a1, 0x2; + //GET_I2C_NODE_ID_a2 + bal i2cread; + nop; + + dli t3, 0x80 + bltu v0, t3, 2f + nop; + move t3, t5; + daddiu t3, 0x100; + move t4, t5; + 1: + sb zero,0(t4); + daddiu t4, 0x1; + bltu t4, t3, 1b + nop; + + b 3f + nop; + + 2: + move t4, t5; + dli t0, 0x0; //used as counter + 1: + move a0, t7; + move a1, t0; + //GET_I2C_NODE_ID_a2 + bal i2cread; + nop; + + sb v0, 0(t4); + + dli a1, 0x100 + daddiu t4, 0x1; + daddiu t0, 0x1; + bne t0, a1, 1b; + nop + 3: + daddiu t5, 0x100; + daddiu t7, 0x2; + + bltu t7, t6, 4b + nop + + TTYDBG("\r\n spd_info_store done.\r\n") + + jr t8 + nop + END(spd_info_store) LEAF(stringserial) move a2, ra diff --git a/Targets/Bonito3b780e/Bonito/start.S b/Targets/Bonito3b780e/Bonito/start.S index 90ca2de4..b1abcacf 100644 --- a/Targets/Bonito3b780e/Bonito/start.S +++ b/Targets/Bonito3b780e/Bonito/start.S @@ -2178,6 +2178,8 @@ TM_over: ########################################## bootnow: + bal spd_info_store + nop; TTYDBG("Copy PMON to execute location...\r\n") #ifdef DEBUG_LOCORE TTYDBG(" start = 0x") @@ -2448,6 +2450,68 @@ END(get_mem_clk) nop END(CPU_TLBInit) + LEAF(spd_info_store) + move t8,ra + + TTYDBG("\r\n spd_info_store begain.\r\n") + + dli t5, 0xffffffff8fffa000; + + dli t7, 0xa1; + dli t6, 0xa9; + + 4: + move a0, t7 + dli a1, 0x2; + //GET_I2C_NODE_ID_a2 + bal i2cread; + nop; + + dli t3, 0x80 + bltu v0, t3, 2f + nop; + move t3, t5; + daddiu t3, 0x100; + move t4, t5; + 1: + sb zero,0(t4); + daddiu t4, 0x1; + bltu t4, t3, 1b + nop; + + b 3f + nop; + + 2: + move t4, t5; + dli t0, 0x0; //used as counter + 1: + move a0, t7; + move a1, t0; + //GET_I2C_NODE_ID_a2 + bal i2cread; + nop; + + sb v0, 0(t4); + + dli a1, 0x100 + daddiu t4, 0x1; + daddiu t0, 0x1; + bne t0, a1, 1b; + nop + 3: + daddiu t5, 0x100; + daddiu t7, 0x2; + + bltu t7, t6, 4b + nop + + TTYDBG("\r\n spd_info_store done.\r\n") + + jr t8 + nop + END(spd_info_store) + LEAF(stringserial) move a2, ra #ifdef ROM_EXCEPTION diff --git a/pmon/common/smbios/smbios.c b/pmon/common/smbios/smbios.c index bb1f8b07..b85382c9 100644 --- a/pmon/common/smbios/smbios.c +++ b/pmon/common/smbios/smbios.c @@ -27,6 +27,10 @@ #include "smbios.h" #include "smbios_types.h" +#define SPD_INFO_ADDR 0x8fffa000 +static unsigned short smbios_table_handle = 0; +static unsigned short memory_array_handle = 0; + void loongson_smbios_init(void); static size_t @@ -56,22 +60,33 @@ smbios_type_2_init(void *start); static void * smbios_type_4_init(void *start); +static void * +smbios_type_16_init(void *start, int dimmnum, int maximum_capacity); + +static void * +smbios_type_17_init(void *start, int slotnum); + static void * smbios_type_28_init(void *start); static void * smbios_type_127_init(void *start); +unsigned long long smbios_addr; + void loongson_smbios_init(void){ write_smbios_tables((void *)SMBIOS_PHYSICAL_ADDRESS); - } + static size_t write_smbios_tables(void *start) { - unsigned cpu_num, nr_structs = 0, max_struct_size = 0; + unsigned int cpu_num, nr_structs = 0, max_struct_size = 0; + unsigned int dimmnum = 0; + unsigned int maximum_capacity = 0; + unsigned int i; char *p, *q; - + p = (char *)start + sizeof(struct smbios_entry_point); @@ -88,6 +103,24 @@ write_smbios_tables(void *start) do_struct(smbios_type_1_init(p)); do_struct(smbios_type_2_init(p)); do_struct(smbios_type_4_init(p)); + +#ifdef LOONGSON_3ASINGLE + dimmnum = 4; + maximum_capacity = 8 * 1024* 1024; +#endif +#ifdef LOONGSON_3BSINGLE + dimmnum = 4; + maximum_capacity = 8 * 1024* 1024; +#endif +#ifdef LOONGSON_3ASERVER + dimmnum = 8; + maximum_capacity = 16 * 1024* 1024; +#endif + do_struct(smbios_type_16_init(p, dimmnum, maximum_capacity)); + for(i = 0; i < dimmnum; i++){ + do_struct(smbios_type_17_init(p, i)); + } + do_struct(smbios_type_28_init(p)); do_struct(smbios_type_127_init(p)); #undef do_struct @@ -188,6 +221,8 @@ smbios_type_0_init(void *start) char temp[20]; int i; + memset(p, 0, sizeof(*p)); + get_update(update); strncpy(temp, update, 4); strncpy(temp + 4, update + 5, 2); @@ -200,7 +235,7 @@ smbios_type_0_init(void *start) sprintf(pmon_version, "LoongSon-PMON-V3.0-%s", temp); p->header.type = 0; p->header.length = sizeof(struct smbios_type_0); - p->header.handle = 0; + p->header.handle = smbios_table_handle++; p->vendor_str = 1; p->version_str = 2; @@ -255,9 +290,10 @@ smbios_type_1_init(void *start) char *q; int i; + memset(p, 0, sizeof(*p)); p->header.type = 1; p->header.length = sizeof(struct smbios_type_1); - p->header.handle = 0x1; + p->header.handle = smbios_table_handle++; p->manufacturer_str = 1; p->product_name_str = 2; @@ -296,10 +332,12 @@ smbios_type_2_init(void *start) char board_name[50]; char board_version[10]; char *motherboard_serial[20]; + + memset(p, 0, sizeof(*p)); p->header.type = 2; p->header.length = sizeof(struct smbios_type_2); - p->header.handle = 0x2; + p->header.handle = smbios_table_handle++; p->manufacturer_str = 1; p->product_name_str = 2; @@ -336,10 +374,11 @@ smbios_type_4_init(void *start) unsigned int prid; unsigned int cpus; char cpu_version[64]; - + + memset(p, 0, sizeof(*p)); p->header.type = 4; p->header.length = sizeof(struct smbios_type_4); - p->header.handle = 4; + p->header.handle = smbios_table_handle++; p->socket_designation_str = 0; p->processor_type = 0x03; @@ -380,9 +419,9 @@ smbios_type_4_init(void *start) p->current_speed = atoi(getenv("cpuclock")) / 1000000; p->status = 0x02; p->upgrade = 0x01; - p->l1_cache_handle = 0; - p->l2_cache_handle = 0; - p->l3_cache_handle = 0; + p->l1_cache_handle = 0xffff; + p->l2_cache_handle = 0xffff; + p->l3_cache_handle = 0xffff; p->serial_number_str = 0; p->assert_tag_str = 0; p->part_number_str = 0; @@ -416,16 +455,318 @@ smbios_type_4_init(void *start) *((uint8_t *)start) = 0; return start+1; } +/*Type 16 -- Physical Memory Array*/ +static void * +smbios_type_16_init(void *start, int dimmnum, int maximum_capacity){ + + struct smbios_type_16 *p = (struct smbios_type_16 *)start; + + memset(p, 0, sizeof(*p)); + + p->header.type = 16; + p->header.length = sizeof(struct smbios_type_16); + p->header.handle = memory_array_handle = smbios_table_handle++; + + p->location = 0x03; + p->use = 0x03; + p->error_correction = 0x02; + p->maximum_capacity = maximum_capacity; + p->memory_error_information_handle = 0xfffe; + p->number_of_memory_devices = dimmnum; + + start += sizeof(struct smbios_type_16); + *((uint8_t *)start) = 0; + *((uint8_t *)(start + 1)) =0; + return start + 2; +} + +/* Type 17 Memory Device */ +unsigned char get_spd_byte(int slotnum, int offset){ + + unsigned char spd_byte; + + spd_byte = *(volatile unsigned char *)(SPD_INFO_ADDR + slotnum * 0x100 + offset); + return spd_byte; +} + +unsigned int get_ddr_size(int slotnum, int ddrtype){ + unsigned char offset_rank,offset_density,offset_0x08; + unsigned char density,capacity,Width,BWidth,rank; + int value = 0; + int size = 0; + + if(ddrtype == 0x8){ + offset_rank=0x05; + rank = get_spd_byte(slotnum, offset_rank) & 0xf; + rank++; + + offset_density=0x1F; + if(density==0x20) + value=128; + else if(density==0x40) + value=256; + else if(density==0x80) + value=512; + else if(density==0x01) + value=1024; + else if(density==0x02) + value=2048; + else if(density==0x04) + value=4096; + else + value=0; + + size = rank * value; + + } + if(ddrtype == 0xb){ + offset_density=0x04;//Capacity + capacity=get_spd_byte(slotnum, offset_density); + //Capacity is the total capacity of SDRAM + //bank=density; + capacity&=0x0F;//b[0:3] at 0x04 + + if(capacity==1) + value=512; + else if(capacity==2) + value=1024; + else if(capacity==3) + value=2048; + else if(capacity==4) + value=4096; + else if(capacity==5) + value=8192; + else if(capacity==6) + value=16384; + else + value=256; + offset_rank=0x07;//Rank + rank=get_spd_byte(slotnum, offset_rank); + Width=rank; + Width&=0x07;//b[0:2] at 0x07 + rank&=0x38;//00111000 , b[3:5] at 0x07 + rank=rank>>3; + rank++; + + switch(Width) + { + case 0:Width=4; break; + case 1:Width=8; break; + case 2:Width=16; break; + case 3:Width=32; break; + } + offset_0x08=0x08; + BWidth=get_spd_byte(slotnum,offset_0x08); + BWidth&=0x07;//b[0:2] at 0x08 + switch(BWidth) + { + case 0:BWidth=8; break; + case 1:BWidth=16; break; + case 2:BWidth=32; break; + case 3:BWidth=64; break; + } + size=(value/8)*BWidth/Width*rank; + } + + + return size; +} + +unsigned int get_ddr_speed(int slotnum, int ddrtype){ + unsigned char cycle=0,offset=0; + unsigned int speed = 0; + + if(ddrtype == 0x8){ + offset=0x09; + cycle=get_spd_byte(slotnum, offset); + if(cycle==0x50) + speed=400; + else if(cycle==0x3D) + speed=533; + else if(cycle==0x30) + speed=667; + else if(cycle==0x25) + speed=800; + } + + if(ddrtype == 0xb){ + offset=0x0C; + cycle=get_spd_byte(slotnum, offset); + if(cycle==0x14) + speed=800; + else if(cycle==0x0F) + speed=1066; + else if(cycle==0x0C) + speed=1333; + else if(cycle==0x0A) + speed=1600; + } + + return speed; + +} +void get_ddr_manustr(int slotnum, char manustr[],int ddrtype){ + unsigned char offset=0,manu=0; + + if(ddrtype == 0x8) + { + offset=0x40; + if((manu=get_spd_byte(slotnum, offset))==0x7F) + {//bank one + offset++; + if((manu=get_spd_byte(slotnum, offset))==0x7F) + {//banktwo + offset++; + if((manu=get_spd_byte(slotnum, offset))==0x7F) + {//bankthree + offset++; + if((manu=get_spd_byte(slotnum, offset))==0x7F) + {//bankfour + offset++; + manu=get_spd_byte(slotnum, offset); + } + } + } + } + + } + + if(ddrtype == 0xb){ + offset=0x76; + manu=get_spd_byte(slotnum, offset); + } + if(manu==0xAD) + strcpy(manustr,"Hynix"); + else if(manu==0xCE) + strcpy(manustr,"SamSung"); + else if(manu==0x0B) + strcpy(manustr,"Micron"); + else if(manu==0x98) + strcpy(manustr,"Kingston"); + else if(manu==0x25) + strcpy(manustr,"Kingmax"); + else if(manu==0x4f) + strcpy(manustr,"Transcend"); + else if(manu==0xCB) + strcpy(manustr,"A-DATA Technology"); + else + strcpy(manustr,"Unknow"); + + return 0; + +} +void get_ddr_snstr(int slotnum, char snstr[], int ddrtype){ + char i = 0, offset, tmp; + if(ddrtype == 0x8) + offset = 95; + if(ddrtype == 0xb) + offset = 122; + for(i = 0; i < 4; i++){ + tmp = get_spd_byte(slotnum, i + offset); + snstr[i * 2] = (((tmp & 0xf0) >> 4) > 9) ? (((tmp & 0xf0) >> 4) - 0xa + 'A') : (((tmp & 0xf0) >> 4) + '0'); + snstr[i * 2 + 1] = ((tmp & 0xf) > 9) ? ((tmp & 0xf) - 0xa + 'A') : ((tmp & 0xf) + '0'); + } + snstr[i * 2] = '\0'; + return 0; +} +void get_ddr_pnstr(int slotnum, char pnstr[], int ddrtype){ + int i = 0, offset, tmp; + if(ddrtype == 0x8) + offset = 73; + if(ddrtype == 0xb) + offset = 128; + for(i = 0; i < 18; i++){ + pnstr[i] = get_spd_byte(slotnum, i + offset); + } + pnstr[i] = '\0'; + if(pnstr[0] == 0) + strcpy(pnstr, "unknown"); + return 0; +} +static void * +smbios_type_17_init(void *start, int slotnum){ + struct smbios_type_17 *p = (struct smbios_type_17 *)start; + int ddrtype = 0; + char dimmstr[10] = {0}; + char manustr[20] = {0}; + char snstr[10] = {0}; + char pnstr[20] = {0}; + + memset(p, 0, sizeof(*p)); + + + p->header.type = 17; + p->header.length = sizeof(struct smbios_type_17); + p->header.handle = smbios_table_handle++; + + p->physical_memory_array_handle = memory_array_handle; + p->memory_error_information_handle = 0xfffe; + + ddrtype = get_spd_byte(slotnum, 2); + if(ddrtype == 0xb){ + p->data_width = (0x1 << ((get_spd_byte(slotnum, 8)) & 0x7)) * 8; + p->total_width = (((get_spd_byte(slotnum, 8)) & 0x18) >> 3) * 8 + p->data_width; + } + else{ + p->total_width = 64; + p->data_width = 64; + } + + if(ddrtype == 0x8) + p->memory_type = 0x13; + if(ddrtype == 0xb) + p->memory_type = 0x18; + + p->speed = get_ddr_speed(slotnum, ddrtype); + p->size = get_ddr_size(slotnum, ddrtype); + p->form_factor = 0x09; /* DIMM */ + p->device_set = 0; + p->device_locator_str = 1; + p->bank_locator_str = 2; + + if(ddrtype == 0x8 || ddrtype == 0xb){ + p->manufacturer = 3; + p->serial_number = 4; + p->part_number = 5; + } + + start += sizeof(struct smbios_type_17); + if(slotnum < 8) + sprintf(dimmstr, "DIMM %d", slotnum); + strcpy(start, dimmstr); + start += strlen(dimmstr) + 1; + + strcpy(start, "BANK 0"); + start += strlen("BANK 0") + 1; + + if(ddrtype == 0x8 || ddrtype == 0xb){ + get_ddr_manustr(slotnum, manustr, ddrtype); + strcpy(start, manustr); + start += strlen(manustr) + 1; + + get_ddr_snstr(slotnum, snstr, ddrtype); + strcpy(start, snstr); + start += strlen(snstr) + 1; + + get_ddr_pnstr(slotnum, pnstr, ddrtype); + strcpy(start, pnstr); + start += strlen(pnstr) + 1; + } + *((uint8_t *)start) = 0; + return start+1; + +} /* Type 28 -- Temperature Probe */ static void * smbios_type_28_init(void *start) { struct smbios_type_28 *p = (struct smbios_type_28 *)start; + memset(p, 0, sizeof(*p)); p->header.type = 28; p->header.length = sizeof(struct smbios_type_28); - p->header.handle = 28; + p->header.handle = smbios_table_handle++; p->description = 1; p->location_status = 0x63; @@ -451,9 +792,10 @@ static void * smbios_type_127_init(void *start) { struct smbios_type_127 *p = (struct smbios_type_127 *)start; + memset(p, 0, sizeof(*p)); p->header.type = 127; p->header.length = sizeof(struct smbios_type_127); - p->header.handle = 127; + p->header.handle = smbios_table_handle++; start += sizeof(struct smbios_type_127); *((uint8_t *)start) = 0; *((uint8_t *)(start + 1)) =0; diff --git a/pmon/common/smbios/smbios_types.h b/pmon/common/smbios/smbios_types.h index 687fbfc1..1c052058 100644 --- a/pmon/common/smbios/smbios_types.h +++ b/pmon/common/smbios/smbios_types.h @@ -169,22 +169,31 @@ struct smbios_type_16 { /* SMBIOS type 17 - Memory Device * Associated with one type 19 - */ +*/ struct smbios_type_17 { - struct smbios_structure_header header; - uint16_t physical_memory_array_handle; - uint16_t memory_error_information_handle; - uint16_t total_width; - uint16_t data_width; - uint16_t size; - uint8_t form_factor; - uint8_t device_set; - uint8_t device_locator_str; - uint8_t bank_locator_str; - uint8_t memory_type; - uint16_t type_detail; + struct smbios_structure_header header; + uint16_t physical_memory_array_handle; + uint16_t memory_error_information_handle; + uint16_t total_width; + uint16_t data_width; + uint16_t size; + uint8_t form_factor; + uint8_t device_set; + uint8_t device_locator_str; + uint8_t bank_locator_str; + uint8_t memory_type; + uint16_t type_detail; + uint16_t speed; + uint8_t manufacturer; + uint8_t serial_number; + uint8_t asset_tag; + uint8_t part_number; + uint8_t attributes; } __attribute__ ((packed)); + + + /* SMBIOS type 19 - Memory Array Mapped Address */ struct smbios_type_19 { struct smbios_structure_header header;