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