1 | /*␊ |
2 | *␊ |
3 | *␊ |
4 | */␊ |
5 | ␊ |
6 | #include "libsaio.h"␊ |
7 | #include "pci.h"␊ |
8 | #include "platform.h"␊ |
9 | #include "spd.h"␊ |
10 | ␊ |
11 | #ifndef DEBUG_SPD␊ |
12 | #define DEBUG_SPD 0␊ |
13 | #endif␊ |
14 | ␊ |
15 | #if DEBUG_SPD␊ |
16 | #define DBG(x...)␉printf(x)␊ |
17 | #else␊ |
18 | #define DBG(x...)␊ |
19 | #endif␊ |
20 | ␊ |
21 | static const char *spd_memory_types[] =␊ |
22 | {␊ |
23 | ␉"RAM", /* 00h Undefined */␊ |
24 | ␉"FPM", /* 01h FPM */␊ |
25 | ␉"EDO", /* 02h EDO */␊ |
26 | ␉"",␉␉␉␉/* 03h PIPELINE NIBBLE */␊ |
27 | ␉"SDRAM", /* 04h SDRAM */␊ |
28 | ␉"",␉␉␉␉/* 05h MULTIPLEXED ROM */␊ |
29 | ␉"DDR SGRAM",␉/* 06h SGRAM DDR */␊ |
30 | ␉"DDR SDRAM",␉/* 07h SDRAM DDR */␊ |
31 | ␉"DDR2 SDRAM", /* 08h SDRAM DDR 2 */␊ |
32 | ␉"",␉␉␉␉/* 09h Undefined */␊ |
33 | ␉"",␉␉␉␉/* 0Ah Undefined */␊ |
34 | ␉"DDR3 SDRAM", /* 0Bh SDRAM DDR 3 */␊ |
35 | };␊ |
36 | ␊ |
37 | #define rdtsc(low,high) \␊ |
38 | __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))␊ |
39 | ␊ |
40 | #define SMBHSTSTS 0␊ |
41 | #define SMBHSTCNT 2␊ |
42 | #define SMBHSTCMD 3␊ |
43 | #define SMBHSTADD 4␊ |
44 | #define SMBHSTDAT 5␊ |
45 | ␊ |
46 | unsigned char smb_read_byte_intel(uint32_t base, uint8_t adr, uint8_t cmd)␊ |
47 | {␊ |
48 | ␉int l1, h1, l2, h2;␊ |
49 | unsigned long long t;␊ |
50 | ␉␊ |
51 | outb(base + SMBHSTSTS, 0x1f);␉␉␉␉␉// reset SMBus Controller␊ |
52 | outb(base + SMBHSTDAT, 0xff);␊ |
53 | ␉␊ |
54 | while( inb(base + SMBHSTSTS) & 0x01);␉␉␉// wait until ready␊ |
55 | ␉␊ |
56 | outb(base + SMBHSTCMD, cmd);␊ |
57 | outb(base + SMBHSTADD, (adr << 1) | 0x01 );␊ |
58 | outb(base + SMBHSTCNT, 0x48 );␊ |
59 | ␉␊ |
60 | rdtsc(l1, h1);␊ |
61 | ␉␊ |
62 | ␉while (!( inb(base + SMBHSTSTS) & 0x02))␉␉// wait til command finished␊ |
63 | ␉{␉␊ |
64 | ␉␉rdtsc(l2, h2);␊ |
65 | ␉␉t = ((h2 - h1) * 0xffffffff + (l2 - l1)) / (Platform.CPU.TSCFrequency / 40);␊ |
66 | ␉␉if (t > 10)␊ |
67 | ␉␉␉break;␉␉␉␉␉␉␉␉␉// break after 10ms␊ |
68 | }␊ |
69 | return inb(base + SMBHSTDAT);␊ |
70 | }␊ |
71 | ␊ |
72 | static void read_smb_intel(pci_dt_t *smbus_dev)␊ |
73 | {␊ |
74 | ␉int i, x;␊ |
75 | ␊ |
76 | ␉uint8_t␉␉spd_size;␊ |
77 | ␉uint32_t␉base;␊ |
78 | ␉␊ |
79 | ␉RamSlotInfo_t␉*slot;␊ |
80 | ␉␊ |
81 | ␉base = pci_config_read16(smbus_dev->dev.addr, 0x20) & 0xFFFE;␊ |
82 | ␉␊ |
83 | ␉// Search MAX_RAM_SLOTS slots␊ |
84 | ␉for (i = 0; i < 6; i++)␊ |
85 | ␉{␊ |
86 | ␉␉slot = &Platform.RAM.DIMM[i];␊ |
87 | ␊ |
88 | ␉␉spd_size = smb_read_byte_intel(base, 0x50 + i, 0);␊ |
89 | ␊ |
90 | ␉␉// Check spd is present␊ |
91 | ␉␉if (spd_size != 0xff)␊ |
92 | ␉␉{␊ |
93 | ␉␉␉slot->InUse = YES;␊ |
94 | ␊ |
95 | ␉␉␉slot->spd = malloc(spd_size);␊ |
96 | ␉␉␉if (slot->spd)␊ |
97 | ␉␉␉{␊ |
98 | ␉␉␉␉bzero(slot->spd, spd_size);␊ |
99 | ␉␉␉␉␊ |
100 | ␉␉␉␉// Copy spd data into buffer␊ |
101 | ␉␉␉␉for (x = 0; x < spd_size; x++)␊ |
102 | ␉␉␉␉␉slot->spd[x] = smb_read_byte_intel(base, 0x50 + i, x);␊ |
103 | ␉␉␉␊ |
104 | ␉␉␉␉switch (slot->spd[SPD_MEMORY_TYPE])␊ |
105 | ␉␉␉␉{␊ |
106 | ␉␉␉␉␉case SPD_MEMORY_TYPE_SDRAM_DDR2:␊ |
107 | ␊ |
108 | ␉␉␉␉␉␉slot->ModuleSize = ((1 << (slot->spd[SPD_NUM_ROWS] & 0x0f) + (slot->spd[SPD_NUM_COLUMNS] & 0x0f) - 17) * ␊ |
109 | ␉␉␉␉␉␉␉␉((slot->spd[SPD_NUM_DIMM_BANKS] & 0x7) + 1) * slot->spd[SPD_NUM_BANKS_PER_SDRAM]);␊ |
110 | ␉␉␉␉␉␉break;␊ |
111 | ␉␉␉␊ |
112 | ␉␉␉␉␉case SPD_MEMORY_TYPE_SDRAM_DDR3:␊ |
113 | ␉␉␉␉␉␉␊ |
114 | ␉␉␉␉␉␉slot->ModuleSize = ((slot->spd[4] & 0x0f) + 28 ) + ((slot->spd[8] & 0x7) + 3 );␊ |
115 | ␉␉␉␉␉␉slot->ModuleSize -= (slot->spd[7] & 0x7) + 25;␊ |
116 | ␉␉␉␉␉␉slot->ModuleSize = ((1 << slot->ModuleSize) * (((slot->spd[7] >> 3) & 0x1f) + 1));␊ |
117 | ␉␉␉␉␉␉␊ |
118 | ␉␉␉␉␉␉break;␊ |
119 | ␉␉␉␉}␊ |
120 | ␉␉␉}␊ |
121 | ␊ |
122 | ␉␉␉verbose(" slot %d - %dMB %s SPD %d bytes at %x\n", i, slot->ModuleSize, ␊ |
123 | ␉␉␉␉␉spd_memory_types[(uint8_t)slot->spd[SPD_MEMORY_TYPE]],␊ |
124 | ␉␉␉␉␉spd_size, slot->spd);␊ |
125 | ␉␉}␊ |
126 | ␉}␊ |
127 | ␉␉␊ |
128 | }␊ |
129 | ␊ |
130 | static struct smbus_controllers_t smbus_controllers[] = {␊ |
131 | ␊ |
132 | ␉{0x8086, 0x5032, "EP80579", read_smb_intel },␊ |
133 | ␉{0x8086, 0x269B, "ESB2", read_smb_intel },␊ |
134 | ␉{0x8086, 0x25A4, "6300ESB", read_smb_intel },␊ |
135 | ␉{0x8086, 0x24C3, "ICH4", read_smb_intel },␊ |
136 | ␉{0x8086, 0x24D3, "ICH5", read_smb_intel },␊ |
137 | ␉{0x8086, 0x266A, "ICH6", read_smb_intel },␊ |
138 | ␉{0x8086, 0x27DA, "ICH7", read_smb_intel },␊ |
139 | ␉{0x8086, 0x283E, "ICH8", read_smb_intel },␊ |
140 | ␉{0x8086, 0x2930, "ICH9", read_smb_intel },␉␊ |
141 | ␉{0x8086, 0x3A30, "ICH10R", read_smb_intel },␊ |
142 | ␉{0x8086, 0x3A60, "ICH10B", read_smb_intel },␊ |
143 | ␉{0x8086, 0x3B30, "P55", read_smb_intel },␊ |
144 | ␊ |
145 | };␊ |
146 | ␊ |
147 | void scan_smbus_controller(pci_dt_t *smbus_dev)␊ |
148 | {␊ |
149 | ␉int␉i;␊ |
150 | ␊ |
151 | ␉for( i = 1; i < sizeof(smbus_controllers) / sizeof(smbus_controllers[0]); i++ )␊ |
152 | ␉␉if (( smbus_controllers[i].vendor == smbus_dev->vendor_id) ␊ |
153 | ␉␉␉&& ( smbus_controllers[i].device == smbus_dev->device_id))␊ |
154 | ␉␉{␊ |
155 | ␉␉␉verbose("%s%s SMBus Controller [%4x:%4x] at %02x:%02x.%x\n", ␊ |
156 | ␉␉␉␉ (smbus_dev->vendor_id == 0x8086) ? "Intel(R) " : "",␊ |
157 | ␉␉␉␉ smbus_controllers[i].name,␊ |
158 | ␉␉␉␉ smbus_dev->vendor_id, smbus_dev->device_id,␊ |
159 | ␉␉␉␉ smbus_dev->dev.bits.bus, smbus_dev->dev.bits.dev, smbus_dev->dev.bits.func);␊ |
160 | ␉␉␉␊ |
161 | ␉␉␉smbus_controllers[i].read_smb(smbus_dev);␊ |
162 | ␉␉␉␊ |
163 | ␉␉}␊ |
164 | ␉␊ |
165 | }␊ |
166 | ␊ |
167 | |