Path: blob/master/arch/powerpc/sysdev/mmio_nvram.c
10817 views
/*1* memory mapped NVRAM2*3* (C) Copyright IBM Corp. 20054*5* Authors : Utz Bacher <[email protected]>6*7* This program is free software; you can redistribute it and/or modify8* it under the terms of the GNU General Public License as published by9* the Free Software Foundation; either version 2, or (at your option)10* any later version.11*12* This program is distributed in the hope that it will be useful,13* but WITHOUT ANY WARRANTY; without even the implied warranty of14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15* GNU General Public License for more details.16*17* You should have received a copy of the GNU General Public License18* along with this program; if not, write to the Free Software19* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.20*/2122#include <linux/fs.h>23#include <linux/init.h>24#include <linux/kernel.h>25#include <linux/spinlock.h>26#include <linux/types.h>2728#include <asm/machdep.h>29#include <asm/nvram.h>30#include <asm/prom.h>3132static void __iomem *mmio_nvram_start;33static long mmio_nvram_len;34static DEFINE_SPINLOCK(mmio_nvram_lock);3536static ssize_t mmio_nvram_read(char *buf, size_t count, loff_t *index)37{38unsigned long flags;3940if (*index >= mmio_nvram_len)41return 0;42if (*index + count > mmio_nvram_len)43count = mmio_nvram_len - *index;4445spin_lock_irqsave(&mmio_nvram_lock, flags);4647memcpy_fromio(buf, mmio_nvram_start + *index, count);4849spin_unlock_irqrestore(&mmio_nvram_lock, flags);5051*index += count;52return count;53}5455static unsigned char mmio_nvram_read_val(int addr)56{57unsigned long flags;58unsigned char val;5960if (addr >= mmio_nvram_len)61return 0xff;6263spin_lock_irqsave(&mmio_nvram_lock, flags);6465val = ioread8(mmio_nvram_start + addr);6667spin_unlock_irqrestore(&mmio_nvram_lock, flags);6869return val;70}7172static ssize_t mmio_nvram_write(char *buf, size_t count, loff_t *index)73{74unsigned long flags;7576if (*index >= mmio_nvram_len)77return 0;78if (*index + count > mmio_nvram_len)79count = mmio_nvram_len - *index;8081spin_lock_irqsave(&mmio_nvram_lock, flags);8283memcpy_toio(mmio_nvram_start + *index, buf, count);8485spin_unlock_irqrestore(&mmio_nvram_lock, flags);8687*index += count;88return count;89}9091void mmio_nvram_write_val(int addr, unsigned char val)92{93unsigned long flags;9495if (addr < mmio_nvram_len) {96spin_lock_irqsave(&mmio_nvram_lock, flags);9798iowrite8(val, mmio_nvram_start + addr);99100spin_unlock_irqrestore(&mmio_nvram_lock, flags);101}102}103104static ssize_t mmio_nvram_get_size(void)105{106return mmio_nvram_len;107}108109int __init mmio_nvram_init(void)110{111struct device_node *nvram_node;112unsigned long nvram_addr;113struct resource r;114int ret;115116nvram_node = of_find_node_by_type(NULL, "nvram");117if (!nvram_node)118nvram_node = of_find_compatible_node(NULL, NULL, "nvram");119if (!nvram_node) {120printk(KERN_WARNING "nvram: no node found in device-tree\n");121return -ENODEV;122}123124ret = of_address_to_resource(nvram_node, 0, &r);125if (ret) {126printk(KERN_WARNING "nvram: failed to get address (err %d)\n",127ret);128goto out;129}130nvram_addr = r.start;131mmio_nvram_len = r.end - r.start + 1;132if ( (!mmio_nvram_len) || (!nvram_addr) ) {133printk(KERN_WARNING "nvram: address or length is 0\n");134ret = -EIO;135goto out;136}137138mmio_nvram_start = ioremap(nvram_addr, mmio_nvram_len);139if (!mmio_nvram_start) {140printk(KERN_WARNING "nvram: failed to ioremap\n");141ret = -ENOMEM;142goto out;143}144145printk(KERN_INFO "mmio NVRAM, %luk at 0x%lx mapped to %p\n",146mmio_nvram_len >> 10, nvram_addr, mmio_nvram_start);147148ppc_md.nvram_read_val = mmio_nvram_read_val;149ppc_md.nvram_write_val = mmio_nvram_write_val;150ppc_md.nvram_read = mmio_nvram_read;151ppc_md.nvram_write = mmio_nvram_write;152ppc_md.nvram_size = mmio_nvram_get_size;153154out:155of_node_put(nvram_node);156return ret;157}158159160