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