Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org)
0004  *
0005  *  Todo: - add support for the OF persistent properties
0006  */
0007 #include <linux/export.h>
0008 #include <linux/kernel.h>
0009 #include <linux/stddef.h>
0010 #include <linux/string.h>
0011 #include <linux/nvram.h>
0012 #include <linux/init.h>
0013 #include <linux/delay.h>
0014 #include <linux/errno.h>
0015 #include <linux/adb.h>
0016 #include <linux/pmu.h>
0017 #include <linux/memblock.h>
0018 #include <linux/completion.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/of_address.h>
0021 #include <asm/sections.h>
0022 #include <asm/io.h>
0023 #include <asm/machdep.h>
0024 #include <asm/nvram.h>
0025 
0026 #include "pmac.h"
0027 
0028 #define DEBUG
0029 
0030 #ifdef DEBUG
0031 #define DBG(x...) printk(x)
0032 #else
0033 #define DBG(x...)
0034 #endif
0035 
0036 #define NVRAM_SIZE      0x2000  /* 8kB of non-volatile RAM */
0037 
0038 #define CORE99_SIGNATURE    0x5a
0039 #define CORE99_ADLER_START  0x14
0040 
0041 /* On Core99, nvram is either a sharp, a micron or an AMD flash */
0042 #define SM_FLASH_STATUS_DONE    0x80
0043 #define SM_FLASH_STATUS_ERR 0x38
0044 
0045 #define SM_FLASH_CMD_ERASE_CONFIRM  0xd0
0046 #define SM_FLASH_CMD_ERASE_SETUP    0x20
0047 #define SM_FLASH_CMD_RESET      0xff
0048 #define SM_FLASH_CMD_WRITE_SETUP    0x40
0049 #define SM_FLASH_CMD_CLEAR_STATUS   0x50
0050 #define SM_FLASH_CMD_READ_STATUS    0x70
0051 
0052 /* CHRP NVRAM header */
0053 struct chrp_header {
0054   u8        signature;
0055   u8        cksum;
0056   u16       len;
0057   char          name[12];
0058   u8        data[];
0059 };
0060 
0061 struct core99_header {
0062   struct chrp_header    hdr;
0063   u32           adler;
0064   u32           generation;
0065   u32           reserved[2];
0066 };
0067 
0068 /*
0069  * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
0070  */
0071 static int nvram_naddrs;
0072 static volatile unsigned char __iomem *nvram_data;
0073 static int is_core_99;
0074 static int core99_bank;
0075 static int nvram_partitions[3];
0076 // XXX Turn that into a sem
0077 static DEFINE_RAW_SPINLOCK(nv_lock);
0078 
0079 static int (*core99_write_bank)(int bank, u8* datas);
0080 static int (*core99_erase_bank)(int bank);
0081 
0082 static char *nvram_image;
0083 
0084 
0085 static unsigned char core99_nvram_read_byte(int addr)
0086 {
0087     if (nvram_image == NULL)
0088         return 0xff;
0089     return nvram_image[addr];
0090 }
0091 
0092 static void core99_nvram_write_byte(int addr, unsigned char val)
0093 {
0094     if (nvram_image == NULL)
0095         return;
0096     nvram_image[addr] = val;
0097 }
0098 
0099 static ssize_t core99_nvram_read(char *buf, size_t count, loff_t *index)
0100 {
0101     int i;
0102 
0103     if (nvram_image == NULL)
0104         return -ENODEV;
0105     if (*index > NVRAM_SIZE)
0106         return 0;
0107 
0108     i = *index;
0109     if (i + count > NVRAM_SIZE)
0110         count = NVRAM_SIZE - i;
0111 
0112     memcpy(buf, &nvram_image[i], count);
0113     *index = i + count;
0114     return count;
0115 }
0116 
0117 static ssize_t core99_nvram_write(char *buf, size_t count, loff_t *index)
0118 {
0119     int i;
0120 
0121     if (nvram_image == NULL)
0122         return -ENODEV;
0123     if (*index > NVRAM_SIZE)
0124         return 0;
0125 
0126     i = *index;
0127     if (i + count > NVRAM_SIZE)
0128         count = NVRAM_SIZE - i;
0129 
0130     memcpy(&nvram_image[i], buf, count);
0131     *index = i + count;
0132     return count;
0133 }
0134 
0135 static ssize_t core99_nvram_size(void)
0136 {
0137     if (nvram_image == NULL)
0138         return -ENODEV;
0139     return NVRAM_SIZE;
0140 }
0141 
0142 #ifdef CONFIG_PPC32
0143 static volatile unsigned char __iomem *nvram_addr;
0144 static int nvram_mult;
0145 
0146 static ssize_t ppc32_nvram_size(void)
0147 {
0148     return NVRAM_SIZE;
0149 }
0150 
0151 static unsigned char direct_nvram_read_byte(int addr)
0152 {
0153     return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
0154 }
0155 
0156 static void direct_nvram_write_byte(int addr, unsigned char val)
0157 {
0158     out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
0159 }
0160 
0161 
0162 static unsigned char indirect_nvram_read_byte(int addr)
0163 {
0164     unsigned char val;
0165     unsigned long flags;
0166 
0167     raw_spin_lock_irqsave(&nv_lock, flags);
0168     out_8(nvram_addr, addr >> 5);
0169     val = in_8(&nvram_data[(addr & 0x1f) << 4]);
0170     raw_spin_unlock_irqrestore(&nv_lock, flags);
0171 
0172     return val;
0173 }
0174 
0175 static void indirect_nvram_write_byte(int addr, unsigned char val)
0176 {
0177     unsigned long flags;
0178 
0179     raw_spin_lock_irqsave(&nv_lock, flags);
0180     out_8(nvram_addr, addr >> 5);
0181     out_8(&nvram_data[(addr & 0x1f) << 4], val);
0182     raw_spin_unlock_irqrestore(&nv_lock, flags);
0183 }
0184 
0185 
0186 #ifdef CONFIG_ADB_PMU
0187 
0188 static void pmu_nvram_complete(struct adb_request *req)
0189 {
0190     if (req->arg)
0191         complete((struct completion *)req->arg);
0192 }
0193 
0194 static unsigned char pmu_nvram_read_byte(int addr)
0195 {
0196     struct adb_request req;
0197     DECLARE_COMPLETION_ONSTACK(req_complete);
0198     
0199     req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
0200     if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
0201             (addr >> 8) & 0xff, addr & 0xff))
0202         return 0xff;
0203     if (system_state == SYSTEM_RUNNING)
0204         wait_for_completion(&req_complete);
0205     while (!req.complete)
0206         pmu_poll();
0207     return req.reply[0];
0208 }
0209 
0210 static void pmu_nvram_write_byte(int addr, unsigned char val)
0211 {
0212     struct adb_request req;
0213     DECLARE_COMPLETION_ONSTACK(req_complete);
0214     
0215     req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
0216     if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
0217             (addr >> 8) & 0xff, addr & 0xff, val))
0218         return;
0219     if (system_state == SYSTEM_RUNNING)
0220         wait_for_completion(&req_complete);
0221     while (!req.complete)
0222         pmu_poll();
0223 }
0224 
0225 #endif /* CONFIG_ADB_PMU */
0226 #endif /* CONFIG_PPC32 */
0227 
0228 static u8 chrp_checksum(struct chrp_header* hdr)
0229 {
0230     u8 *ptr;
0231     u16 sum = hdr->signature;
0232     for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
0233         sum += *ptr;
0234     while (sum > 0xFF)
0235         sum = (sum & 0xFF) + (sum>>8);
0236     return sum;
0237 }
0238 
0239 static u32 core99_calc_adler(u8 *buffer)
0240 {
0241     int cnt;
0242     u32 low, high;
0243 
0244     buffer += CORE99_ADLER_START;
0245     low = 1;
0246     high = 0;
0247     for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
0248         if ((cnt % 5000) == 0) {
0249             high  %= 65521UL;
0250             high %= 65521UL;
0251         }
0252         low += buffer[cnt];
0253         high += low;
0254     }
0255     low  %= 65521UL;
0256     high %= 65521UL;
0257 
0258     return (high << 16) | low;
0259 }
0260 
0261 static u32 __init core99_check(u8 *datas)
0262 {
0263     struct core99_header* hdr99 = (struct core99_header*)datas;
0264 
0265     if (hdr99->hdr.signature != CORE99_SIGNATURE) {
0266         DBG("Invalid signature\n");
0267         return 0;
0268     }
0269     if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
0270         DBG("Invalid checksum\n");
0271         return 0;
0272     }
0273     if (hdr99->adler != core99_calc_adler(datas)) {
0274         DBG("Invalid adler\n");
0275         return 0;
0276     }
0277     return hdr99->generation;
0278 }
0279 
0280 static int sm_erase_bank(int bank)
0281 {
0282     int stat;
0283     unsigned long timeout;
0284 
0285     u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
0286 
0287         DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
0288 
0289     out_8(base, SM_FLASH_CMD_ERASE_SETUP);
0290     out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
0291     timeout = 0;
0292     do {
0293         if (++timeout > 1000000) {
0294             printk(KERN_ERR "nvram: Sharp/Micron flash erase timeout !\n");
0295             break;
0296         }
0297         out_8(base, SM_FLASH_CMD_READ_STATUS);
0298         stat = in_8(base);
0299     } while (!(stat & SM_FLASH_STATUS_DONE));
0300 
0301     out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
0302     out_8(base, SM_FLASH_CMD_RESET);
0303 
0304     if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
0305         printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
0306         return -ENXIO;
0307     }
0308     return 0;
0309 }
0310 
0311 static int sm_write_bank(int bank, u8* datas)
0312 {
0313     int i, stat = 0;
0314     unsigned long timeout;
0315 
0316     u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
0317 
0318         DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
0319 
0320     for (i=0; i<NVRAM_SIZE; i++) {
0321         out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
0322         udelay(1);
0323         out_8(base+i, datas[i]);
0324         timeout = 0;
0325         do {
0326             if (++timeout > 1000000) {
0327                 printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
0328                 break;
0329             }
0330             out_8(base, SM_FLASH_CMD_READ_STATUS);
0331             stat = in_8(base);
0332         } while (!(stat & SM_FLASH_STATUS_DONE));
0333         if (!(stat & SM_FLASH_STATUS_DONE))
0334             break;
0335     }
0336     out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
0337     out_8(base, SM_FLASH_CMD_RESET);
0338     if (memcmp(base, datas, NVRAM_SIZE)) {
0339         printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
0340         return -ENXIO;
0341     }
0342     return 0;
0343 }
0344 
0345 static int amd_erase_bank(int bank)
0346 {
0347     int stat = 0;
0348     unsigned long timeout;
0349 
0350     u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
0351 
0352         DBG("nvram: AMD Erasing bank %d...\n", bank);
0353 
0354     /* Unlock 1 */
0355     out_8(base+0x555, 0xaa);
0356     udelay(1);
0357     /* Unlock 2 */
0358     out_8(base+0x2aa, 0x55);
0359     udelay(1);
0360 
0361     /* Sector-Erase */
0362     out_8(base+0x555, 0x80);
0363     udelay(1);
0364     out_8(base+0x555, 0xaa);
0365     udelay(1);
0366     out_8(base+0x2aa, 0x55);
0367     udelay(1);
0368     out_8(base, 0x30);
0369     udelay(1);
0370 
0371     timeout = 0;
0372     do {
0373         if (++timeout > 1000000) {
0374             printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
0375             break;
0376         }
0377         stat = in_8(base) ^ in_8(base);
0378     } while (stat != 0);
0379     
0380     /* Reset */
0381     out_8(base, 0xf0);
0382     udelay(1);
0383 
0384     if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
0385         printk(KERN_ERR "nvram: AMD flash erase failed !\n");
0386         return -ENXIO;
0387     }
0388     return 0;
0389 }
0390 
0391 static int amd_write_bank(int bank, u8* datas)
0392 {
0393     int i, stat = 0;
0394     unsigned long timeout;
0395 
0396     u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
0397 
0398         DBG("nvram: AMD Writing bank %d...\n", bank);
0399 
0400     for (i=0; i<NVRAM_SIZE; i++) {
0401         /* Unlock 1 */
0402         out_8(base+0x555, 0xaa);
0403         udelay(1);
0404         /* Unlock 2 */
0405         out_8(base+0x2aa, 0x55);
0406         udelay(1);
0407 
0408         /* Write single word */
0409         out_8(base+0x555, 0xa0);
0410         udelay(1);
0411         out_8(base+i, datas[i]);
0412         
0413         timeout = 0;
0414         do {
0415             if (++timeout > 1000000) {
0416                 printk(KERN_ERR "nvram: AMD flash write timeout !\n");
0417                 break;
0418             }
0419             stat = in_8(base) ^ in_8(base);
0420         } while (stat != 0);
0421         if (stat != 0)
0422             break;
0423     }
0424 
0425     /* Reset */
0426     out_8(base, 0xf0);
0427     udelay(1);
0428 
0429     if (memcmp(base, datas, NVRAM_SIZE)) {
0430         printk(KERN_ERR "nvram: AMD flash write failed !\n");
0431         return -ENXIO;
0432     }
0433     return 0;
0434 }
0435 
0436 static void __init lookup_partitions(void)
0437 {
0438     u8 buffer[17];
0439     int i, offset;
0440     struct chrp_header* hdr;
0441 
0442     if (pmac_newworld) {
0443         nvram_partitions[pmac_nvram_OF] = -1;
0444         nvram_partitions[pmac_nvram_XPRAM] = -1;
0445         nvram_partitions[pmac_nvram_NR] = -1;
0446         hdr = (struct chrp_header *)buffer;
0447 
0448         offset = 0;
0449         buffer[16] = 0;
0450         do {
0451             for (i=0;i<16;i++)
0452                 buffer[i] = ppc_md.nvram_read_val(offset+i);
0453             if (!strcmp(hdr->name, "common"))
0454                 nvram_partitions[pmac_nvram_OF] = offset + 0x10;
0455             if (!strcmp(hdr->name, "APL,MacOS75")) {
0456                 nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
0457                 nvram_partitions[pmac_nvram_NR] = offset + 0x110;
0458             }
0459             offset += (hdr->len * 0x10);
0460         } while(offset < NVRAM_SIZE);
0461     } else {
0462         nvram_partitions[pmac_nvram_OF] = 0x1800;
0463         nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
0464         nvram_partitions[pmac_nvram_NR] = 0x1400;
0465     }
0466     DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
0467     DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
0468     DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
0469 }
0470 
0471 static void core99_nvram_sync(void)
0472 {
0473     struct core99_header* hdr99;
0474     unsigned long flags;
0475 
0476     if (!is_core_99 || !nvram_data || !nvram_image)
0477         return;
0478 
0479     raw_spin_lock_irqsave(&nv_lock, flags);
0480     if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
0481         NVRAM_SIZE))
0482         goto bail;
0483 
0484     DBG("Updating nvram...\n");
0485 
0486     hdr99 = (struct core99_header*)nvram_image;
0487     hdr99->generation++;
0488     hdr99->hdr.signature = CORE99_SIGNATURE;
0489     hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
0490     hdr99->adler = core99_calc_adler(nvram_image);
0491     core99_bank = core99_bank ? 0 : 1;
0492     if (core99_erase_bank)
0493         if (core99_erase_bank(core99_bank)) {
0494             printk("nvram: Error erasing bank %d\n", core99_bank);
0495             goto bail;
0496         }
0497     if (core99_write_bank)
0498         if (core99_write_bank(core99_bank, nvram_image))
0499             printk("nvram: Error writing bank %d\n", core99_bank);
0500  bail:
0501     raw_spin_unlock_irqrestore(&nv_lock, flags);
0502 
0503 #ifdef DEBUG
0504         mdelay(2000);
0505 #endif
0506 }
0507 
0508 static int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
0509 {
0510     int i;
0511     u32 gen_bank0, gen_bank1;
0512 
0513     if (nvram_naddrs < 1) {
0514         printk(KERN_ERR "nvram: no address\n");
0515         return -EINVAL;
0516     }
0517     nvram_image = memblock_alloc(NVRAM_SIZE, SMP_CACHE_BYTES);
0518     if (!nvram_image)
0519         panic("%s: Failed to allocate %u bytes\n", __func__,
0520               NVRAM_SIZE);
0521     nvram_data = ioremap(addr, NVRAM_SIZE*2);
0522     nvram_naddrs = 1; /* Make sure we get the correct case */
0523 
0524     DBG("nvram: Checking bank 0...\n");
0525 
0526     gen_bank0 = core99_check((u8 *)nvram_data);
0527     gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
0528     core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
0529 
0530     DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
0531     DBG("nvram: Active bank is: %d\n", core99_bank);
0532 
0533     for (i=0; i<NVRAM_SIZE; i++)
0534         nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
0535 
0536     ppc_md.nvram_read_val   = core99_nvram_read_byte;
0537     ppc_md.nvram_write_val  = core99_nvram_write_byte;
0538     ppc_md.nvram_read   = core99_nvram_read;
0539     ppc_md.nvram_write  = core99_nvram_write;
0540     ppc_md.nvram_size   = core99_nvram_size;
0541     ppc_md.nvram_sync   = core99_nvram_sync;
0542     ppc_md.machine_shutdown = core99_nvram_sync;
0543     /* 
0544      * Maybe we could be smarter here though making an exclusive list
0545      * of known flash chips is a bit nasty as older OF didn't provide us
0546      * with a useful "compatible" entry. A solution would be to really
0547      * identify the chip using flash id commands and base ourselves on
0548      * a list of known chips IDs
0549      */
0550     if (of_device_is_compatible(dp, "amd-0137")) {
0551         core99_erase_bank = amd_erase_bank;
0552         core99_write_bank = amd_write_bank;
0553     } else {
0554         core99_erase_bank = sm_erase_bank;
0555         core99_write_bank = sm_write_bank;
0556     }
0557     return 0;
0558 }
0559 
0560 int __init pmac_nvram_init(void)
0561 {
0562     struct device_node *dp;
0563     struct resource r1, r2;
0564     unsigned int s1 = 0, s2 = 0;
0565     int err = 0;
0566 
0567     nvram_naddrs = 0;
0568 
0569     dp = of_find_node_by_name(NULL, "nvram");
0570     if (dp == NULL) {
0571         printk(KERN_ERR "Can't find NVRAM device\n");
0572         return -ENODEV;
0573     }
0574 
0575     /* Try to obtain an address */
0576     if (of_address_to_resource(dp, 0, &r1) == 0) {
0577         nvram_naddrs = 1;
0578         s1 = resource_size(&r1);
0579         if (of_address_to_resource(dp, 1, &r2) == 0) {
0580             nvram_naddrs = 2;
0581             s2 = resource_size(&r2);
0582         }
0583     }
0584 
0585     is_core_99 = of_device_is_compatible(dp, "nvram,flash");
0586     if (is_core_99) {
0587         err = core99_nvram_setup(dp, r1.start);
0588         goto bail;
0589     }
0590 
0591 #ifdef CONFIG_PPC32
0592     if (machine_is(chrp) && nvram_naddrs == 1) {
0593         nvram_data = ioremap(r1.start, s1);
0594         nvram_mult = 1;
0595         ppc_md.nvram_read_val   = direct_nvram_read_byte;
0596         ppc_md.nvram_write_val  = direct_nvram_write_byte;
0597         ppc_md.nvram_size   = ppc32_nvram_size;
0598     } else if (nvram_naddrs == 1) {
0599         nvram_data = ioremap(r1.start, s1);
0600         nvram_mult = (s1 + NVRAM_SIZE - 1) / NVRAM_SIZE;
0601         ppc_md.nvram_read_val   = direct_nvram_read_byte;
0602         ppc_md.nvram_write_val  = direct_nvram_write_byte;
0603         ppc_md.nvram_size   = ppc32_nvram_size;
0604     } else if (nvram_naddrs == 2) {
0605         nvram_addr = ioremap(r1.start, s1);
0606         nvram_data = ioremap(r2.start, s2);
0607         ppc_md.nvram_read_val   = indirect_nvram_read_byte;
0608         ppc_md.nvram_write_val  = indirect_nvram_write_byte;
0609         ppc_md.nvram_size   = ppc32_nvram_size;
0610     } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
0611 #ifdef CONFIG_ADB_PMU
0612         nvram_naddrs = -1;
0613         ppc_md.nvram_read_val   = pmu_nvram_read_byte;
0614         ppc_md.nvram_write_val  = pmu_nvram_write_byte;
0615         ppc_md.nvram_size   = ppc32_nvram_size;
0616 #endif /* CONFIG_ADB_PMU */
0617     } else {
0618         printk(KERN_ERR "Incompatible type of NVRAM\n");
0619         err = -ENXIO;
0620     }
0621 #endif /* CONFIG_PPC32 */
0622 bail:
0623     of_node_put(dp);
0624     if (err == 0)
0625         lookup_partitions();
0626     return err;
0627 }
0628 
0629 int pmac_get_partition(int partition)
0630 {
0631     return nvram_partitions[partition];
0632 }
0633 
0634 u8 pmac_xpram_read(int xpaddr)
0635 {
0636     int offset = pmac_get_partition(pmac_nvram_XPRAM);
0637 
0638     if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
0639         return 0xff;
0640 
0641     return ppc_md.nvram_read_val(xpaddr + offset);
0642 }
0643 
0644 void pmac_xpram_write(int xpaddr, u8 data)
0645 {
0646     int offset = pmac_get_partition(pmac_nvram_XPRAM);
0647 
0648     if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
0649         return;
0650 
0651     ppc_md.nvram_write_val(xpaddr + offset, data);
0652 }
0653 
0654 EXPORT_SYMBOL(pmac_get_partition);
0655 EXPORT_SYMBOL(pmac_xpram_read);
0656 EXPORT_SYMBOL(pmac_xpram_write);