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