xref: /OK3568_Linux_fs/kernel/arch/powerpc/sysdev/mmio_nvram.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * memory mapped NVRAM
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * (C) Copyright IBM Corp. 2005
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Authors : Utz Bacher <utz.bacher@de.ibm.com>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/fs.h>
11*4882a593Smuzhiyun #include <linux/init.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/spinlock.h>
14*4882a593Smuzhiyun #include <linux/types.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <asm/machdep.h>
17*4882a593Smuzhiyun #include <asm/nvram.h>
18*4882a593Smuzhiyun #include <asm/prom.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun static void __iomem *mmio_nvram_start;
21*4882a593Smuzhiyun static long mmio_nvram_len;
22*4882a593Smuzhiyun static DEFINE_SPINLOCK(mmio_nvram_lock);
23*4882a593Smuzhiyun 
mmio_nvram_read(char * buf,size_t count,loff_t * index)24*4882a593Smuzhiyun static ssize_t mmio_nvram_read(char *buf, size_t count, loff_t *index)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	unsigned long flags;
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 	if (*index >= mmio_nvram_len)
29*4882a593Smuzhiyun 		return 0;
30*4882a593Smuzhiyun 	if (*index + count > mmio_nvram_len)
31*4882a593Smuzhiyun 		count = mmio_nvram_len - *index;
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	spin_lock_irqsave(&mmio_nvram_lock, flags);
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	memcpy_fromio(buf, mmio_nvram_start + *index, count);
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mmio_nvram_lock, flags);
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	*index += count;
40*4882a593Smuzhiyun 	return count;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun 
mmio_nvram_read_val(int addr)43*4882a593Smuzhiyun static unsigned char mmio_nvram_read_val(int addr)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun 	unsigned long flags;
46*4882a593Smuzhiyun 	unsigned char val;
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	if (addr >= mmio_nvram_len)
49*4882a593Smuzhiyun 		return 0xff;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	spin_lock_irqsave(&mmio_nvram_lock, flags);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	val = ioread8(mmio_nvram_start + addr);
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mmio_nvram_lock, flags);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	return val;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun 
mmio_nvram_write(char * buf,size_t count,loff_t * index)60*4882a593Smuzhiyun static ssize_t mmio_nvram_write(char *buf, size_t count, loff_t *index)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	unsigned long flags;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	if (*index >= mmio_nvram_len)
65*4882a593Smuzhiyun 		return 0;
66*4882a593Smuzhiyun 	if (*index + count > mmio_nvram_len)
67*4882a593Smuzhiyun 		count = mmio_nvram_len - *index;
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	spin_lock_irqsave(&mmio_nvram_lock, flags);
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	memcpy_toio(mmio_nvram_start + *index, buf, count);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	spin_unlock_irqrestore(&mmio_nvram_lock, flags);
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	*index += count;
76*4882a593Smuzhiyun 	return count;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
mmio_nvram_write_val(int addr,unsigned char val)79*4882a593Smuzhiyun static void mmio_nvram_write_val(int addr, unsigned char val)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun 	unsigned long flags;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	if (addr < mmio_nvram_len) {
84*4882a593Smuzhiyun 		spin_lock_irqsave(&mmio_nvram_lock, flags);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 		iowrite8(val, mmio_nvram_start + addr);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 		spin_unlock_irqrestore(&mmio_nvram_lock, flags);
89*4882a593Smuzhiyun 	}
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
mmio_nvram_get_size(void)92*4882a593Smuzhiyun static ssize_t mmio_nvram_get_size(void)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	return mmio_nvram_len;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
mmio_nvram_init(void)97*4882a593Smuzhiyun int __init mmio_nvram_init(void)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	struct device_node *nvram_node;
100*4882a593Smuzhiyun 	unsigned long nvram_addr;
101*4882a593Smuzhiyun 	struct resource r;
102*4882a593Smuzhiyun 	int ret;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	nvram_node = of_find_node_by_type(NULL, "nvram");
105*4882a593Smuzhiyun 	if (!nvram_node)
106*4882a593Smuzhiyun 		nvram_node = of_find_compatible_node(NULL, NULL, "nvram");
107*4882a593Smuzhiyun 	if (!nvram_node) {
108*4882a593Smuzhiyun 		printk(KERN_WARNING "nvram: no node found in device-tree\n");
109*4882a593Smuzhiyun 		return -ENODEV;
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	ret = of_address_to_resource(nvram_node, 0, &r);
113*4882a593Smuzhiyun 	if (ret) {
114*4882a593Smuzhiyun 		printk(KERN_WARNING "nvram: failed to get address (err %d)\n",
115*4882a593Smuzhiyun 		       ret);
116*4882a593Smuzhiyun 		goto out;
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 	nvram_addr = r.start;
119*4882a593Smuzhiyun 	mmio_nvram_len = resource_size(&r);
120*4882a593Smuzhiyun 	if ( (!mmio_nvram_len) || (!nvram_addr) ) {
121*4882a593Smuzhiyun 		printk(KERN_WARNING "nvram: address or length is 0\n");
122*4882a593Smuzhiyun 		ret = -EIO;
123*4882a593Smuzhiyun 		goto out;
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	mmio_nvram_start = ioremap(nvram_addr, mmio_nvram_len);
127*4882a593Smuzhiyun 	if (!mmio_nvram_start) {
128*4882a593Smuzhiyun 		printk(KERN_WARNING "nvram: failed to ioremap\n");
129*4882a593Smuzhiyun 		ret = -ENOMEM;
130*4882a593Smuzhiyun 		goto out;
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	printk(KERN_INFO "mmio NVRAM, %luk at 0x%lx mapped to %p\n",
134*4882a593Smuzhiyun 	       mmio_nvram_len >> 10, nvram_addr, mmio_nvram_start);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	ppc_md.nvram_read_val	= mmio_nvram_read_val;
137*4882a593Smuzhiyun 	ppc_md.nvram_write_val	= mmio_nvram_write_val;
138*4882a593Smuzhiyun 	ppc_md.nvram_read	= mmio_nvram_read;
139*4882a593Smuzhiyun 	ppc_md.nvram_write	= mmio_nvram_write;
140*4882a593Smuzhiyun 	ppc_md.nvram_size	= mmio_nvram_get_size;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun out:
143*4882a593Smuzhiyun 	of_node_put(nvram_node);
144*4882a593Smuzhiyun 	return ret;
145*4882a593Smuzhiyun }
146