File Index
Files and directories
Sign in
FILE

nvram.c

File preview with syntax highlighting.

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