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 */
114b16f8e2d6d64249f0ed3ca7fe2a319d0dde2719Paul Gortmaker#include <linux/export.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/delay.h>
1814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/errno.h>
1914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/adb.h>
2014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/pmu.h>
2114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/bootmem.h>
2214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/completion.h>
2314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <linux/spinlock.h>
2414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/sections.h>
2514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/io.h>
2614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/prom.h>
2714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/machdep.h>
2814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#include <asm/nvram.h>
2914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
300ebfff1491ef85d41ddf9c633834838be144f69fBenjamin Herrenschmidt#include "pmac.h"
310ebfff1491ef85d41ddf9c633834838be144f69fBenjamin Herrenschmidt
3214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define DEBUG
3314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
3414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef DEBUG
3514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define DBG(x...) printk(x)
3614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#else
3714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define DBG(x...)
3814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif
3914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
4014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
4114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
4214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define CORE99_SIGNATURE	0x5a
4314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define CORE99_ADLER_START	0x14
4414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
4514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/* On Core99, nvram is either a sharp, a micron or an AMD flash */
4614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_STATUS_DONE	0x80
4735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#define SM_FLASH_STATUS_ERR	0x38
4835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
4914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_ERASE_CONFIRM	0xd0
5014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_ERASE_SETUP	0x20
5114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_RESET		0xff
5214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_WRITE_SETUP	0x40
5314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_CLEAR_STATUS	0x50
5414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#define SM_FLASH_CMD_READ_STATUS	0x70
5514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
5614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/* CHRP NVRAM header */
5714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstruct chrp_header {
5814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  u8		signature;
5914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  u8		cksum;
6014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  u16		len;
6114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  char          name[12];
6214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  u8		data[0];
6314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras};
6414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
6514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstruct core99_header {
6614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  struct chrp_header	hdr;
6714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  u32			adler;
6814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  u32			generation;
6914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras  u32			reserved[2];
7014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras};
7114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
7214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras/*
7314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
7414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras */
7514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int nvram_naddrs;
76af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwellstatic volatile unsigned char __iomem *nvram_data;
7735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic int is_core_99;
7814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int core99_bank = 0;
7914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int nvram_partitions[3];
8035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras// XXX Turn that into a sem
817d725bdc1b25b9c4ff7c14e43d0d0d6c3d677727Thomas Gleixnerstatic DEFINE_RAW_SPINLOCK(nv_lock);
8214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
8314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int (*core99_write_bank)(int bank, u8* datas);
8414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int (*core99_erase_bank)(int bank);
8514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
8614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic char *nvram_image;
8714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
8814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
8914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char core99_nvram_read_byte(int addr)
9014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
9114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (nvram_image == NULL)
9214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return 0xff;
9314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return nvram_image[addr];
9414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
9514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
9614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void core99_nvram_write_byte(int addr, unsigned char val)
9714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
9814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (nvram_image == NULL)
9914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return;
10014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	nvram_image[addr] = val;
10114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
10214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
10335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic ssize_t core99_nvram_read(char *buf, size_t count, loff_t *index)
10435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{
10535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	int i;
10635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
10735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (nvram_image == NULL)
10835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return -ENODEV;
10935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (*index > NVRAM_SIZE)
11035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return 0;
11135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
11235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	i = *index;
11335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (i + count > NVRAM_SIZE)
11435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		count = NVRAM_SIZE - i;
11535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
11635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	memcpy(buf, &nvram_image[i], count);
11735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	*index = i + count;
11835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	return count;
11935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras}
12035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
12135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic ssize_t core99_nvram_write(char *buf, size_t count, loff_t *index)
12235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{
12335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	int i;
12435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
12535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (nvram_image == NULL)
12635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return -ENODEV;
12735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (*index > NVRAM_SIZE)
12835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return 0;
12935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
13035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	i = *index;
13135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (i + count > NVRAM_SIZE)
13235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		count = NVRAM_SIZE - i;
13335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
13435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	memcpy(&nvram_image[i], buf, count);
13535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	*index = i + count;
13635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	return count;
13735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras}
13835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
13935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic ssize_t core99_nvram_size(void)
14035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{
14135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (nvram_image == NULL)
14235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return -ENODEV;
14335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	return NVRAM_SIZE;
14435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras}
14535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
14635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#ifdef CONFIG_PPC32
147af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwellstatic volatile unsigned char __iomem *nvram_addr;
14835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasstatic int nvram_mult;
14914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
15014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char direct_nvram_read_byte(int addr)
15114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
15214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]);
15314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
15414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
15514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void direct_nvram_write_byte(int addr, unsigned char val)
15614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
15714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val);
15814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
15914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
16014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
16114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char indirect_nvram_read_byte(int addr)
16214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
16314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned char val;
16414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long flags;
16514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
1667d725bdc1b25b9c4ff7c14e43d0d0d6c3d677727Thomas Gleixner	raw_spin_lock_irqsave(&nv_lock, flags);
16714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(nvram_addr, addr >> 5);
16814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	val = in_8(&nvram_data[(addr & 0x1f) << 4]);
1697d725bdc1b25b9c4ff7c14e43d0d0d6c3d677727Thomas Gleixner	raw_spin_unlock_irqrestore(&nv_lock, flags);
17014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
17114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return val;
17214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
17314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
17414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void indirect_nvram_write_byte(int addr, unsigned char val)
17514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
17614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long flags;
17714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
1787d725bdc1b25b9c4ff7c14e43d0d0d6c3d677727Thomas Gleixner	raw_spin_lock_irqsave(&nv_lock, flags);
17914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(nvram_addr, addr >> 5);
18014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(&nvram_data[(addr & 0x1f) << 4], val);
1817d725bdc1b25b9c4ff7c14e43d0d0d6c3d677727Thomas Gleixner	raw_spin_unlock_irqrestore(&nv_lock, flags);
18214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
18314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
18414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
18514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef CONFIG_ADB_PMU
18614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
18714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void pmu_nvram_complete(struct adb_request *req)
18814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
18914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (req->arg)
19014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		complete((struct completion *)req->arg);
19114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
19214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
19314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic unsigned char pmu_nvram_read_byte(int addr)
19414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
19514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	struct adb_request req;
1966e9a4738c9fadb7cbdcabc1e3b415159f3741ed9Peter Zijlstra	DECLARE_COMPLETION_ONSTACK(req_complete);
19714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
19814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
19914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM,
20014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			(addr >> 8) & 0xff, addr & 0xff))
20114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return 0xff;
20214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (system_state == SYSTEM_RUNNING)
20314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		wait_for_completion(&req_complete);
20414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	while (!req.complete)
20514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		pmu_poll();
20614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return req.reply[0];
20714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
20814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
20914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void pmu_nvram_write_byte(int addr, unsigned char val)
21014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
21114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	struct adb_request req;
2126e9a4738c9fadb7cbdcabc1e3b415159f3741ed9Peter Zijlstra	DECLARE_COMPLETION_ONSTACK(req_complete);
21314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
21414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL;
21514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM,
21614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			(addr >> 8) & 0xff, addr & 0xff, val))
21714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return;
21814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (system_state == SYSTEM_RUNNING)
21914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		wait_for_completion(&req_complete);
22014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	while (!req.complete)
22114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		pmu_poll();
22214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
22314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
22414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif /* CONFIG_ADB_PMU */
22535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#endif /* CONFIG_PPC32 */
22614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
22714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic u8 chrp_checksum(struct chrp_header* hdr)
22814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
22914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	u8 *ptr;
23014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	u16 sum = hdr->signature;
23114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
23214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		sum += *ptr;
23314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	while (sum > 0xFF)
23414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		sum = (sum & 0xFF) + (sum>>8);
23514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return sum;
23614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
23714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
23814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic u32 core99_calc_adler(u8 *buffer)
23914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
24014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	int cnt;
24114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	u32 low, high;
24214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
24314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras   	buffer += CORE99_ADLER_START;
24414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	low = 1;
24514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	high = 0;
24614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
24714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if ((cnt % 5000) == 0) {
24814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			high  %= 65521UL;
24914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			high %= 65521UL;
25014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		}
25114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		low += buffer[cnt];
25214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		high += low;
25314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
25414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	low  %= 65521UL;
25514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	high %= 65521UL;
25614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
25714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return (high << 16) | low;
25814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
25914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
26014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic u32 core99_check(u8* datas)
26114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
26214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	struct core99_header* hdr99 = (struct core99_header*)datas;
26314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
26414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (hdr99->hdr.signature != CORE99_SIGNATURE) {
26514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		DBG("Invalid signature\n");
26614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return 0;
26714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
26814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
26914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		DBG("Invalid checksum\n");
27014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return 0;
27114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
27214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (hdr99->adler != core99_calc_adler(datas)) {
27314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		DBG("Invalid adler\n");
27414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return 0;
27514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
27614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return hdr99->generation;
27714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
27814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
27914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int sm_erase_bank(int bank)
28014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
2812d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	int stat;
28214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long timeout;
28314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
284af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
28514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
28614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras       	DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank);
28714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
28814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, SM_FLASH_CMD_ERASE_SETUP);
28914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, SM_FLASH_CMD_ERASE_CONFIRM);
29014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	timeout = 0;
29114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	do {
29214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (++timeout > 1000000) {
29335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras			printk(KERN_ERR "nvram: Sharp/Micron flash erase timeout !\n");
29414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			break;
29514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		}
29614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		out_8(base, SM_FLASH_CMD_READ_STATUS);
29714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		stat = in_8(base);
29814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} while (!(stat & SM_FLASH_STATUS_DONE));
29914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
30014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
30114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, SM_FLASH_CMD_RESET);
30214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
3032d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
3042d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n");
3052d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		return -ENXIO;
3062d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	}
30714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return 0;
30814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
30914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
31014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int sm_write_bank(int bank, u8* datas)
31114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
31214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	int i, stat = 0;
31314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long timeout;
31414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
315af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
31614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
31714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras       	DBG("nvram: Sharp/Micron Writing bank %d...\n", bank);
31814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
31914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	for (i=0; i<NVRAM_SIZE; i++) {
32014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		out_8(base+i, SM_FLASH_CMD_WRITE_SETUP);
32114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		udelay(1);
32214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		out_8(base+i, datas[i]);
32314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		timeout = 0;
32414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		do {
32514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			if (++timeout > 1000000) {
32614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras				printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n");
32714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras				break;
32814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			}
32914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			out_8(base, SM_FLASH_CMD_READ_STATUS);
33014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			stat = in_8(base);
33114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		} while (!(stat & SM_FLASH_STATUS_DONE));
33214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (!(stat & SM_FLASH_STATUS_DONE))
33314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			break;
33414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
33514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, SM_FLASH_CMD_CLEAR_STATUS);
33614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, SM_FLASH_CMD_RESET);
3372d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	if (memcmp(base, datas, NVRAM_SIZE)) {
3382d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n");
3392d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		return -ENXIO;
3402d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	}
34114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return 0;
34214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
34314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
34414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int amd_erase_bank(int bank)
34514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
3462d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	int stat = 0;
34714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long timeout;
34814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
349af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
35014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
35114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras       	DBG("nvram: AMD Erasing bank %d...\n", bank);
35214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
35314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/* Unlock 1 */
35414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base+0x555, 0xaa);
35514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
35614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/* Unlock 2 */
35714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base+0x2aa, 0x55);
35814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
35914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
36014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/* Sector-Erase */
36114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base+0x555, 0x80);
36214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
36314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base+0x555, 0xaa);
36414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
36514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base+0x2aa, 0x55);
36614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
36714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, 0x30);
36814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
36914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
37014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	timeout = 0;
37114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	do {
37214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (++timeout > 1000000) {
37314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			printk(KERN_ERR "nvram: AMD flash erase timeout !\n");
37414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			break;
37514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		}
37614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		stat = in_8(base) ^ in_8(base);
37714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} while (stat != 0);
37814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
37914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/* Reset */
38014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, 0xf0);
38114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
3822d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita
3832d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	if (memchr_inv(base, 0xff, NVRAM_SIZE)) {
3842d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		printk(KERN_ERR "nvram: AMD flash erase failed !\n");
3852d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		return -ENXIO;
3862d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	}
38714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return 0;
38814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
38914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
39014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic int amd_write_bank(int bank, u8* datas)
39114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
39214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	int i, stat = 0;
39314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long timeout;
39414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
395af308377e204e25f1f58627d05fe0f483703b514Stephen Rothwell	u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE;
39614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
39714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras       	DBG("nvram: AMD Writing bank %d...\n", bank);
39814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
39914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	for (i=0; i<NVRAM_SIZE; i++) {
40014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		/* Unlock 1 */
40114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		out_8(base+0x555, 0xaa);
40214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		udelay(1);
40314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		/* Unlock 2 */
40414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		out_8(base+0x2aa, 0x55);
40514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		udelay(1);
40614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
40714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		/* Write single word */
40814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		out_8(base+0x555, 0xa0);
40914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		udelay(1);
41014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		out_8(base+i, datas[i]);
41114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
41214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		timeout = 0;
41314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		do {
41414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			if (++timeout > 1000000) {
41514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras				printk(KERN_ERR "nvram: AMD flash write timeout !\n");
41614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras				break;
41714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			}
41814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			stat = in_8(base) ^ in_8(base);
41914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		} while (stat != 0);
42014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (stat != 0)
42114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			break;
42214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
42314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
42414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	/* Reset */
42514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	out_8(base, 0xf0);
42614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	udelay(1);
42714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
4282d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	if (memcmp(base, datas, NVRAM_SIZE)) {
4292d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		printk(KERN_ERR "nvram: AMD flash write failed !\n");
4302d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita		return -ENXIO;
4312d4b971287cbce16585acda4b76308faa8da0950Akinobu Mita	}
43214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return 0;
43314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
43414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
43514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void __init lookup_partitions(void)
43614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
43714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	u8 buffer[17];
43814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	int i, offset;
43914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	struct chrp_header* hdr;
44014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
44114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (pmac_newworld) {
44214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_partitions[pmac_nvram_OF] = -1;
44314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_partitions[pmac_nvram_XPRAM] = -1;
44414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_partitions[pmac_nvram_NR] = -1;
44514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		hdr = (struct chrp_header *)buffer;
44614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
44714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		offset = 0;
44814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		buffer[16] = 0;
44914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		do {
45014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			for (i=0;i<16;i++)
45135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras				buffer[i] = ppc_md.nvram_read_val(offset+i);
45214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			if (!strcmp(hdr->name, "common"))
45314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras				nvram_partitions[pmac_nvram_OF] = offset + 0x10;
45414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			if (!strcmp(hdr->name, "APL,MacOS75")) {
45514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras				nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
45614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras				nvram_partitions[pmac_nvram_NR] = offset + 0x110;
45714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			}
45814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			offset += (hdr->len * 0x10);
45914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		} while(offset < NVRAM_SIZE);
46014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} else {
46114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_partitions[pmac_nvram_OF] = 0x1800;
46214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
46314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_partitions[pmac_nvram_NR] = 0x1400;
46414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
46514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
46614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
46714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
46814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
46914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
47014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasstatic void core99_nvram_sync(void)
47114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
47214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	struct core99_header* hdr99;
47314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	unsigned long flags;
47414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
47514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (!is_core_99 || !nvram_data || !nvram_image)
47614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return;
47714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
4787d725bdc1b25b9c4ff7c14e43d0d0d6c3d677727Thomas Gleixner	raw_spin_lock_irqsave(&nv_lock, flags);
47914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
48014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		NVRAM_SIZE))
48114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		goto bail;
48214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
48314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	DBG("Updating nvram...\n");
48414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
48514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	hdr99 = (struct core99_header*)nvram_image;
48614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	hdr99->generation++;
48714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	hdr99->hdr.signature = CORE99_SIGNATURE;
48814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
48914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	hdr99->adler = core99_calc_adler(nvram_image);
49014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	core99_bank = core99_bank ? 0 : 1;
49114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (core99_erase_bank)
49214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (core99_erase_bank(core99_bank)) {
49314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			printk("nvram: Error erasing bank %d\n", core99_bank);
49414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			goto bail;
49514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		}
49614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (core99_write_bank)
49714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		if (core99_write_bank(core99_bank, nvram_image))
49814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras			printk("nvram: Error writing bank %d\n", core99_bank);
49914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras bail:
5007d725bdc1b25b9c4ff7c14e43d0d0d6c3d677727Thomas Gleixner	raw_spin_unlock_irqrestore(&nv_lock, flags);
50114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
50214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef DEBUG
50314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras       	mdelay(2000);
50414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif
50514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
50614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
507cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidtstatic int __init core99_nvram_setup(struct device_node *dp, unsigned long addr)
50835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras{
50935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	int i;
51035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	u32 gen_bank0, gen_bank1;
51135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
51235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (nvram_naddrs < 1) {
51335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		printk(KERN_ERR "nvram: no address\n");
51435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return -EINVAL;
51535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	}
51635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	nvram_image = alloc_bootmem(NVRAM_SIZE);
51735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (nvram_image == NULL) {
51835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		printk(KERN_ERR "nvram: can't allocate ram image\n");
51935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return -ENOMEM;
52035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	}
521cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	nvram_data = ioremap(addr, NVRAM_SIZE*2);
52235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	nvram_naddrs = 1; /* Make sure we get the correct case */
52335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
52435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	DBG("nvram: Checking bank 0...\n");
52535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
52635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	gen_bank0 = core99_check((u8 *)nvram_data);
52735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
52835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
52935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
53035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
53135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	DBG("nvram: Active bank is: %d\n", core99_bank);
53235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
53335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	for (i=0; i<NVRAM_SIZE; i++)
53435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
53535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
53635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	ppc_md.nvram_read_val	= core99_nvram_read_byte;
53735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	ppc_md.nvram_write_val	= core99_nvram_write_byte;
53835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	ppc_md.nvram_read	= core99_nvram_read;
53935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	ppc_md.nvram_write	= core99_nvram_write;
54035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	ppc_md.nvram_size	= core99_nvram_size;
54135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	ppc_md.nvram_sync	= core99_nvram_sync;
5423d1229d6ae92ed1994f4411b8493327ef8f4b76fMichael Ellerman	ppc_md.machine_shutdown	= core99_nvram_sync;
54335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	/*
54435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	 * Maybe we could be smarter here though making an exclusive list
54535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	 * of known flash chips is a bit nasty as older OF didn't provide us
54635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	 * with a useful "compatible" entry. A solution would be to really
54735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	 * identify the chip using flash id commands and base ourselves on
54835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	 * a list of known chips IDs
54935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	 */
55055b61fec22caa3e7872caea6c4100fc75cb8f49bStephen Rothwell	if (of_device_is_compatible(dp, "amd-0137")) {
55135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		core99_erase_bank = amd_erase_bank;
55235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		core99_write_bank = amd_write_bank;
55335499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	} else {
55435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		core99_erase_bank = sm_erase_bank;
55535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		core99_write_bank = sm_write_bank;
55635499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	}
55735499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	return 0;
55835499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras}
55935499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras
56035499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerrasint __init pmac_nvram_init(void)
56114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
56214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	struct device_node *dp;
563cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	struct resource r1, r2;
564cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	unsigned int s1 = 0, s2 = 0;
56535499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	int err = 0;
56614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
56714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	nvram_naddrs = 0;
56814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
569cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	dp = of_find_node_by_name(NULL, "nvram");
57014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	if (dp == NULL) {
57114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		printk(KERN_ERR "Can't find NVRAM device\n");
57235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		return -ENODEV;
57314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
574cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt
575cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	/* Try to obtain an address */
576cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	if (of_address_to_resource(dp, 0, &r1) == 0) {
577cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		nvram_naddrs = 1;
57828f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches		s1 = resource_size(&r1);
579cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		if (of_address_to_resource(dp, 1, &r2) == 0) {
580cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt			nvram_naddrs = 2;
58128f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches			s2 = resource_size(&r2);
582cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		}
583cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	}
584cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt
58555b61fec22caa3e7872caea6c4100fc75cb8f49bStephen Rothwell	is_core_99 = of_device_is_compatible(dp, "nvram,flash");
586cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	if (is_core_99) {
587cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		err = core99_nvram_setup(dp, r1.start);
588cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		goto bail;
589cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	}
590cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt
59135499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras#ifdef CONFIG_PPC32
592e8222502ee6157e2713da9e0792c21f4ad458d50Benjamin Herrenschmidt	if (machine_is(chrp) && nvram_naddrs == 1) {
593cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		nvram_data = ioremap(r1.start, s1);
59414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_mult = 1;
59514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_read_val	= direct_nvram_read_byte;
59614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_write_val	= direct_nvram_write_byte;
59714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} else if (nvram_naddrs == 1) {
598cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		nvram_data = ioremap(r1.start, s1);
599cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		nvram_mult = (s1 + NVRAM_SIZE - 1) / NVRAM_SIZE;
60014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_read_val	= direct_nvram_read_byte;
60114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_write_val	= direct_nvram_write_byte;
60214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} else if (nvram_naddrs == 2) {
603cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		nvram_addr = ioremap(r1.start, s1);
604cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		nvram_data = ioremap(r2.start, s2);
60514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_read_val	= indirect_nvram_read_byte;
60614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_write_val	= indirect_nvram_write_byte;
60714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
60814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#ifdef CONFIG_ADB_PMU
60914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		nvram_naddrs = -1;
61014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_read_val	= pmu_nvram_read_byte;
61114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		ppc_md.nvram_write_val	= pmu_nvram_write_byte;
61214cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras#endif /* CONFIG_ADB_PMU */
613cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	} else {
61435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras		printk(KERN_ERR "Incompatible type of NVRAM\n");
615cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		err = -ENXIO;
61614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	}
617cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt#endif /* CONFIG_PPC32 */
618cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidtbail:
619cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	of_node_put(dp);
620cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt	if (err == 0)
621cc5d0189b9ba95260857a5018a1c2fef90008507Benjamin Herrenschmidt		lookup_partitions();
62235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	return err;
62314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
62414cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
62514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasint pmac_get_partition(int partition)
62614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
62714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return nvram_partitions[partition];
62814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
62914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
63014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasu8 pmac_xpram_read(int xpaddr)
63114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
63235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	int offset = pmac_get_partition(pmac_nvram_XPRAM);
63314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
63435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
63514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return 0xff;
63614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
63714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	return ppc_md.nvram_read_val(xpaddr + offset);
63814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
63914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
64014cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerrasvoid pmac_xpram_write(int xpaddr, u8 data)
64114cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras{
64235499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	int offset = pmac_get_partition(pmac_nvram_XPRAM);
64314cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
64435499c0195e46f479cf6ac16ad8d3f394b5fcc10Paul Mackerras	if (offset < 0 || xpaddr < 0 || xpaddr > 0x100)
64514cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras		return;
64614cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
64714cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras	ppc_md.nvram_write_val(xpaddr + offset, data);
64814cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras}
64914cf11af6cf608eb8c23e989ddb17a715ddce109Paul Mackerras
65014cf11af6cf608eb8c23e989ddb17a715ddce109Paul MackerrasEXPORT_SYMBOL(pmac_get_partition);
65114cf11af6cf608eb8c23e989ddb17a715ddce109Paul MackerrasEXPORT_SYMBOL(pmac_xpram_read);
65214cf11af6cf608eb8c23e989ddb17a715ddce109Paul MackerrasEXPORT_SYMBOL(pmac_xpram_write);
653