Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * memory mapped NVRAM
0004  *
0005  * (C) Copyright IBM Corp. 2005
0006  *
0007  * Authors : Utz Bacher <utz.bacher@de.ibm.com>
0008  */
0009 
0010 #include <linux/fs.h>
0011 #include <linux/init.h>
0012 #include <linux/kernel.h>
0013 #include <linux/of_address.h>
0014 #include <linux/spinlock.h>
0015 #include <linux/types.h>
0016 
0017 #include <asm/machdep.h>
0018 #include <asm/nvram.h>
0019 
0020 static void __iomem *mmio_nvram_start;
0021 static long mmio_nvram_len;
0022 static DEFINE_SPINLOCK(mmio_nvram_lock);
0023 
0024 static ssize_t mmio_nvram_read(char *buf, size_t count, loff_t *index)
0025 {
0026     unsigned long flags;
0027 
0028     if (*index >= mmio_nvram_len)
0029         return 0;
0030     if (*index + count > mmio_nvram_len)
0031         count = mmio_nvram_len - *index;
0032 
0033     spin_lock_irqsave(&mmio_nvram_lock, flags);
0034 
0035     memcpy_fromio(buf, mmio_nvram_start + *index, count);
0036 
0037     spin_unlock_irqrestore(&mmio_nvram_lock, flags);
0038     
0039     *index += count;
0040     return count;
0041 }
0042 
0043 static unsigned char mmio_nvram_read_val(int addr)
0044 {
0045     unsigned long flags;
0046     unsigned char val;
0047 
0048     if (addr >= mmio_nvram_len)
0049         return 0xff;
0050 
0051     spin_lock_irqsave(&mmio_nvram_lock, flags);
0052 
0053     val = ioread8(mmio_nvram_start + addr);
0054 
0055     spin_unlock_irqrestore(&mmio_nvram_lock, flags);
0056 
0057     return val;
0058 }
0059 
0060 static ssize_t mmio_nvram_write(char *buf, size_t count, loff_t *index)
0061 {
0062     unsigned long flags;
0063 
0064     if (*index >= mmio_nvram_len)
0065         return 0;
0066     if (*index + count > mmio_nvram_len)
0067         count = mmio_nvram_len - *index;
0068 
0069     spin_lock_irqsave(&mmio_nvram_lock, flags);
0070 
0071     memcpy_toio(mmio_nvram_start + *index, buf, count);
0072 
0073     spin_unlock_irqrestore(&mmio_nvram_lock, flags);
0074     
0075     *index += count;
0076     return count;
0077 }
0078 
0079 static void mmio_nvram_write_val(int addr, unsigned char val)
0080 {
0081     unsigned long flags;
0082 
0083     if (addr < mmio_nvram_len) {
0084         spin_lock_irqsave(&mmio_nvram_lock, flags);
0085 
0086         iowrite8(val, mmio_nvram_start + addr);
0087 
0088         spin_unlock_irqrestore(&mmio_nvram_lock, flags);
0089     }
0090 }
0091 
0092 static ssize_t mmio_nvram_get_size(void)
0093 {
0094     return mmio_nvram_len;
0095 }
0096 
0097 int __init mmio_nvram_init(void)
0098 {
0099     struct device_node *nvram_node;
0100     unsigned long nvram_addr;
0101     struct resource r;
0102     int ret;
0103 
0104     nvram_node = of_find_node_by_type(NULL, "nvram");
0105     if (!nvram_node)
0106         nvram_node = of_find_compatible_node(NULL, NULL, "nvram");
0107     if (!nvram_node) {
0108         printk(KERN_WARNING "nvram: no node found in device-tree\n");
0109         return -ENODEV;
0110     }
0111 
0112     ret = of_address_to_resource(nvram_node, 0, &r);
0113     if (ret) {
0114         printk(KERN_WARNING "nvram: failed to get address (err %d)\n",
0115                ret);
0116         goto out;
0117     }
0118     nvram_addr = r.start;
0119     mmio_nvram_len = resource_size(&r);
0120     if ( (!mmio_nvram_len) || (!nvram_addr) ) {
0121         printk(KERN_WARNING "nvram: address or length is 0\n");
0122         ret = -EIO;
0123         goto out;
0124     }
0125 
0126     mmio_nvram_start = ioremap(nvram_addr, mmio_nvram_len);
0127     if (!mmio_nvram_start) {
0128         printk(KERN_WARNING "nvram: failed to ioremap\n");
0129         ret = -ENOMEM;
0130         goto out;
0131     }
0132 
0133     printk(KERN_INFO "mmio NVRAM, %luk at 0x%lx mapped to %p\n",
0134            mmio_nvram_len >> 10, nvram_addr, mmio_nvram_start);
0135 
0136     ppc_md.nvram_read_val   = mmio_nvram_read_val;
0137     ppc_md.nvram_write_val  = mmio_nvram_write_val;
0138     ppc_md.nvram_read   = mmio_nvram_read;
0139     ppc_md.nvram_write  = mmio_nvram_write;
0140     ppc_md.nvram_size   = mmio_nvram_get_size;
0141 
0142 out:
0143     of_node_put(nvram_node);
0144     return ret;
0145 }