162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *    EISA "eeprom" support routines
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *    Copyright (C) 2001 Thomas Bogendoerfer <tsbogend at parisc-linux.org>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/init.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/miscdevice.h>
1262306a36Sopenharmony_ci#include <linux/slab.h>
1362306a36Sopenharmony_ci#include <linux/fs.h>
1462306a36Sopenharmony_ci#include <asm/io.h>
1562306a36Sopenharmony_ci#include <linux/uaccess.h>
1662306a36Sopenharmony_ci#include <asm/eisa_eeprom.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define 	EISA_EEPROM_MINOR 241
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	return fixed_size_llseek(file, offset, origin, HPEE_MAX_LENGTH);
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic ssize_t eisa_eeprom_read(struct file * file,
2662306a36Sopenharmony_ci			      char __user *buf, size_t count, loff_t *ppos )
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	unsigned char *tmp;
2962306a36Sopenharmony_ci	ssize_t ret;
3062306a36Sopenharmony_ci	int i;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (*ppos < 0 || *ppos >= HPEE_MAX_LENGTH)
3362306a36Sopenharmony_ci		return 0;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	count = *ppos + count < HPEE_MAX_LENGTH ? count : HPEE_MAX_LENGTH - *ppos;
3662306a36Sopenharmony_ci	tmp = kmalloc(count, GFP_KERNEL);
3762306a36Sopenharmony_ci	if (tmp) {
3862306a36Sopenharmony_ci		for (i = 0; i < count; i++)
3962306a36Sopenharmony_ci			tmp[i] = readb(eisa_eeprom_addr+(*ppos)++);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci		if (copy_to_user (buf, tmp, count))
4262306a36Sopenharmony_ci			ret = -EFAULT;
4362306a36Sopenharmony_ci		else
4462306a36Sopenharmony_ci			ret = count;
4562306a36Sopenharmony_ci		kfree (tmp);
4662306a36Sopenharmony_ci	} else
4762306a36Sopenharmony_ci		ret = -ENOMEM;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	return ret;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistatic int eisa_eeprom_open(struct inode *inode, struct file *file)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	if (file->f_mode & FMODE_WRITE)
5562306a36Sopenharmony_ci		return -EINVAL;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	return 0;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic int eisa_eeprom_release(struct inode *inode, struct file *file)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	return 0;
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/*
6662306a36Sopenharmony_ci *	The various file operations we support.
6762306a36Sopenharmony_ci */
6862306a36Sopenharmony_cistatic const struct file_operations eisa_eeprom_fops = {
6962306a36Sopenharmony_ci	.owner =	THIS_MODULE,
7062306a36Sopenharmony_ci	.llseek =	eisa_eeprom_llseek,
7162306a36Sopenharmony_ci	.read =		eisa_eeprom_read,
7262306a36Sopenharmony_ci	.open =		eisa_eeprom_open,
7362306a36Sopenharmony_ci	.release =	eisa_eeprom_release,
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic struct miscdevice eisa_eeprom_dev = {
7762306a36Sopenharmony_ci	EISA_EEPROM_MINOR,
7862306a36Sopenharmony_ci	"eisa_eeprom",
7962306a36Sopenharmony_ci	&eisa_eeprom_fops
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic int __init eisa_eeprom_init(void)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	int retval;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	if (!eisa_eeprom_addr)
8762306a36Sopenharmony_ci		return -ENODEV;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	retval = misc_register(&eisa_eeprom_dev);
9062306a36Sopenharmony_ci	if (retval < 0) {
9162306a36Sopenharmony_ci		printk(KERN_ERR "EISA EEPROM: cannot register misc device.\n");
9262306a36Sopenharmony_ci		return retval;
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	printk(KERN_INFO "EISA EEPROM at 0x%px\n", eisa_eeprom_addr);
9662306a36Sopenharmony_ci	return 0;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cimodule_init(eisa_eeprom_init);
102