From fea796e8f4af85f7c384f80985c5656577dc5d84 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 6 Feb 2004 14:20:56 +1100 Subject: [PATCH] ppc32: Rework nvram management move drivers/macintosh/nvram.c to drivers/char/generic_nvram.c, update platform hooks, fix powermac nvram driver for newer machines --- arch/ppc/Kconfig | 4 + arch/ppc/kernel/ppc_ksyms.c | 8 - arch/ppc/kernel/setup.c | 34 ++- arch/ppc/platforms/pmac_nvram.c | 523 +++++++++++++++++++++----------- drivers/char/Makefile | 4 +- drivers/char/generic_nvram.c | 145 +++++++++ drivers/macintosh/Makefile | 3 - include/asm-ppc/machdep.h | 1 + include/asm-ppc/nvram.h | 25 +- 9 files changed, 547 insertions(+), 200 deletions(-) create mode 100644 drivers/char/generic_nvram.c diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index dda6dc91e1b7d..df86732b720c6 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -30,6 +30,10 @@ config PPC32 bool default y +# All PPCs use generic nvram driver through ppc_md +config GENERIC_NVRAM + bool + default y source "init/Kconfig" diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 8d0360f8d911f..6cf2478be1a4b 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -283,14 +283,6 @@ EXPORT_SYMBOL(note_scsi_host); #ifdef CONFIG_VT EXPORT_SYMBOL(kd_mksound); #endif -#ifdef CONFIG_NVRAM -EXPORT_SYMBOL(nvram_read_byte); -EXPORT_SYMBOL(nvram_write_byte); -#ifdef CONFIG_PPC_PMAC -EXPORT_SYMBOL(pmac_xpram_read); -EXPORT_SYMBOL(pmac_xpram_write); -#endif -#endif /* CONFIG_NVRAM */ EXPORT_SYMBOL(to_tm); EXPORT_SYMBOL(pm_power_off); diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 94c00edb40bf6..7d1ecb35a6196 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #if defined CONFIG_KGDB @@ -111,6 +112,9 @@ struct screen_info screen_info = { void machine_restart(char *cmd) { +#ifdef CONFIG_NVRAM + nvram_sync(); +#endif ppc_md.restart(cmd); } @@ -118,6 +122,9 @@ EXPORT_SYMBOL(machine_restart); void machine_power_off(void) { +#ifdef CONFIG_NVRAM + nvram_sync(); +#endif ppc_md.power_off(); } @@ -125,6 +132,9 @@ EXPORT_SYMBOL(machine_power_off); void machine_halt(void) { +#ifdef CONFIG_NVRAM + nvram_sync(); +#endif ppc_md.halt(); } @@ -558,24 +568,30 @@ int __init ppc_setup_l2cr(char *str) __setup("l2cr=", ppc_setup_l2cr); #ifdef CONFIG_NVRAM -/* Generic nvram hooks we now look into ppc_md.nvram_read_val - * on pmac too ;) - * //XX Those 2 could be moved to headers - */ -unsigned char -nvram_read_byte(int addr) + +/* Generic nvram hooks used by drivers/char/gen_nvram.c */ +unsigned char nvram_read_byte(int addr) { if (ppc_md.nvram_read_val) return ppc_md.nvram_read_val(addr); return 0xff; } +EXPORT_SYMBOL(nvram_read_byte); -void -nvram_write_byte(unsigned char val, int addr) +void nvram_write_byte(unsigned char val, int addr) { if (ppc_md.nvram_write_val) - ppc_md.nvram_write_val(val, addr); + ppc_md.nvram_write_val(addr, val); +} +EXPORT_SYMBOL(nvram_write_byte); + +void nvram_sync(void) +{ + if (ppc_md.nvram_sync) + ppc_md.nvram_sync(); } +EXPORT_SYMBOL(nvram_sync); + #endif /* CONFIG_NVRAM */ static struct cpu cpu_devices[NR_CPUS]; diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c index d11d2445b54e4..f381f3f745f95 100644 --- a/arch/ppc/platforms/pmac_nvram.c +++ b/arch/ppc/platforms/pmac_nvram.c @@ -8,8 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Todo: - cleanup some coding horrors in the flash code - * - add support for the OF persistent properties + * Todo: - add support for the OF persistent properties */ #include #include @@ -21,29 +20,40 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include #include #include #include -#include -#include -#undef DEBUG +#define DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif #define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ #define CORE99_SIGNATURE 0x5a #define CORE99_ADLER_START 0x14 -/* Core99 nvram is a flash */ -#define CORE99_FLASH_STATUS_DONE 0x80 -#define CORE99_FLASH_STATUS_ERR 0x38 -#define CORE99_FLASH_CMD_ERASE_CONFIRM 0xd0 -#define CORE99_FLASH_CMD_ERASE_SETUP 0x20 -#define CORE99_FLASH_CMD_RESET 0xff -#define CORE99_FLASH_CMD_WRITE_SETUP 0x40 +/* On Core99, nvram is either a sharp, a micron or an AMD flash */ +#define SM_FLASH_STATUS_DONE 0x80 +#define SM_FLASH_STATUS_ERR 0x38 +#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 +#define SM_FLASH_CMD_ERASE_SETUP 0x20 +#define SM_FLASH_CMD_RESET 0xff +#define SM_FLASH_CMD_WRITE_SETUP 0x40 +#define SM_FLASH_CMD_CLEAR_STATUS 0x50 +#define SM_FLASH_CMD_READ_STATUS 0x70 /* CHRP NVRAM header */ struct chrp_header { @@ -70,21 +80,110 @@ static volatile unsigned char *nvram_data; static int nvram_mult, is_core_99; static int core99_bank = 0; static int nvram_partitions[3]; - -/* FIXME: kmalloc fails to allocate the image now that I had to move it - * before time_init(). For now, I allocate a static buffer here - * but it's a waste of space on all but core99 machines - */ -#if 0 -static char* nvram_image; -#else -static char nvram_image[NVRAM_SIZE] __pmacdata; -#endif +static spinlock_t nv_lock = SPIN_LOCK_UNLOCKED; extern int pmac_newworld; +extern int system_running; + +static int (*core99_write_bank)(int bank, u8* datas); +static int (*core99_erase_bank)(int bank); + +static char *nvram_image __pmacdata; + + +static unsigned char __pmac core99_nvram_read_byte(int addr) +{ + if (nvram_image == NULL) + return 0xff; + return nvram_image[addr]; +} + +static void __pmac core99_nvram_write_byte(int addr, unsigned char val) +{ + if (nvram_image == NULL) + return; + nvram_image[addr] = val; +} + + +static unsigned char __openfirmware direct_nvram_read_byte(int addr) +{ + return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]); +} + +static void __openfirmware direct_nvram_write_byte(int addr, unsigned char val) +{ + out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val); +} + + +static unsigned char __pmac indirect_nvram_read_byte(int addr) +{ + unsigned char val; + unsigned long flags; + + spin_lock_irqsave(&nv_lock, flags); + out_8(nvram_addr, addr >> 5); + val = in_8(&nvram_data[(addr & 0x1f) << 4]); + spin_unlock_irqrestore(&nv_lock, flags); + + return val; +} + +static void __pmac indirect_nvram_write_byte(int addr, unsigned char val) +{ + unsigned long flags; + + spin_lock_irqsave(&nv_lock, flags); + out_8(nvram_addr, addr >> 5); + out_8(&nvram_data[(addr & 0x1f) << 4], val); + spin_unlock_irqrestore(&nv_lock, flags); +} + + +#ifdef CONFIG_ADB_PMU + +static void __pmac pmu_nvram_complete(struct adb_request *req) +{ + if (req->arg) + complete((struct completion *)req->arg); +} -static u8 __pmac -chrp_checksum(struct chrp_header* hdr) +static unsigned char __pmac pmu_nvram_read_byte(int addr) +{ + struct adb_request req; + DECLARE_COMPLETION(req_complete); + + req.arg = system_running ? &req_complete : NULL; + if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM, + (addr >> 8) & 0xff, addr & 0xff)) + return 0xff; + if (system_running) + wait_for_completion(&req_complete); + while (!req.complete) + pmu_poll(); + return req.reply[0]; +} + +static void __pmac pmu_nvram_write_byte(int addr, unsigned char val) +{ + struct adb_request req; + DECLARE_COMPLETION(req_complete); + + req.arg = system_running ? &req_complete : NULL; + if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM, + (addr >> 8) & 0xff, addr & 0xff, val)) + return; + if (system_running) + wait_for_completion(&req_complete); + while (!req.complete) + pmu_poll(); +} + +#endif /* CONFIG_ADB_PMU */ + + +static u8 __pmac chrp_checksum(struct chrp_header* hdr) { u8 *ptr; u16 sum = hdr->signature; @@ -95,8 +194,7 @@ chrp_checksum(struct chrp_header* hdr) return sum; } -static u32 __pmac -core99_calc_adler(u8 *buffer) +static u32 __pmac core99_calc_adler(u8 *buffer) { int cnt; u32 low, high; @@ -118,86 +216,186 @@ core99_calc_adler(u8 *buffer) return (high << 16) | low; } -static u32 __pmac -core99_check(u8* datas) +static u32 __pmac core99_check(u8* datas) { struct core99_header* hdr99 = (struct core99_header*)datas; if (hdr99->hdr.signature != CORE99_SIGNATURE) { -#ifdef DEBUG - printk("Invalid signature\n"); -#endif + DBG("Invalid signature\n"); return 0; } if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { -#ifdef DEBUG - printk("Invalid checksum\n"); -#endif + DBG("Invalid checksum\n"); return 0; } if (hdr99->adler != core99_calc_adler(datas)) { -#ifdef DEBUG - printk("Invalid adler\n"); -#endif + DBG("Invalid adler\n"); return 0; } return hdr99->generation; } -static int __pmac -core99_erase_bank(int bank) +static int __pmac sm_erase_bank(int bank) { int stat, i; + unsigned long timeout; u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; - out_8(base, CORE99_FLASH_CMD_ERASE_SETUP); - out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM); - do { stat = in_8(base); } - while(!(stat & CORE99_FLASH_STATUS_DONE)); - out_8(base, CORE99_FLASH_CMD_RESET); - if (stat & CORE99_FLASH_STATUS_ERR) { - printk("nvram: flash error 0x%02x on erase !\n", stat); - return -ENXIO; - } + DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); + + out_8(base, SM_FLASH_CMD_ERASE_SETUP); + out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); + timeout = 0; + do { + if (++timeout > 1000000) { + printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + if (!(stat & SM_FLASH_STATUS_DONE)) break; } - out_8(base, CORE99_FLASH_CMD_RESET); - if (stat & CORE99_FLASH_STATUS_ERR) { - printk("nvram: flash error 0x%02x on write !\n", stat); - return -ENXIO; + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash write timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + if (stat != 0) + break; } + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + for (i=0; igeneration++; + hdr99->hdr.signature = CORE99_SIGNATURE; + hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); + hdr99->adler = core99_calc_adler(nvram_image); + core99_bank = core99_bank ? 0 : 1; + if (core99_erase_bank) + if (core99_erase_bank(core99_bank)) { + printk("nvram: Error erasing bank %d\n", core99_bank); + goto bail; + } + if (core99_write_bank) + if (core99_write_bank(core99_bank, nvram_image)) + printk("nvram: Error writing bank %d\n", core99_bank); + bail: + spin_unlock_irqrestore(&nv_lock, flags); + #ifdef DEBUG - printk("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]); - printk("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]); - printk("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]); + mdelay(2000); #endif } -void __init -pmac_nvram_init(void) +void __init pmac_nvram_init(void) { struct device_node *dp; @@ -256,38 +488,65 @@ pmac_nvram_init(void) printk(KERN_ERR "nvram: no address\n"); return; } -#if 0 - nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL); - if (!nvram_image) { - printk(KERN_ERR "nvram: can't allocate image\n"); + nvram_image = alloc_bootmem(NVRAM_SIZE); + if (nvram_image == NULL) { + printk(KERN_ERR "nvram: can't allocate ram image\n"); return; } -#endif nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); -#ifdef DEBUG - printk("nvram: Checking bank 0...\n"); -#endif + nvram_naddrs = 1; /* Make sure we get the correct case */ + + DBG("nvram: Checking bank 0...\n"); + gen_bank0 = core99_check((u8 *)nvram_data); gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; -#ifdef DEBUG - printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); - printk("nvram: Active bank is: %d\n", core99_bank); -#endif + + DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); + DBG("nvram: Active bank is: %d\n", core99_bank); + for (i=0; iaddrs[0].address + isa_mem_base, dp->addrs[0].size); nvram_mult = 1; + ppc_md.nvram_read_val = direct_nvram_read_byte; + ppc_md.nvram_write_val = direct_nvram_write_byte; } else if (nvram_naddrs == 1) { nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE; + ppc_md.nvram_read_val = direct_nvram_read_byte; + ppc_md.nvram_write_val = direct_nvram_write_byte; } else if (nvram_naddrs == 2) { nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); + ppc_md.nvram_read_val = indirect_nvram_read_byte; + ppc_md.nvram_write_val = indirect_nvram_write_byte; } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { +#ifdef CONFIG_ADB_PMU nvram_naddrs = -1; + ppc_md.nvram_read_val = pmu_nvram_read_byte; + ppc_md.nvram_write_val = pmu_nvram_write_byte; +#endif /* CONFIG_ADB_PMU */ } else { printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", nvram_naddrs); @@ -295,117 +554,31 @@ pmac_nvram_init(void) lookup_partitions(); } -void __pmac -pmac_nvram_update(void) -{ - struct core99_header* hdr99; - - if (!is_core_99 || !nvram_data || !nvram_image) - return; - if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE, - NVRAM_SIZE)) - return; -#ifdef DEBUG - printk("Updating nvram...\n"); -#endif - hdr99 = (struct core99_header*)nvram_image; - hdr99->generation++; - hdr99->hdr.signature = CORE99_SIGNATURE; - hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); - hdr99->adler = core99_calc_adler(nvram_image); - core99_bank = core99_bank ? 0 : 1; - if (core99_erase_bank(core99_bank)) { - printk("nvram: Error erasing bank %d\n", core99_bank); - return; - } - if (core99_write_bank(core99_bank, nvram_image)) - printk("nvram: Error writing bank %d\n", core99_bank); -} - -unsigned char __pmac -pmac_nvram_read_byte(int addr) -{ - switch (nvram_naddrs) { -#ifdef CONFIG_ADB_PMU - case -1: { - struct adb_request req; - - if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM, - (addr >> 8) & 0xff, addr & 0xff)) - break; - while (!req.complete) - pmu_poll(); - return req.reply[0]; - } -#endif - case 1: - if (is_core_99) - return nvram_image[addr]; - return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]; - case 2: - *nvram_addr = addr >> 5; - eieio(); - return nvram_data[(addr & 0x1f) << 4]; - } - return 0; -} - -void __pmac -pmac_nvram_write_byte(int addr, unsigned char val) -{ - switch (nvram_naddrs) { -#ifdef CONFIG_ADB_PMU - case -1: { - struct adb_request req; - - if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM, - (addr >> 8) & 0xff, addr & 0xff, val)) - break; - while (!req.complete) - pmu_poll(); - break; - } -#endif - case 1: - if (is_core_99) { - nvram_image[addr] = val; - break; - } - nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val; - break; - case 2: - *nvram_addr = addr >> 5; - eieio(); - nvram_data[(addr & 0x1f) << 4] = val; - break; - } - eieio(); -} - -int __pmac -pmac_get_partition(int partition) +int __pmac pmac_get_partition(int partition) { return nvram_partitions[partition]; } -u8 __pmac -pmac_xpram_read(int xpaddr) +u8 __pmac pmac_xpram_read(int xpaddr) { int offset = nvram_partitions[pmac_nvram_XPRAM]; if (offset < 0) - return 0; + return 0xff; - return pmac_nvram_read_byte(xpaddr + offset); + return ppc_md.nvram_read_val(xpaddr + offset); } -void __pmac -pmac_xpram_write(int xpaddr, u8 data) +void __pmac pmac_xpram_write(int xpaddr, u8 data) { int offset = nvram_partitions[pmac_nvram_XPRAM]; if (offset < 0) return; - pmac_nvram_write_byte(data, xpaddr + offset); + ppc_md.nvram_write_val(xpaddr + offset, data); } + +EXPORT_SYMBOL(pmac_get_partition); +EXPORT_SYMBOL(pmac_xpram_read); +EXPORT_SYMBOL(pmac_xpram_write); diff --git a/drivers/char/Makefile b/drivers/char/Makefile index ca8aa47ef43e9..302afc35f0770 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -57,7 +57,9 @@ obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_RTC) += rtc.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o -ifeq ($(CONFIG_PPC),) +ifeq ($(CONFIG_GENERIC_NVRAM),y) + obj-$(CONFIG_NVRAM) += generic_nvram.o +else obj-$(CONFIG_NVRAM) += nvram.o endif obj-$(CONFIG_TOSHIBA) += toshiba.o diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c new file mode 100644 index 0000000000000..b4d657d02d441 --- /dev/null +++ b/drivers/char/generic_nvram.c @@ -0,0 +1,145 @@ +/* + * Generic /dev/nvram driver for architectures providing some + * "generic" hooks, that is : + * + * nvram_read_byte, nvram_write_byte, nvram_sync + * + * Note that an additional hook is supported for PowerMac only + * for getting the nvram "partition" informations + * + */ + +#define NVRAM_VERSION "1.1" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NVRAM_SIZE 8192 + +static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) +{ + lock_kernel(); + switch (origin) { + case 1: + offset += file->f_pos; + break; + case 2: + offset += NVRAM_SIZE; + break; + } + if (offset < 0) { + unlock_kernel(); + return -EINVAL; + } + file->f_pos = offset; + unlock_kernel(); + return file->f_pos; +} + +static ssize_t read_nvram(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned int i; + char __user *p = buf; + + if (verify_area(VERIFY_WRITE, buf, count)) + return -EFAULT; + if (*ppos >= NVRAM_SIZE) + return 0; + for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) + if (__put_user(nvram_read_byte(i), p)) + return -EFAULT; + *ppos = i; + return p - buf; +} + +static ssize_t write_nvram(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + unsigned int i; + const char __user *p = buf; + char c; + + if (verify_area(VERIFY_READ, buf, count)) + return -EFAULT; + if (*ppos >= NVRAM_SIZE) + return 0; + for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) { + if (__get_user(c, p)) + return -EFAULT; + nvram_write_byte(c, i); + } + *ppos = i; + return p - buf; +} + +static int nvram_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch(cmd) { +#ifdef CONFIG_PPC_PMAC + case OBSOLETE_PMAC_NVRAM_GET_OFFSET: + printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n"); + case IOC_NVRAM_GET_OFFSET: { + int part, offset; + + if (_machine != _MACH_Pmac) + return -EINVAL; + if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) + return -EFAULT; + if (part < pmac_nvram_OF || part > pmac_nvram_NR) + return -EINVAL; + offset = pmac_get_partition(part); + if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0) + return -EFAULT; + break; + } +#endif /* CONFIG_PPC_PMAC */ + case IOC_NVRAM_SYNC: + nvram_sync(); + break; + default: + return -EINVAL; + } + + return 0; +} + +struct file_operations nvram_fops = { + .owner = THIS_MODULE, + .llseek = nvram_llseek, + .read = read_nvram, + .write = write_nvram, + .ioctl = nvram_ioctl, +}; + +static struct miscdevice nvram_dev = { + NVRAM_MINOR, + "nvram", + &nvram_fops +}; + +int __init nvram_init(void) +{ + printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n", + NVRAM_VERSION); + return misc_register(&nvram_dev); +} + +void __exit nvram_cleanup(void) +{ + misc_deregister( &nvram_dev ); +} + +module_init(nvram_init); +module_exit(nvram_cleanup); +MODULE_LICENSE("GPL"); diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile index da5aadbd07da2..d8755852471ec 100644 --- a/drivers/macintosh/Makefile +++ b/drivers/macintosh/Makefile @@ -8,9 +8,6 @@ obj-$(CONFIG_PPC_PMAC) += macio_asic.o obj-$(CONFIG_PMAC_PBOOK) += mediabay.o obj-$(CONFIG_MAC_SERIAL) += macserial.o -ifneq ($(CONFIG_MAC),y) - obj-$(CONFIG_NVRAM) += nvram.o -endif obj-$(CONFIG_MAC_EMUMOUSEBTN) += mac_hid.o obj-$(CONFIG_INPUT_ADBHID) += adbhid.o obj-$(CONFIG_ANSLCD) += ans-lcd.o diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h index 54cb5a93d5085..c241973ff78ee 100644 --- a/include/asm-ppc/machdep.h +++ b/include/asm-ppc/machdep.h @@ -57,6 +57,7 @@ struct machdep_calls { unsigned char (*nvram_read_val)(int addr); void (*nvram_write_val)(int addr, unsigned char val); + void (*nvram_sync)(void); /* * optional PCI "hooks" diff --git a/include/asm-ppc/nvram.h b/include/asm-ppc/nvram.h index d65bb55baf9de..31ef16e3fc4fc 100644 --- a/include/asm-ppc/nvram.h +++ b/include/asm-ppc/nvram.h @@ -34,23 +34,40 @@ enum { /* Return partition offset in nvram */ extern int pmac_get_partition(int partition); -/* Direct access to XPRAM */ +/* Direct access to XPRAM on PowerMacs */ extern u8 pmac_xpram_read(int xpaddr); extern void pmac_xpram_write(int xpaddr, u8 data); +/* Synchronize NVRAM */ +extern void nvram_sync(void); + +/* Normal access to NVRAM */ +extern unsigned char nvram_read_byte(int i); +extern void nvram_write_byte(unsigned char c, int i); + /* Some offsets in XPRAM */ #define PMAC_XPRAM_MACHINE_LOC 0xe4 #define PMAC_XPRAM_SOUND_VOLUME 0x08 -/* Machine location structure in XPRAM */ +/* Machine location structure in PowerMac XPRAM */ struct pmac_machine_location { unsigned int latitude; /* 2+30 bit Fractional number */ unsigned int longitude; /* 2+30 bit Fractional number */ unsigned int delta; /* mix of GMT delta and DLS */ }; -/* /dev/nvram ioctls */ -#define PMAC_NVRAM_GET_OFFSET _IOWR('p', 0x40, int) /* Get NVRAM partition offset */ +/* + * /dev/nvram ioctls + * + * Note that PMAC_NVRAM_GET_OFFSET is still supported, but is + * definitely obsolete. Do not use it if you can avoid it + */ + +#define OBSOLETE_PMAC_NVRAM_GET_OFFSET \ + _IOWR('p', 0x40, int) + +#define IOC_NVRAM_GET_OFFSET _IOWR('p', 0x42, int) /* Get NVRAM partition offset */ +#define IOC_NVRAM_SYNC _IO('p', 0x43) /* Sync NVRAM image */ #endif #endif /* __KERNEL__ */ -- 2.53.0