nvram.c revision 0ebfff1491ef85d41ddf9c633834838be144f69f
114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/* 214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) 314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * 414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * This program is free software; you can redistribute it and/or 514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * modify it under the terms of the GNU General Public License 614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * as published by the Free Software Foundation; either version 714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * 2 of the License, or (at your option) any later version. 814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * 914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * Todo: - add support for the OF persistent properties 1014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras */ 1114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/module.h> 1214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/kernel.h> 1314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/stddef.h> 1414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/string.h> 1514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/nvram.h> 1614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/init.h> 1714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/slab.h> 1814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/delay.h> 1914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/errno.h> 2014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/adb.h> 2114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/pmu.h> 2214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/bootmem.h> 2314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/completion.h> 2414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/spinlock.h> 2514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/sections.h> 2614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/io.h> 2714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/system.h> 2814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/prom.h> 2914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/machdep.h> 3014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/nvram.h> 3114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 320ebfff1491ef85d41ddf9c633834838be144f69fBenjamin Herrenschmidt#include "pmac.h" 330ebfff1491ef85d41ddf9c633834838be144f69fBenjamin Herrenschmidt 3414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define DEBUG 3514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 3614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef DEBUG 3714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define DBG(x...) printk(x) 3814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#else 3914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define DBG(x...) 4014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif 4114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 4214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ 4314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 4414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define CORE99_SIGNATURE 0x5a 4514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define CORE99_ADLER_START 0x14 4614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 4714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/* On Core99, nvram is either a sharp, a micron or an AMD flash */ 4814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_STATUS_DONE 0x80 4935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#define SM_FLASH_STATUS_ERR 0x38 5035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 5114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 5214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_ERASE_SETUP 0x20 5314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_RESET 0xff 5414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_WRITE_SETUP 0x40 5514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_CLEAR_STATUS 0x50 5614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_READ_STATUS 0x70 5714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 5814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/* CHRP NVRAM header */ 5914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstruct chrp_header { 6014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u8 signature; 6114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u8 cksum; 6214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u16 len; 6314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras char name[12]; 6414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u8 data[0]; 6514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}; 6614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 6714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstruct core99_header { 6814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras struct chrp_header hdr; 6914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u32 adler; 7014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u32 generation; 7114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u32 reserved[2]; 7214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}; 7314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 7414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/* 7514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * Read and write the non-volatile RAM on PowerMacs and CHRP machines. 7614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras */ 7714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int nvram_naddrs; 78af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwellstatic volatile unsigned char __iomem *nvram_data; 7935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic int is_core_99; 8014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int core99_bank = 0; 8114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int nvram_partitions[3]; 8235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras// XXX Turn that into a sem 8314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic DEFINE_SPINLOCK(nv_lock); 8414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 8514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int (*core99_write_bank)(int bank, u8* datas); 8614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int (*core99_erase_bank)(int bank); 8714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 8814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic char *nvram_image; 8914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 9014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 9114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char core99_nvram_read_byte(int addr) 9214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 9314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (nvram_image == NULL) 9414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0xff; 9514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return nvram_image[addr]; 9614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 9714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 9814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void core99_nvram_write_byte(int addr, unsigned char val) 9914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 10014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (nvram_image == NULL) 10114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return; 10214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_image[addr] = val; 10314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 10414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 10535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic ssize_t core99_nvram_read(char *buf, size_t count, loff_t *index) 10635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{ 10735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras int i; 10835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 10935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (nvram_image == NULL) 11035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return -ENODEV; 11135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (*index > NVRAM_SIZE) 11235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return 0; 11335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 11435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras i = *index; 11535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (i + count > NVRAM_SIZE) 11635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras count = NVRAM_SIZE - i; 11735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 11835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras memcpy(buf, &nvram_image[i], count); 11935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras *index = i + count; 12035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return count; 12135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras} 12235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 12335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic ssize_t core99_nvram_write(char *buf, size_t count, loff_t *index) 12435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{ 12535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras int i; 12635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 12735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (nvram_image == NULL) 12835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return -ENODEV; 12935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (*index > NVRAM_SIZE) 13035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return 0; 13135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 13235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras i = *index; 13335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (i + count > NVRAM_SIZE) 13435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras count = NVRAM_SIZE - i; 13535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 13635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras memcpy(&nvram_image[i], buf, count); 13735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras *index = i + count; 13835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return count; 13935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras} 14035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 14135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic ssize_t core99_nvram_size(void) 14235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{ 14335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (nvram_image == NULL) 14435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return -ENODEV; 14535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return NVRAM_SIZE; 14635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras} 14735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 14835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#ifdef CONFIG_PPC32 149af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwellstatic volatile unsigned char __iomem *nvram_addr; 15035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic int nvram_mult; 15114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 15214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char direct_nvram_read_byte(int addr) 15314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 15414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]); 15514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 15614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 15714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void direct_nvram_write_byte(int addr, unsigned char val) 15814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 15914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val); 16014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 16114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 16214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 16314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char indirect_nvram_read_byte(int addr) 16414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 16514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned char val; 16614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned long flags; 16714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 16814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras spin_lock_irqsave(&nv_lock, flags); 16914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(nvram_addr, addr >> 5); 17014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras val = in_8(&nvram_data[(addr & 0x1f) << 4]); 17114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras spin_unlock_irqrestore(&nv_lock, flags); 17214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 17314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return val; 17414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 17514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 17614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void indirect_nvram_write_byte(int addr, unsigned char val) 17714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 17814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned long flags; 17914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 18014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras spin_lock_irqsave(&nv_lock, flags); 18114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(nvram_addr, addr >> 5); 18214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(&nvram_data[(addr & 0x1f) << 4], val); 18314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras spin_unlock_irqrestore(&nv_lock, flags); 18414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 18514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 18614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 18714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef CONFIG_ADB_PMU 18814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 18914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void pmu_nvram_complete(struct adb_request *req) 19014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 19114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (req->arg) 19214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras complete((struct completion *)req->arg); 19314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 19414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 19514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char pmu_nvram_read_byte(int addr) 19614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 19714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras struct adb_request req; 19814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DECLARE_COMPLETION(req_complete); 19914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 20014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; 20114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM, 20214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras (addr >> 8) & 0xff, addr & 0xff)) 20314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0xff; 20414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (system_state == SYSTEM_RUNNING) 20514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras wait_for_completion(&req_complete); 20614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras while (!req.complete) 20714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras pmu_poll(); 20814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return req.reply[0]; 20914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 21014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 21114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void pmu_nvram_write_byte(int addr, unsigned char val) 21214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 21314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras struct adb_request req; 21414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DECLARE_COMPLETION(req_complete); 21514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 21614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; 21714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM, 21814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras (addr >> 8) & 0xff, addr & 0xff, val)) 21914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return; 22014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (system_state == SYSTEM_RUNNING) 22114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras wait_for_completion(&req_complete); 22214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras while (!req.complete) 22314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras pmu_poll(); 22414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 22514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 22614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif /* CONFIG_ADB_PMU */ 22735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#endif /* CONFIG_PPC32 */ 22814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 22914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic u8 chrp_checksum(struct chrp_header* hdr) 23014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 23114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u8 *ptr; 23214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u16 sum = hdr->signature; 23314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++) 23414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras sum += *ptr; 23514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras while (sum > 0xFF) 23614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras sum = (sum & 0xFF) + (sum>>8); 23714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return sum; 23814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 23914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 24014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic u32 core99_calc_adler(u8 *buffer) 24114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 24214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras int cnt; 24314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u32 low, high; 24414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 24514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras buffer += CORE99_ADLER_START; 24614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras low = 1; 24714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras high = 0; 24814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { 24914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if ((cnt % 5000) == 0) { 25014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras high %= 65521UL; 25114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras high %= 65521UL; 25214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 25314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras low += buffer[cnt]; 25414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras high += low; 25514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 25614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras low %= 65521UL; 25714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras high %= 65521UL; 25814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 25914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return (high << 16) | low; 26014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 26114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 26214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic u32 core99_check(u8* datas) 26314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 26414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras struct core99_header* hdr99 = (struct core99_header*)datas; 26514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 26614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (hdr99->hdr.signature != CORE99_SIGNATURE) { 26714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("Invalid signature\n"); 26814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0; 26914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 27014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { 27114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("Invalid checksum\n"); 27214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0; 27314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 27414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (hdr99->adler != core99_calc_adler(datas)) { 27514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("Invalid adler\n"); 27614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0; 27714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 27814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return hdr99->generation; 27914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 28014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 28114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int sm_erase_bank(int bank) 28214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 28314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras int stat, i; 28414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned long timeout; 28514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 286af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; 28714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 28814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); 28914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 29014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_ERASE_SETUP); 29114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); 29214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras timeout = 0; 29314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras do { 29414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (++timeout > 1000000) { 29535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras printk(KERN_ERR "nvram: Sharp/Micron flash erase timeout !\n"); 29614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras break; 29714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 29814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_READ_STATUS); 29914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras stat = in_8(base); 30014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } while (!(stat & SM_FLASH_STATUS_DONE)); 30114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 30214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_CLEAR_STATUS); 30314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_RESET); 30414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 30514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (i=0; i<NVRAM_SIZE; i++) 30614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (base[i] != 0xff) { 30714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n"); 30814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return -ENXIO; 30914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 31014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0; 31114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 31214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 31314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int sm_write_bank(int bank, u8* datas) 31414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 31514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras int i, stat = 0; 31614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned long timeout; 31714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 318af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; 31914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 32014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("nvram: Sharp/Micron Writing bank %d...\n", bank); 32114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 32214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (i=0; i<NVRAM_SIZE; i++) { 32314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+i, SM_FLASH_CMD_WRITE_SETUP); 32414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 32514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+i, datas[i]); 32614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras timeout = 0; 32714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras do { 32814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (++timeout > 1000000) { 32914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); 33014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras break; 33114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 33214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_READ_STATUS); 33314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras stat = in_8(base); 33414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } while (!(stat & SM_FLASH_STATUS_DONE)); 33514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (!(stat & SM_FLASH_STATUS_DONE)) 33614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras break; 33714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 33814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_CLEAR_STATUS); 33914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, SM_FLASH_CMD_RESET); 34014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (i=0; i<NVRAM_SIZE; i++) 34114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (base[i] != datas[i]) { 34214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n"); 34314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return -ENXIO; 34414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 34514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0; 34614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 34714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 34814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int amd_erase_bank(int bank) 34914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 35014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras int i, stat = 0; 35114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned long timeout; 35214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 353af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; 35414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 35514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("nvram: AMD Erasing bank %d...\n", bank); 35614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 35714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Unlock 1 */ 35814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x555, 0xaa); 35914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 36014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Unlock 2 */ 36114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x2aa, 0x55); 36214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 36314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 36414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Sector-Erase */ 36514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x555, 0x80); 36614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 36714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x555, 0xaa); 36814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 36914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x2aa, 0x55); 37014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 37114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, 0x30); 37214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 37314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 37414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras timeout = 0; 37514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras do { 37614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (++timeout > 1000000) { 37714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); 37814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras break; 37914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 38014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras stat = in_8(base) ^ in_8(base); 38114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } while (stat != 0); 38214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 38314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Reset */ 38414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, 0xf0); 38514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 38614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 38714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (i=0; i<NVRAM_SIZE; i++) 38814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (base[i] != 0xff) { 38914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "nvram: AMD flash erase failed !\n"); 39014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return -ENXIO; 39114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 39214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0; 39314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 39414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 39514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int amd_write_bank(int bank, u8* datas) 39614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 39714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras int i, stat = 0; 39814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned long timeout; 39914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 400af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; 40114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 40214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("nvram: AMD Writing bank %d...\n", bank); 40314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 40414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (i=0; i<NVRAM_SIZE; i++) { 40514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Unlock 1 */ 40614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x555, 0xaa); 40714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 40814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Unlock 2 */ 40914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x2aa, 0x55); 41014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 41114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 41214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Write single word */ 41314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+0x555, 0xa0); 41414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 41514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base+i, datas[i]); 41614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 41714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras timeout = 0; 41814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras do { 41914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (++timeout > 1000000) { 42014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "nvram: AMD flash write timeout !\n"); 42114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras break; 42214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 42314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras stat = in_8(base) ^ in_8(base); 42414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } while (stat != 0); 42514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (stat != 0) 42614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras break; 42714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 42814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 42914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras /* Reset */ 43014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras out_8(base, 0xf0); 43114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras udelay(1); 43214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 43314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (i=0; i<NVRAM_SIZE; i++) 43414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (base[i] != datas[i]) { 43514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "nvram: AMD flash write failed !\n"); 43614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return -ENXIO; 43714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 43814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0; 43914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 44014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 44114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void __init lookup_partitions(void) 44214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 44314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras u8 buffer[17]; 44414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras int i, offset; 44514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras struct chrp_header* hdr; 44614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 44714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (pmac_newworld) { 44814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_OF] = -1; 44914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_XPRAM] = -1; 45014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_NR] = -1; 45114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras hdr = (struct chrp_header *)buffer; 45214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 45314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras offset = 0; 45414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras buffer[16] = 0; 45514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras do { 45614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras for (i=0;i<16;i++) 45735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras buffer[i] = ppc_md.nvram_read_val(offset+i); 45814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (!strcmp(hdr->name, "common")) 45914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_OF] = offset + 0x10; 46014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (!strcmp(hdr->name, "APL,MacOS75")) { 46114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10; 46214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_NR] = offset + 0x110; 46314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 46414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras offset += (hdr->len * 0x10); 46514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } while(offset < NVRAM_SIZE); 46614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } else { 46714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_OF] = 0x1800; 46814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_XPRAM] = 0x1300; 46914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_partitions[pmac_nvram_NR] = 0x1400; 47014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 47114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]); 47214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]); 47314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]); 47414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 47514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 47614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void core99_nvram_sync(void) 47714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 47814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras struct core99_header* hdr99; 47914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras unsigned long flags; 48014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 48114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (!is_core_99 || !nvram_data || !nvram_image) 48214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return; 48314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 48414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras spin_lock_irqsave(&nv_lock, flags); 48514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE, 48614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras NVRAM_SIZE)) 48714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras goto bail; 48814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 48914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras DBG("Updating nvram...\n"); 49014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 49114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras hdr99 = (struct core99_header*)nvram_image; 49214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras hdr99->generation++; 49314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras hdr99->hdr.signature = CORE99_SIGNATURE; 49414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); 49514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras hdr99->adler = core99_calc_adler(nvram_image); 49614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras core99_bank = core99_bank ? 0 : 1; 49714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (core99_erase_bank) 49814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (core99_erase_bank(core99_bank)) { 49914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk("nvram: Error erasing bank %d\n", core99_bank); 50014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras goto bail; 50114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 50214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (core99_write_bank) 50314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (core99_write_bank(core99_bank, nvram_image)) 50414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk("nvram: Error writing bank %d\n", core99_bank); 50514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras bail: 50614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras spin_unlock_irqrestore(&nv_lock, flags); 50714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 50814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef DEBUG 50914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras mdelay(2000); 51014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif 51114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 51214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 513cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidtstatic int __init core99_nvram_setup(struct device_node *dp, unsigned long addr) 51435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{ 51535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras int i; 51635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras u32 gen_bank0, gen_bank1; 51735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 51835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (nvram_naddrs < 1) { 51935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras printk(KERN_ERR "nvram: no address\n"); 52035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return -EINVAL; 52135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras } 52235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras nvram_image = alloc_bootmem(NVRAM_SIZE); 52335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (nvram_image == NULL) { 52435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras printk(KERN_ERR "nvram: can't allocate ram image\n"); 52535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return -ENOMEM; 52635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras } 527cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_data = ioremap(addr, NVRAM_SIZE*2); 52835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras nvram_naddrs = 1; /* Make sure we get the correct case */ 52935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 53035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras DBG("nvram: Checking bank 0...\n"); 53135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 53235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras gen_bank0 = core99_check((u8 *)nvram_data); 53335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); 53435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; 53535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 53635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); 53735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras DBG("nvram: Active bank is: %d\n", core99_bank); 53835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 53935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras for (i=0; i<NVRAM_SIZE; i++) 54035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE]; 54135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 54235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras ppc_md.nvram_read_val = core99_nvram_read_byte; 54335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras ppc_md.nvram_write_val = core99_nvram_write_byte; 54435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras ppc_md.nvram_read = core99_nvram_read; 54535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras ppc_md.nvram_write = core99_nvram_write; 54635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras ppc_md.nvram_size = core99_nvram_size; 54735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras ppc_md.nvram_sync = core99_nvram_sync; 5483d1229d6ae92ed1994f4411b8493327ef8f4b76fMichael Ellerman ppc_md.machine_shutdown = core99_nvram_sync; 54935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras /* 55035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras * Maybe we could be smarter here though making an exclusive list 55135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras * of known flash chips is a bit nasty as older OF didn't provide us 55235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras * with a useful "compatible" entry. A solution would be to really 55335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras * identify the chip using flash id commands and base ourselves on 55435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras * a list of known chips IDs 55535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras */ 55635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (device_is_compatible(dp, "amd-0137")) { 55735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras core99_erase_bank = amd_erase_bank; 55835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras core99_write_bank = amd_write_bank; 55935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras } else { 56035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras core99_erase_bank = sm_erase_bank; 56135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras core99_write_bank = sm_write_bank; 56235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras } 56335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return 0; 56435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras} 56535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras 56635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasint __init pmac_nvram_init(void) 56714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 56814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras struct device_node *dp; 569cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt struct resource r1, r2; 570cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt unsigned int s1 = 0, s2 = 0; 57135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras int err = 0; 57214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 57314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_naddrs = 0; 57414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 575cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt dp = of_find_node_by_name(NULL, "nvram"); 57614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras if (dp == NULL) { 57714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras printk(KERN_ERR "Can't find NVRAM device\n"); 57835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return -ENODEV; 57914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 580cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt 581cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt /* Try to obtain an address */ 582cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt if (of_address_to_resource(dp, 0, &r1) == 0) { 583cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_naddrs = 1; 584cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt s1 = (r1.end - r1.start) + 1; 585cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt if (of_address_to_resource(dp, 1, &r2) == 0) { 586cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_naddrs = 2; 587cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt s2 = (r2.end - r2.start) + 1; 588cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt } 589cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt } 590cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt 59114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras is_core_99 = device_is_compatible(dp, "nvram,flash"); 592cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt if (is_core_99) { 593cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt err = core99_nvram_setup(dp, r1.start); 594cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt goto bail; 595cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt } 596cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt 59735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#ifdef CONFIG_PPC32 598e8222502ee6157e2713da9e0792c21f4ad458d50Benjamin Herrenschmidt if (machine_is(chrp) && nvram_naddrs == 1) { 599cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_data = ioremap(r1.start, s1); 60014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_mult = 1; 60114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_read_val = direct_nvram_read_byte; 60214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_write_val = direct_nvram_write_byte; 60314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } else if (nvram_naddrs == 1) { 604cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_data = ioremap(r1.start, s1); 605cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_mult = (s1 + NVRAM_SIZE - 1) / NVRAM_SIZE; 60614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_read_val = direct_nvram_read_byte; 60714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_write_val = direct_nvram_write_byte; 60814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } else if (nvram_naddrs == 2) { 609cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_addr = ioremap(r1.start, s1); 610cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt nvram_data = ioremap(r2.start, s2); 61114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_read_val = indirect_nvram_read_byte; 61214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_write_val = indirect_nvram_write_byte; 61314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { 61414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef CONFIG_ADB_PMU 61514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras nvram_naddrs = -1; 61614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_read_val = pmu_nvram_read_byte; 61714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_write_val = pmu_nvram_write_byte; 61814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif /* CONFIG_ADB_PMU */ 619cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt } else { 62035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras printk(KERN_ERR "Incompatible type of NVRAM\n"); 621cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt err = -ENXIO; 62214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras } 623cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt#endif /* CONFIG_PPC32 */ 624cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidtbail: 625cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt of_node_put(dp); 626cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt if (err == 0) 627cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt lookup_partitions(); 62835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras return err; 62914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 63014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 63114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasint pmac_get_partition(int partition) 63214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 63314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return nvram_partitions[partition]; 63414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 63514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 63614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasu8 pmac_xpram_read(int xpaddr) 63714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 63835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras int offset = pmac_get_partition(pmac_nvram_XPRAM); 63914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 64035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (offset < 0 || xpaddr < 0 || xpaddr > 0x100) 64114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return 0xff; 64214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 64314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return ppc_md.nvram_read_val(xpaddr + offset); 64414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 64514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 64614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasvoid pmac_xpram_write(int xpaddr, u8 data) 64714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{ 64835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras int offset = pmac_get_partition(pmac_nvram_XPRAM); 64914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 65035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras if (offset < 0 || xpaddr < 0 || xpaddr > 0x100) 65114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras return; 65214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 65314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras ppc_md.nvram_write_val(xpaddr + offset, data); 65414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras} 65514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras 65614cf11af6cf608eb8c23e989ddb17a715ddce109Paul MackerrasEXPORT_SYMBOL(pmac_get_partition); 65714cf11af6cf608eb8c23e989ddb17a715ddce109Paul MackerrasEXPORT_SYMBOL(pmac_xpram_read); 65814cf11af6cf608eb8c23e989ddb17a715ddce109Paul MackerrasEXPORT_SYMBOL(pmac_xpram_write); 659