blob: e749c0994491811506b4827c4d7a8cb294fdb941 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0+
#if 0
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/cdev.h>
#include <asm/uaccess.h> /* copy_*_user */
#include "i2c_driver.h"
int i2c_cdev_open(struct inode *inode, struct file *filp)
{
struct i2c_device *lddev;
if(NULL == inode) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_open: inode is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_open: inode is a NULL pointer\n");
return -EINVAL;
}
if(NULL == filp) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_open: filp is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_open: filp is a NULL pointer\n");
return -EINVAL;
}
lddev = container_of(inode->i_cdev, struct i2c_device, cdev);
//printk(KERN_DEBUG "<pl_i2c> i2c_cdev_open(filp = [%p], lddev = [%p])\n", filp, lddev);
DBG_PRINT(KERN_DEBUG, "i2c_cdev_open(filp = [%p], lddev = [%p])\n", filp, lddev);
filp->private_data = lddev; /* so other methods can access it */
return 0; /* success */
}
int i2c_cdev_close(struct inode *inode, struct file *filp)
{
struct i2c_device *lddev;
if(NULL == inode) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_close: inode is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_close: inode is a NULL pointer\n");
return -EINVAL;
}
if(NULL == filp) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_close: filp is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_close: filp is a NULL pointer\n");
return -EINVAL;
}
lddev = filp->private_data;
//printk(KERN_DEBUG "<pl_i2c> i2c_cdev_close(filp = [%p], lddev = [%p])\n", filp, lddev);
DBG_PRINT(KERN_DEBUG, "i2c_cdev_close(filp = [%p], lddev = [%p])\n", filp, lddev);
return 0;
}
ssize_t i2c_cdev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
size_t copy;
ssize_t ret = 0;
int err = 0;
u64 read_val;
char tmp_buf[48] = { 0 };
struct i2c_device *lddev = filp->private_data;
if(NULL == filp) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_read: filp is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_read: filp is a NULL pointer\n");
return -EINVAL;
}
if(NULL == buf) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_read: buf is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_read: buf is a NULL pointer\n");
return -EINVAL;
}
if(NULL == f_pos) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_read: f_pos is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_read: f_pos is a NULL pointer\n");
return -EINVAL;
}
if(count < sizeof(tmp_buf)) {
//printk(KERN_INFO "<pl_i2c> i2c_cdev_read: buffer is too small (count = %d, should be at least %d bytes)\n", (int)count, (int)sizeof(tmp_buf));
DBG_PRINT(KERN_INFO, "i2c_cdev_read: buffer is too small (count = %d, should be at least %d bytes)\n", (int)count, (int)sizeof(tmp_buf));
return -EINVAL;
}
if(((*f_pos * 8) + lddev->pldev->resource[0].start) > lddev->pldev->resource[0].end) {
//printk(KERN_INFO "<pl_i2c> i2c_cdev_read: bad read addr %016llx\n", (*f_pos * 8) + lddev->pldev->resource[0].start);
DBG_PRINT(KERN_INFO, "i2c_cdev_read: bad read addr %016llx\n", (*f_pos * 8) + lddev->pldev->resource[0].start);
//printk(KERN_INFO "<pl_i2c> i2c_cdev_read: addr end %016llx\n", lddev->pldev->resource[0].end);
DBG_PRINT(KERN_INFO, "i2c_cdev_read: addr end %016llx\n", lddev->pldev->resource[0].end);
//printk(KERN_INFO "<pl_i2c> i2c_cdev_read: EOF reached\n");
DBG_PRINT(KERN_INFO, "i2c_cdev_read: EOF reached\n");
return 0;
}
down_read(&lddev->rw_sem);
read_val = *(lddev->regs + *f_pos);
copy = clamp_t(size_t, count, 1, sizeof(tmp_buf));
copy = scnprintf(tmp_buf, copy, "reg: 0x%x val: 0x%llx\n", (unsigned int)*f_pos, read_val);
err = copy_to_user(buf, tmp_buf, copy);
if(err) {
//printk(KERN_INFO "<pl_i2c> i2c_cdev_read: could not copy to user (err = %d)\n", err);
DBG_PRINT(KERN_INFO, "i2c_cdev_read: could not copy to user (err = %d)\n", err);
return -EINVAL;
}
ret = (ssize_t)copy;
(*f_pos)++;
up_read(&lddev->rw_sem);
return ret;
}
ssize_t i2c_cdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
u8 reg;
u8 val;
char tmp[8] = { 0 };
struct i2c_device *lddev = filp->private_data;
if(NULL == filp) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_write: filp is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_write: filp is a NULL pointer\n");
return -EINVAL;
}
if(NULL == buf) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_write: buf is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_write: buf is a NULL pointer\n");
return -EINVAL;
}
if(NULL == f_pos) {
//printk(KERN_WARNING "<pl_i2c> i2c_cdev_write: f_pos is a NULL pointer\n");
DBG_PRINT(KERN_WARNING, "i2c_cdev_write: f_pos is a NULL pointer\n");
return -EINVAL;
}
//printk(KERN_DEBUG "<pl_i2c> i2c_cdev_write(filp = [%p], lddev = [%p])\n", filp, lddev);
DBG_PRINT(KERN_DEBUG, "i2c_cdev_write(filp = [%p], lddev = [%p])\n", filp, lddev);
down_write(&lddev->rw_sem);
if(count >= 2) {
if(copy_from_user(tmp, buf, 2)) {
return -EFAULT;
}
reg = tmp[0] - '0';
val = tmp[1] - '0';
//printk(KERN_DEBUG " reg = %d val = %d\n", reg, val);
DBG_PRINT(KERN_DEBUG, " reg = %d val = %d\n", reg, val);
if(reg >= 0 && reg < 16) {
//printk(KERN_DEBUG " Writing 0x%x to %p\n", val, lddev->regs + reg);
DBG_PRINT(KERN_DEBUG, " Writing 0x%x to %p\n", val, lddev->regs + reg);
*(lddev->regs + reg) = val;
}
}
(*f_pos)++;
up_write(&lddev->rw_sem);
return count;
}
struct file_operations i2c_fops = {
.owner = THIS_MODULE,
.open = i2c_cdev_open,
.release = i2c_cdev_close,
.read = i2c_cdev_read,
.write = i2c_cdev_write,
};
#endif