1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) IBM Corporation 2023 */
4 #include <linux/cdev.h>
5 #include <linux/device.h>
8 #include <linux/module.h>
9 #include <linux/mod_devicetable.h>
11 #include "fsi-master-i2cr.h"
12 #include "fsi-slave.h"
17 struct fsi_master_i2cr
*i2cr
;
20 static loff_t
i2cr_scom_llseek(struct file
*file
, loff_t offset
, int whence
)
35 static ssize_t
i2cr_scom_read(struct file
*filep
, char __user
*buf
, size_t len
, loff_t
*offset
)
37 struct i2cr_scom
*scom
= filep
->private_data
;
41 if (len
!= sizeof(data
))
44 ret
= fsi_master_i2cr_read(scom
->i2cr
, (u32
)*offset
, &data
);
48 ret
= copy_to_user(buf
, &data
, len
);
55 static ssize_t
i2cr_scom_write(struct file
*filep
, const char __user
*buf
, size_t len
,
58 struct i2cr_scom
*scom
= filep
->private_data
;
62 if (len
!= sizeof(data
))
65 ret
= copy_from_user(&data
, buf
, len
);
69 ret
= fsi_master_i2cr_write(scom
->i2cr
, (u32
)*offset
, data
);
76 static const struct file_operations i2cr_scom_fops
= {
79 .llseek
= i2cr_scom_llseek
,
80 .read
= i2cr_scom_read
,
81 .write
= i2cr_scom_write
,
84 static int i2cr_scom_probe(struct device
*dev
)
86 struct fsi_device
*fsi_dev
= to_fsi_dev(dev
);
87 struct i2cr_scom
*scom
;
91 if (!is_fsi_master_i2cr(fsi_dev
->slave
->master
))
94 scom
= devm_kzalloc(dev
, sizeof(*scom
), GFP_KERNEL
);
98 scom
->i2cr
= to_fsi_master_i2cr(fsi_dev
->slave
->master
);
99 dev_set_drvdata(dev
, scom
);
101 scom
->dev
.type
= &fsi_cdev_type
;
102 scom
->dev
.parent
= dev
;
103 device_initialize(&scom
->dev
);
105 ret
= fsi_get_new_minor(fsi_dev
, fsi_dev_scom
, &scom
->dev
.devt
, &didx
);
109 dev_set_name(&scom
->dev
, "scom%d", didx
);
110 cdev_init(&scom
->cdev
, &i2cr_scom_fops
);
111 ret
= cdev_device_add(&scom
->cdev
, &scom
->dev
);
113 fsi_free_minor(scom
->dev
.devt
);
118 static int i2cr_scom_remove(struct device
*dev
)
120 struct i2cr_scom
*scom
= dev_get_drvdata(dev
);
122 cdev_device_del(&scom
->cdev
, &scom
->dev
);
123 fsi_free_minor(scom
->dev
.devt
);
128 static const struct of_device_id i2cr_scom_of_ids
[] = {
129 { .compatible
= "ibm,i2cr-scom" },
132 MODULE_DEVICE_TABLE(of
, i2cr_scom_of_ids
);
134 static const struct fsi_device_id i2cr_scom_ids
[] = {
135 { 0x5, FSI_VERSION_ANY
},
139 static struct fsi_driver i2cr_scom_driver
= {
140 .id_table
= i2cr_scom_ids
,
143 .bus
= &fsi_bus_type
,
144 .of_match_table
= i2cr_scom_of_ids
,
145 .probe
= i2cr_scom_probe
,
146 .remove
= i2cr_scom_remove
,
150 module_fsi_driver(i2cr_scom_driver
);
152 MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>");
153 MODULE_DESCRIPTION("IBM I2C Responder SCOM driver");
154 MODULE_LICENSE("GPL");