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;