xref: /openbmc/linux/arch/powerpc/platforms/powermac/nvram.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   *  Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)
4   *
5   *  Todo: - add support for the OF persistent properties
6   */
7  #include <linux/export.h>
8  #include <linux/kernel.h>
9  #include <linux/stddef.h>
10  #include <linux/string.h>
11  #include <linux/nvram.h>
12  #include <linux/init.h>
13  #include <linux/delay.h>
14  #include <linux/errno.h>
15  #include <linux/adb.h>
16  #include <linux/pmu.h>
17  #include <linux/memblock.h>
18  #include <linux/completion.h>
19  #include <linux/spinlock.h>
20  #include <linux/of_address.h>
21  #include <asm/sections.h>
22  #include <asm/io.h>
23  #include <asm/machdep.h>
24  #include <asm/nvram.h>
25  
26  #include "pmac.h"
27  
28  #define DEBUG
29  
30  #ifdef DEBUG
31  #define DBG(x...) printk(x)
32  #else
33  #define DBG(x...)
34  #endif
35  
36  #define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
37  
38  #define CORE99_SIGNATURE	0x5a
39  #define CORE99_ADLER_START	0x14
40  
41  /* On Core99, nvram is either a sharp, a micron or an AMD flash */
42  #define SM_FLASH_STATUS_DONE	0x80
43  #define SM_FLASH_STATUS_ERR	0x38
44  
45  #define SM_FLASH_CMD_ERASE_CONFIRM	0xd0
46  #define SM_FLASH_CMD_ERASE_SETUP	0x20
47  #define SM_FLASH_CMD_RESET		0xff
48  #define SM_FLASH_CMD_WRITE_SETUP	0x40
49  #define SM_FLASH_CMD_CLEAR_STATUS	0x50
50  #define SM_FLASH_CMD_READ_STATUS	0x70
51  
52  /* CHRP NVRAM header */
53  struct chrp_header {
54    u8		signature;
55    u8		cksum;
56    u16		len;
57    char          name[12];
58    u8		data[];
59  };
60  
61  struct core99_header {
62    struct chrp_header	hdr;
63    u32			adler;
64    u32			generation;
65    u32			reserved[2];
66  };
67  
68  /*
69   * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
70   */
71  static int nvram_naddrs;
72  static volatile unsigned char __iomem *nvram_data;
73  static int is_core_99;
74  static int core99_bank;
75  static int nvram_partitions[3];
76  // XXX Turn that into a sem
77  static DEFINE_RAW_SPINLOCK(nv_lock);
78  
79  static int (*core99_write_bank)(int bank, u8* datas);
80  static int (*core99_erase_bank)(int bank);
81  
82  static char *nvram_image;
83  
84  
core99_nvram_read_byte(int addr)85  static unsigned char core99_nvram_read_byte(int addr)
86  {
87  	if (nvram_image == NULL)
88  		return 0xff;
89  	return nvram_image[addr];
90  }
91  
core99_nvram_write_byte(int addr,unsigned char val)92  static void core99_nvram_write_byte(int addr, unsigned char val)
93  {
94  	if (nvram_image == NULL)
95  		return;
96  	nvram_image[addr] = val;
97  }
98  
core99_nvram_read(char * buf,size_t count,loff_t * index)99  static ssize_t core99_nvram_read(char *buf, size_t count, loff_t *index)
100  {
101  	int i;
102  
103  	if (nvram_image == NULL)
104  		return -ENODEV;
105  	if (*index > NVRAM_SIZE)
106  		return 0;
107  
108  	i = *index;
109  	if (i + count > NVRAM_SIZE)
110  		count = NVRAM_SIZE - i;
111  
112  	memcpy(buf, &nvram_image[i], count);
113  	*index = i + count;
114  	return count;
115  }
116  
core99_nvram_write(char * buf,size_t count,loff_t * index)117  static ssize_t core99_nvram_write(char *buf, size_t count, loff_t *index)
118  {
119  	int i;
120  
121  	if (nvram_image == NULL)
122  		return -ENODEV;
123  	if (*index > NVRAM_SIZE)
124  		return 0;
125  
126  	i = *index;
127  	if (i + count > NVRAM_SIZE)
128  		count = NVRAM_SIZE - i;
129  
130  	memcpy(&nvram_image[i], buf, count);
131  	*index = i + count;
132  	return count;
133  }
134  
core99_nvram_size(void)135  static ssize_t core99_nvram_size(void)
136  {
137  	if (nvram_image == NULL)
138  		return -ENODEV;
139  	return NVRAM_SIZE;
140  }
141  
142  #ifdef CONFIG_PPC32
143  static volatile unsigned char __iomem *nvram_addr;
144  static int nvram_mult;
145  
ppc32_nvram_size(void)146  static ssize_t ppc32_nvram_size(void)
147  {
148  	return NVRAM_SIZE;
149  }
150  
direct_nvram_read_byte(int addr)151  static unsigned char direct_nvram_read_byte(int addr)
152  {
153  	return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
154  }
155  
direct_nvram_write_byte(int addr,unsigned char val)156  static void direct_nvram_write_byte(int addr, unsigned char val)
157  {
158  	out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
159  }
160  
161  
indirect_nvram_read_byte(int addr)162  static unsigned char indirect_nvram_read_byte(int addr)
163  {
164  	unsigned char val;
165  	unsigned long flags;
166  
167  	raw_spin_lock_irqsave(&nv_lock, flags);
168  	out_8(nvram_addr, addr >> 5);
169  	val = in_8(&nvram_data[(addr & 0x1f) << 4]);
170  	raw_spin_unlock_irqrestore(&nv_lock, flags);
171  
172  	return val;
173  }
174  
indirect_nvram_write_byte(int addr,unsigned char val)175  static void indirect_nvram_write_byte(int addr, unsigned char val)
176  {
177  	unsigned long flags;
178  
179  	raw_spin_lock_irqsave(&nv_lock, flags);
180  	out_8(nvram_addr, addr >> 5);
181  	out_8(&nvram_data[(addr & 0x1f) << 4], val);
182  	raw_spin_unlock_irqrestore(&nv_lock, flags);
183  }
184  
185  
186  #ifdef CONFIG_ADB_PMU
187  
pmu_nvram_complete(struct adb_request * req)188  static void pmu_nvram_complete(struct adb_request *req)
189  {
190  	if (req->arg)
191  		complete((struct completion *)req->arg);
192  }
193  
pmu_nvram_read_byte(int addr)194  static unsigned char pmu_nvram_read_byte(int addr)
195  {
196  	struct adb_request req;
197  	DECLARE_COMPLETION_ONSTACK(req_complete);
198  
199  	req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
200  	if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
201  			(addr >> 8) & 0xff, addr & 0xff))
202  		return 0xff;
203  	if (system_state == SYSTEM_RUNNING)
204  		wait_for_completion(&req_complete);
205  	while (!req.complete)
206  		pmu_poll();
207  	return req.reply[0];
208  }
209  
pmu_nvram_write_byte(int addr,unsigned char val)210  static void pmu_nvram_write_byte(int addr, unsigned char val)
211  {
212  	struct adb_request req;
213  	DECLARE_COMPLETION_ONSTACK(req_complete);
214  
215  	req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
216  	if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
217  			(addr >> 8) & 0xff, addr & 0xff, val))
218  		return;
219  	if (system_state == SYSTEM_RUNNING)
220  		wait_for_completion(&req_complete);
221  	while (!req.complete)
222  		pmu_poll();
223  }
224  
225  #endif /* CONFIG_ADB_PMU */
226  #endif /* CONFIG_PPC32 */
227  
chrp_checksum(struct chrp_header * hdr)228  static u8 chrp_checksum(struct chrp_header* hdr)
229  {
230  	u8 *ptr;
231  	u16 sum = hdr->signature;
232  	for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
233  		sum += *ptr;
234  	while (sum > 0xFF)
235  		sum = (sum & 0xFF) + (sum>>8);
236  	return sum;
237  }
238  
core99_calc_adler(u8 * buffer)239  static u32 core99_calc_adler(u8 *buffer)
240  {
241  	int cnt;
242  	u32 low, high;
243  
244     	buffer += CORE99_ADLER_START;
245  	low = 1;
246  	high = 0;
247  	for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
248  		if ((cnt % 5000) == 0) {
249  			high  %= 65521UL;
250  			high %= 65521UL;
251  		}
252  		low += buffer[cnt];
253  		high += low;
254  	}
255  	low  %= 65521UL;
256  	high %= 65521UL;
257  
258  	return (high << 16) | low;
259  }
260  
core99_check(u8 * datas)261  static u32 __init core99_check(u8 *datas)
262  {
263  	struct core99_header* hdr99 = (struct core99_header*)datas;
264  
265  	if (hdr99->hdr.signature != CORE99_SIGNATURE) {
266  		DBG("Invalid signature\n");
267  		return 0;
268  	}
269  	if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
270  		DBG("Invalid checksum\n");
271  		return 0;
272  	}
273  	if (hdr99->adler != core99_calc_adler(datas)) {
274  		DBG("Invalid adler\n");
275  		return 0;
276  	}
277  	return hdr99->generation;
278  }
279  
sm_erase_bank(int bank)280  static int sm_erase_bank(int bank)
281  {
282  	int stat;
283  	unsigned long timeout;
284  
285  	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
286  
287         	DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
288  
289  	out_8(base, SM_FLASH_CMD_ERASE_SETUP);
290  	out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
291  	timeout = 0;
292  	do {
293  		if (++timeout > 1000000) {
294  			printk(KERN_ERR "nvram: Sharp/Micron flash erase timeout !\n");
295  			break;
296  		}
297  		out_8(base, SM_FLASH_CMD_READ_STATUS);
298  		stat = in_8(base);
299  	} while (!(stat & SM_FLASH_STATUS_DONE));
300  
301  	out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
302  	out_8(base, SM_FLASH_CMD_RESET);
303  
304  	if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
305  		printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
306  		return -ENXIO;
307  	}
308  	return 0;
309  }
310  
sm_write_bank(int bank,u8 * datas)311  static int sm_write_bank(int bank, u8* datas)
312  {
313  	int i, stat = 0;
314  	unsigned long timeout;
315  
316  	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
317  
318         	DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
319  
320  	for (i=0; i<NVRAM_SIZE; i++) {
321  		out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
322  		udelay(1);
323  		out_8(base+i, datas[i]);
324  		timeout = 0;
325  		do {
326  			if (++timeout > 1000000) {
327  				printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
328  				break;
329  			}
330  			out_8(base, SM_FLASH_CMD_READ_STATUS);
331  			stat = in_8(base);
332  		} while (!(stat & SM_FLASH_STATUS_DONE));
333  		if (!(stat & SM_FLASH_STATUS_DONE))
334  			break;
335  	}
336  	out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
337  	out_8(base, SM_FLASH_CMD_RESET);
338  	if (memcmp(base, datas, NVRAM_SIZE)) {
339  		printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
340  		return -ENXIO;
341  	}
342  	return 0;
343  }
344  
amd_erase_bank(int bank)345  static int amd_erase_bank(int bank)
346  {
347  	int stat = 0;
348  	unsigned long timeout;
349  
350  	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
351  
352         	DBG("nvram: AMD Erasing bank %d...\n", bank);
353  
354  	/* Unlock 1 */
355  	out_8(base+0x555, 0xaa);
356  	udelay(1);
357  	/* Unlock 2 */
358  	out_8(base+0x2aa, 0x55);
359  	udelay(1);
360  
361  	/* Sector-Erase */
362  	out_8(base+0x555, 0x80);
363  	udelay(1);
364  	out_8(base+0x555, 0xaa);
365  	udelay(1);
366  	out_8(base+0x2aa, 0x55);
367  	udelay(1);
368  	out_8(base, 0x30);
369  	udelay(1);
370  
371  	timeout = 0;
372  	do {
373  		if (++timeout > 1000000) {
374  			printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
375  			break;
376  		}
377  		stat = in_8(base) ^ in_8(base);
378  	} while (stat != 0);
379  
380  	/* Reset */
381  	out_8(base, 0xf0);
382  	udelay(1);
383  
384  	if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
385  		printk(KERN_ERR "nvram: AMD flash erase failed !\n");
386  		return -ENXIO;
387  	}
388  	return 0;
389  }
390  
amd_write_bank(int bank,u8 * datas)391  static int amd_write_bank(int bank, u8* datas)
392  {
393  	int i, stat = 0;
394  	unsigned long timeout;
395  
396  	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
397  
398         	DBG("nvram: AMD Writing bank %d...\n", bank);
399  
400  	for (i=0; i<NVRAM_SIZE; i++) {
401  		/* Unlock 1 */
402  		out_8(base+0x555, 0xaa);
403  		udelay(1);
404  		/* Unlock 2 */
405  		out_8(base+0x2aa, 0x55);
406  		udelay(1);
407  
408  		/* Write single word */
409  		out_8(base+0x555, 0xa0);
410  		udelay(1);
411  		out_8(base+i, datas[i]);
412  
413  		timeout = 0;
414  		do {
415  			if (++timeout > 1000000) {
416  				printk(KERN_ERR "nvram: AMD flash write timeout !\n");
417  				break;
418  			}
419  			stat = in_8(base) ^ in_8(base);
420  		} while (stat != 0);
421  		if (stat != 0)
422  			break;
423  	}
424  
425  	/* Reset */
426  	out_8(base, 0xf0);
427  	udelay(1);
428  
429  	if (memcmp(base, datas, NVRAM_SIZE)) {
430  		printk(KERN_ERR "nvram: AMD flash write failed !\n");
431  		return -ENXIO;
432  	}
433  	return 0;
434  }
435  
lookup_partitions(void)436  static void __init lookup_partitions(void)
437  {
438  	u8 buffer[17];
439  	int i, offset;
440  	struct chrp_header* hdr;
441  
442  	if (pmac_newworld) {
443  		nvram_partitions[pmac_nvram_OF] = -1;
444  		nvram_partitions[pmac_nvram_XPRAM] = -1;
445  		nvram_partitions[pmac_nvram_NR] = -1;
446  		hdr = (struct chrp_header *)buffer;
447  
448  		offset = 0;
449  		buffer[16] = 0;
450  		do {
451  			for (i=0;i<16;i++)
452  				buffer[i] = ppc_md.nvram_read_val(offset+i);
453  			if (!strcmp(hdr->name, "common"))
454  				nvram_partitions[pmac_nvram_OF] = offset + 0x10;
455  			if (!strcmp(hdr->name, "APL,MacOS75")) {
456  				nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
457  				nvram_partitions[pmac_nvram_NR] = offset + 0x110;
458  			}
459  			offset += (hdr->len * 0x10);
460  		} while(offset < NVRAM_SIZE);
461  	} else {
462  		nvram_partitions[pmac_nvram_OF] = 0x1800;
463  		nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
464  		nvram_partitions[pmac_nvram_NR] = 0x1400;
465  	}
466  	DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
467  	DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
468  	DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
469  }
470  
core99_nvram_sync(void)471  static void core99_nvram_sync(void)
472  {
473  	struct core99_header* hdr99;
474  	unsigned long flags;
475  
476  	if (!is_core_99 || !nvram_data || !nvram_image)
477  		return;
478  
479  	raw_spin_lock_irqsave(&nv_lock, flags);
480  	if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
481  		NVRAM_SIZE))
482  		goto bail;
483  
484  	DBG("Updating nvram...\n");
485  
486  	hdr99 = (struct core99_header*)nvram_image;
487  	hdr99->generation++;
488  	hdr99->hdr.signature = CORE99_SIGNATURE;
489  	hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
490  	hdr99->adler = core99_calc_adler(nvram_image);
491  	core99_bank = core99_bank ? 0 : 1;
492  	if (core99_erase_bank)
493  		if (core99_erase_bank(core99_bank)) {
494  			printk("nvram: Error erasing bank %d\n", core99_bank);
495  			goto bail;
496  		}
497  	if (core99_write_bank)
498  		if (core99_write_bank(core99_bank, nvram_image))
499  			printk("nvram: Error writing bank %d\n", core99_bank);
500   bail:
501  	raw_spin_unlock_irqrestore(&nv_lock, flags);
502  
503  #ifdef DEBUG
504         	mdelay(2000);
505  #endif
506  }
507  
core99_nvram_setup(struct device_node * dp,unsigned long addr)508  static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
509  {
510  	int i;
511  	u32 gen_bank0, gen_bank1;
512  
513  	if (nvram_naddrs < 1) {
514  		printk(KERN_ERR "nvram: no address\n");
515  		return -EINVAL;
516  	}
517  	nvram_image = memblock_alloc(NVRAM_SIZE, SMP_CACHE_BYTES);
518  	if (!nvram_image)
519  		panic("%s: Failed to allocate %u bytes\n", __func__,
520  		      NVRAM_SIZE);
521  	nvram_data = ioremap(addr, NVRAM_SIZE*2);
522  	nvram_naddrs = 1; /* Make sure we get the correct case */
523  
524  	DBG("nvram: Checking bank 0...\n");
525  
526  	gen_bank0 = core99_check((u8 *)nvram_data);
527  	gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
528  	core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
529  
530  	DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
531  	DBG("nvram: Active bank is: %d\n", core99_bank);
532  
533  	for (i=0; i<NVRAM_SIZE; i++)
534  		nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
535  
536  	ppc_md.nvram_read_val	= core99_nvram_read_byte;
537  	ppc_md.nvram_write_val	= core99_nvram_write_byte;
538  	ppc_md.nvram_read	= core99_nvram_read;
539  	ppc_md.nvram_write	= core99_nvram_write;
540  	ppc_md.nvram_size	= core99_nvram_size;
541  	ppc_md.nvram_sync	= core99_nvram_sync;
542  	ppc_md.machine_shutdown	= core99_nvram_sync;
543  	/*
544  	 * Maybe we could be smarter here though making an exclusive list
545  	 * of known flash chips is a bit nasty as older OF didn't provide us
546  	 * with a useful "compatible" entry. A solution would be to really
547  	 * identify the chip using flash id commands and base ourselves on
548  	 * a list of known chips IDs
549  	 */
550  	if (of_device_is_compatible(dp, "amd-0137")) {
551  		core99_erase_bank = amd_erase_bank;
552  		core99_write_bank = amd_write_bank;
553  	} else {
554  		core99_erase_bank = sm_erase_bank;
555  		core99_write_bank = sm_write_bank;
556  	}
557  	return 0;
558  }
559  
pmac_nvram_init(void)560  int __init pmac_nvram_init(void)
561  {
562  	struct device_node *dp;
563  	struct resource r1, r2;
564  	unsigned int s1 = 0, s2 = 0;
565  	int err = 0;
566  
567  	nvram_naddrs = 0;
568  
569  	dp = of_find_node_by_name(NULL, "nvram");
570  	if (dp == NULL) {
571  		printk(KERN_ERR "Can't find NVRAM device\n");
572  		return -ENODEV;
573  	}
574  
575  	/* Try to obtain an address */
576  	if (of_address_to_resource(dp, 0, &r1) == 0) {
577  		nvram_naddrs = 1;
578  		s1 = resource_size(&r1);
579  		if (of_address_to_resource(dp, 1, &r2) == 0) {
580  			nvram_naddrs = 2;
581  			s2 = resource_size(&r2);
582  		}
583  	}
584  
585  	is_core_99 = of_device_is_compatible(dp, "nvram,flash");
586  	if (is_core_99) {
587  		err = core99_nvram_setup(dp, r1.start);
588  		goto bail;
589  	}
590  
591  #ifdef CONFIG_PPC32
592  	if (machine_is(chrp) && nvram_naddrs == 1) {
593  		nvram_data = ioremap(r1.start, s1);
594  		nvram_mult = 1;
595  		ppc_md.nvram_read_val	= direct_nvram_read_byte;
596  		ppc_md.nvram_write_val	= direct_nvram_write_byte;
597  		ppc_md.nvram_size	= ppc32_nvram_size;
598  	} else if (nvram_naddrs == 1) {
599  		nvram_data = ioremap(r1.start, s1);
600  		nvram_mult = (s1 + NVRAM_SIZE - 1) / NVRAM_SIZE;
601  		ppc_md.nvram_read_val	= direct_nvram_read_byte;
602  		ppc_md.nvram_write_val	= direct_nvram_write_byte;
603  		ppc_md.nvram_size	= ppc32_nvram_size;
604  	} else if (nvram_naddrs == 2) {
605  		nvram_addr = ioremap(r1.start, s1);
606  		nvram_data = ioremap(r2.start, s2);
607  		ppc_md.nvram_read_val	= indirect_nvram_read_byte;
608  		ppc_md.nvram_write_val	= indirect_nvram_write_byte;
609  		ppc_md.nvram_size	= ppc32_nvram_size;
610  	} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
611  #ifdef CONFIG_ADB_PMU
612  		nvram_naddrs = -1;
613  		ppc_md.nvram_read_val	= pmu_nvram_read_byte;
614  		ppc_md.nvram_write_val	= pmu_nvram_write_byte;
615  		ppc_md.nvram_size	= ppc32_nvram_size;
616  #endif /* CONFIG_ADB_PMU */
617  	} else {
618  		printk(KERN_ERR "Incompatible type of NVRAM\n");
619  		err = -ENXIO;
620  	}
621  #endif /* CONFIG_PPC32 */
622  bail:
623  	of_node_put(dp);
624  	if (err == 0)
625  		lookup_partitions();
626  	return err;
627  }
628  
pmac_get_partition(int partition)629  int pmac_get_partition(int partition)
630  {
631  	return nvram_partitions[partition];
632  }
633  
pmac_xpram_read(int xpaddr)634  u8 pmac_xpram_read(int xpaddr)
635  {
636  	int offset = pmac_get_partition(pmac_nvram_XPRAM);
637  
638  	if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
639  		return 0xff;
640  
641  	return ppc_md.nvram_read_val(xpaddr + offset);
642  }
643  
pmac_xpram_write(int xpaddr,u8 data)644  void pmac_xpram_write(int xpaddr, u8 data)
645  {
646  	int offset = pmac_get_partition(pmac_nvram_XPRAM);
647  
648  	if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
649  		return;
650  
651  	ppc_md.nvram_write_val(xpaddr + offset, data);
652  }
653  
654  EXPORT_SYMBOL(pmac_get_partition);
655  EXPORT_SYMBOL(pmac_xpram_read);
656  EXPORT_SYMBOL(pmac_xpram_write);
657