1 /*
2 * Miscellaneous procedures for dealing with the PowerMac hardware.
3 */
4 #include <linux/config.h>
5 #include <linux/module.h>
6 #include <linux/kernel.h>
7 #include <linux/stddef.h>
8 #include <linux/nvram.h>
9 #include <linux/init.h>
10 #include <linux/slab.h>
11 #include <linux/delay.h>
12 #include <asm/sections.h>
13 #include <asm/io.h>
14 #include <asm/system.h>
15 #include <asm/prom.h>
16 #include <asm/machdep.h>
17 #include <asm/nvram.h>
18 #include <linux/adb.h>
19 #include <linux/pmu.h>
20
21 #undef DEBUG
22
23 #define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
24
25 #define CORE99_SIGNATURE 0x5a
26 #define CORE99_ADLER_START 0x14
27
28 /* Core99 nvram is a flash */
29 #define CORE99_FLASH_STATUS_DONE 0x80
30 #define CORE99_FLASH_STATUS_ERR 0x38
31 #define CORE99_FLASH_CMD_ERASE_CONFIRM 0xd0
32 #define CORE99_FLASH_CMD_ERASE_SETUP 0x20
33 #define CORE99_FLASH_CMD_RESET 0xff
34 #define CORE99_FLASH_CMD_WRITE_SETUP 0x40
35
36 /* CHRP NVRAM header */
37 struct chrp_header {
38 u8 signature;
39 u8 cksum;
40 u16 len;
41 char name[12];
42 u8 data[0];
43 };
44
45 struct core99_header {
46 struct chrp_header hdr;
47 u32 adler;
48 u32 generation;
49 u32 reserved[2];
50 };
51
52 /*
53 * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
54 */
55 static int nvram_naddrs;
56 static volatile unsigned char *nvram_addr;
57 static volatile unsigned char *nvram_data;
58 static int nvram_mult, is_core_99;
59 static int core99_bank = 0;
60 static int nvram_partitions[3];
61
62 /* FIXME: kmalloc fails to allocate the image now that I had to move it
63 * before time_init(). For now, I allocate a static buffer here
64 * but it's a waste of space on all but core99 machines
65 */
66 #if 0
67 static char* nvram_image;
68 #else
69 static char nvram_image[NVRAM_SIZE] __pmacdata;
70 #endif
71
72 extern int pmac_newworld;
73
74 static u8 __openfirmware
chrp_checksum(struct chrp_header * hdr)75 chrp_checksum(struct chrp_header* hdr)
76 {
77 u8 *ptr;
78 u16 sum = hdr->signature;
79 for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
80 sum += *ptr;
81 while (sum > 0xFF)
82 sum = (sum & 0xFF) + (sum>>8);
83 return sum;
84 }
85
86 static u32 __pmac
core99_calc_adler(u8 * buffer)87 core99_calc_adler(u8 *buffer)
88 {
89 int cnt;
90 u32 low, high;
91
92 buffer += CORE99_ADLER_START;
93 low = 1;
94 high = 0;
95 for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
96 if ((cnt % 5000) == 0) {
97 high %= 65521UL;
98 high %= 65521UL;
99 }
100 low += buffer[cnt];
101 high += low;
102 }
103 low %= 65521UL;
104 high %= 65521UL;
105
106 return (high << 16) | low;
107 }
108
109 static u32 __pmac
core99_check(u8 * datas)110 core99_check(u8* datas)
111 {
112 struct core99_header* hdr99 = (struct core99_header*)datas;
113
114 if (hdr99->hdr.signature != CORE99_SIGNATURE) {
115 #ifdef DEBUG
116 printk("Invalid signature\n");
117 #endif
118 return 0;
119 }
120 if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
121 #ifdef DEBUG
122 printk("Invalid checksum\n");
123 #endif
124 return 0;
125 }
126 if (hdr99->adler != core99_calc_adler(datas)) {
127 #ifdef DEBUG
128 printk("Invalid adler\n");
129 #endif
130 return 0;
131 }
132 return hdr99->generation;
133 }
134
135 static int __pmac
core99_erase_bank(int bank)136 core99_erase_bank(int bank)
137 {
138 int stat, i;
139
140 u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
141
142 out_8(base, CORE99_FLASH_CMD_ERASE_SETUP);
143 out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM);
144 do { stat = in_8(base); }
145 while(!(stat & CORE99_FLASH_STATUS_DONE));
146 out_8(base, CORE99_FLASH_CMD_RESET);
147 if (stat & CORE99_FLASH_STATUS_ERR) {
148 printk("nvram: flash error 0x%02x on erase !\n", stat);
149 return -ENXIO;
150 }
151 for (i=0; i<NVRAM_SIZE; i++)
152 if (base[i] != 0xff) {
153 printk("nvram: flash erase failed !\n");
154 return -ENXIO;
155 }
156 return 0;
157 }
158
159 static int __pmac
core99_write_bank(int bank,u8 * datas)160 core99_write_bank(int bank, u8* datas)
161 {
162 int i, stat = 0;
163
164 u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
165
166 for (i=0; i<NVRAM_SIZE; i++) {
167 out_8(base+i, CORE99_FLASH_CMD_WRITE_SETUP);
168 out_8(base+i, datas[i]);
169 do { stat = in_8(base); }
170 while(!(stat & CORE99_FLASH_STATUS_DONE));
171 if (stat & CORE99_FLASH_STATUS_ERR)
172 break;
173 }
174 out_8(base, CORE99_FLASH_CMD_RESET);
175 if (stat & CORE99_FLASH_STATUS_ERR) {
176 printk("nvram: flash error 0x%02x on write !\n", stat);
177 return -ENXIO;
178 }
179 for (i=0; i<NVRAM_SIZE; i++)
180 if (base[i] != datas[i]) {
181 printk("nvram: flash write failed !\n");
182 return -ENXIO;
183 }
184 return 0;
185 }
186
187 static void __init
lookup_partitions(void)188 lookup_partitions(void)
189 {
190 u8 buffer[17];
191 int i, offset;
192 struct chrp_header* hdr;
193
194 if (pmac_newworld) {
195 nvram_partitions[pmac_nvram_OF] = -1;
196 nvram_partitions[pmac_nvram_XPRAM] = -1;
197 nvram_partitions[pmac_nvram_NR] = -1;
198 hdr = (struct chrp_header *)buffer;
199
200 offset = 0;
201 buffer[16] = 0;
202 do {
203 for (i=0;i<16;i++)
204 buffer[i] = nvram_read_byte(offset+i);
205 if (!strcmp(hdr->name, "common"))
206 nvram_partitions[pmac_nvram_OF] = offset + 0x10;
207 if (!strcmp(hdr->name, "APL,MacOS75")) {
208 nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
209 nvram_partitions[pmac_nvram_NR] = offset + 0x110;
210 }
211 offset += (hdr->len * 0x10);
212 } while(offset < NVRAM_SIZE);
213 } else {
214 nvram_partitions[pmac_nvram_OF] = 0x1800;
215 nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
216 nvram_partitions[pmac_nvram_NR] = 0x1400;
217 }
218 #ifdef DEBUG
219 printk("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
220 printk("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
221 printk("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
222 #endif
223 }
224
225 void __init
pmac_nvram_init(void)226 pmac_nvram_init(void)
227 {
228 struct device_node *dp;
229
230 nvram_naddrs = 0;
231
232 dp = find_devices("nvram");
233 if (dp == NULL) {
234 printk(KERN_ERR "Can't find NVRAM device\n");
235 return;
236 }
237 nvram_naddrs = dp->n_addrs;
238 is_core_99 = device_is_compatible(dp, "nvram,flash");
239 if (is_core_99) {
240 int i;
241 u32 gen_bank0, gen_bank1;
242
243 if (nvram_naddrs < 1) {
244 printk(KERN_ERR "nvram: no address\n");
245 return;
246 }
247 #if 0
248 nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
249 if (!nvram_image) {
250 printk(KERN_ERR "nvram: can't allocate image\n");
251 return;
252 }
253 #endif
254 nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
255 #ifdef DEBUG
256 printk("nvram: Checking bank 0...\n");
257 #endif
258 gen_bank0 = core99_check((u8 *)nvram_data);
259 gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
260 core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
261 #ifdef DEBUG
262 printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
263 printk("nvram: Active bank is: %d\n", core99_bank);
264 #endif
265 for (i=0; i<NVRAM_SIZE; i++)
266 nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
267 } else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
268 nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
269 dp->addrs[0].size);
270 nvram_mult = 1;
271 } else if (nvram_naddrs == 1) {
272 nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
273 nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
274 } else if (nvram_naddrs == 2) {
275 nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
276 nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
277 } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
278 nvram_naddrs = -1;
279 } else {
280 printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
281 nvram_naddrs);
282 }
283 lookup_partitions();
284 }
285
286 void __pmac
pmac_nvram_update(void)287 pmac_nvram_update(void)
288 {
289 struct core99_header* hdr99;
290
291 if (!is_core_99 || !nvram_data || !nvram_image)
292 return;
293 if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
294 NVRAM_SIZE))
295 return;
296 #ifdef DEBUG
297 printk("Updating nvram...\n");
298 #endif
299 hdr99 = (struct core99_header*)nvram_image;
300 hdr99->generation++;
301 hdr99->hdr.signature = CORE99_SIGNATURE;
302 hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
303 hdr99->adler = core99_calc_adler(nvram_image);
304 core99_bank = core99_bank ? 0 : 1;
305 if (core99_erase_bank(core99_bank)) {
306 printk("nvram: Error erasing bank %d\n", core99_bank);
307 return;
308 }
309 if (core99_write_bank(core99_bank, nvram_image))
310 printk("nvram: Error writing bank %d\n", core99_bank);
311 }
312
313 unsigned char __openfirmware
nvram_read_byte(int addr)314 nvram_read_byte(int addr)
315 {
316 switch (nvram_naddrs) {
317 #ifdef CONFIG_ADB_PMU
318 case -1: {
319 struct adb_request req;
320
321 if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
322 (addr >> 8) & 0xff, addr & 0xff))
323 break;
324 while (!req.complete)
325 pmu_poll();
326 return req.reply[0];
327 }
328 #endif
329 case 1:
330 if (is_core_99)
331 return nvram_image[addr];
332 return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
333 case 2:
334 *nvram_addr = addr >> 5;
335 eieio();
336 return nvram_data[(addr & 0x1f) << 4];
337 }
338 return 0;
339 }
340
341 void __openfirmware
nvram_write_byte(unsigned char val,int addr)342 nvram_write_byte(unsigned char val, int addr)
343 {
344 switch (nvram_naddrs) {
345 #ifdef CONFIG_ADB_PMU
346 case -1: {
347 struct adb_request req;
348
349 if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
350 (addr >> 8) & 0xff, addr & 0xff, val))
351 break;
352 while (!req.complete)
353 pmu_poll();
354 break;
355 }
356 #endif
357 case 1:
358 if (is_core_99) {
359 nvram_image[addr] = val;
360 break;
361 }
362 nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val;
363 break;
364 case 2:
365 *nvram_addr = addr >> 5;
366 eieio();
367 nvram_data[(addr & 0x1f) << 4] = val;
368 break;
369 }
370 eieio();
371 }
372
373 int __pmac
pmac_get_partition(int partition)374 pmac_get_partition(int partition)
375 {
376 return nvram_partitions[partition];
377 }
378
379 u8 __pmac
pmac_xpram_read(int xpaddr)380 pmac_xpram_read(int xpaddr)
381 {
382 int offset = nvram_partitions[pmac_nvram_XPRAM];
383
384 if (offset < 0)
385 return 0;
386
387 return nvram_read_byte(xpaddr + offset);
388 }
389
390 void __pmac
pmac_xpram_write(int xpaddr,u8 data)391 pmac_xpram_write(int xpaddr, u8 data)
392 {
393 int offset = nvram_partitions[pmac_nvram_XPRAM];
394
395 if (offset < 0)
396 return;
397
398 nvram_write_byte(xpaddr + offset, data);
399 }
400