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