* From dagu-s-oss * Run clang-format on source files Change-Id: I2e7eb87cf0e116f85dbe84dd144eea6d70434302
207 lines
4.0 KiB
C
207 lines
4.0 KiB
C
#include <linux/spi-xiaomi-tp.h>
|
|
|
|
#define DEBUG
|
|
|
|
static struct ts_spi_info owner;
|
|
|
|
static ssize_t ts_xsfer_state_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
ssize_t ret;
|
|
|
|
mutex_lock(&owner.lock);
|
|
|
|
ret = snprintf(buf, PAGE_SIZE, "[%s] used:%d, tmp:%d\n", owner.name,
|
|
owner.used, owner.tmp);
|
|
|
|
mutex_unlock(&owner.lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static DEVICE_ATTR(ts_xsfer_state, S_IRUGO, ts_xsfer_state_show, NULL);
|
|
|
|
/*tmporary get spi device's ownership until invoke tmp_drop_ts_xsfer()
|
|
*
|
|
*return -EBUSY others is using, -EPERM if spi device already belong to others.
|
|
*/
|
|
int32_t tmp_hold_ts_xsfer(struct spi_device **client)
|
|
{
|
|
if (!owner.init) {
|
|
PDEBUG("ts_xsfer does not exist");
|
|
return -EINVAL;
|
|
}
|
|
|
|
mutex_lock(&owner.lock);
|
|
|
|
if (owner.used) {
|
|
PDEBUG("ts_xsfer belong to %s, can't tmporary use it\n",
|
|
owner.name);
|
|
mutex_unlock(&owner.lock);
|
|
return -EPERM;
|
|
}
|
|
|
|
if (owner.tmp) {
|
|
PDEBUG("ts_xsfer is in using, others can't use it now\n");
|
|
mutex_unlock(&owner.lock);
|
|
return -EBUSY;
|
|
}
|
|
|
|
owner.tmp = true;
|
|
*client = owner.client;
|
|
|
|
mutex_unlock(&owner.lock);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(tmp_hold_ts_xsfer);
|
|
|
|
/*must balance with tmp_hold_ts_xsfer*/
|
|
void tmp_drop_ts_xsfer(void)
|
|
{
|
|
if (owner.init) {
|
|
mutex_lock(&owner.lock);
|
|
owner.tmp = false;
|
|
mutex_unlock(&owner.lock);
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(tmp_drop_ts_xsfer);
|
|
|
|
/*make spi device belong to module which invoke this function
|
|
*-EPERM if spi device already belong to others.
|
|
*/
|
|
int32_t get_ts_xsfer(const char *name)
|
|
{
|
|
if (!name) {
|
|
PDEBUG("name can't be empty\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
mutex_lock(&owner.lock);
|
|
|
|
if (owner.used) {
|
|
PDEBUG("ts_xsfer belong to %s, others can't get it\n",
|
|
owner.name);
|
|
mutex_unlock(&owner.lock);
|
|
return -EPERM;
|
|
}
|
|
owner.used = true;
|
|
strlcpy(owner.name, name, NAME_MAX_LENS);
|
|
|
|
mutex_unlock(&owner.lock);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(get_ts_xsfer);
|
|
|
|
void put_ts_xsfer(const char *name)
|
|
{
|
|
if (name && !strncmp(name, owner.name, NAME_MAX_LENS)) {
|
|
mutex_lock(&owner.lock);
|
|
owner.used = false;
|
|
owner.name[0] = '\0';
|
|
mutex_unlock(&owner.lock);
|
|
} else {
|
|
PDEBUG("must released by owner\n");
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(put_ts_xsfer);
|
|
|
|
const char *get_owner_name(void)
|
|
{
|
|
if (owner.name[0] == '\0')
|
|
return NULL;
|
|
|
|
return owner.name;
|
|
}
|
|
EXPORT_SYMBOL_GPL(get_owner_name);
|
|
|
|
/*test weather spi device belong someone, if not get the device's ownership.
|
|
*name@:name of owner
|
|
*return NULL if device already been used.
|
|
*/
|
|
struct spi_device *test_then_get_spi(const char *name)
|
|
{
|
|
struct spi_device *ret;
|
|
|
|
mutex_lock(&owner.lock);
|
|
|
|
if (owner.used) {
|
|
ret = NULL;
|
|
} else {
|
|
owner.used = true;
|
|
ret = owner.client;
|
|
if (name)
|
|
strlcpy(owner.name, name, NAME_MAX_LENS);
|
|
}
|
|
|
|
mutex_unlock(&owner.lock);
|
|
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(test_then_get_spi);
|
|
|
|
static int32_t ts_spi_probe(struct spi_device *client)
|
|
{
|
|
int32_t ret;
|
|
PDEBUG("Start probe\n");
|
|
mutex_init(&owner.lock);
|
|
owner.name[0] = '\0';
|
|
owner.used = false;
|
|
owner.tmp = false;
|
|
owner.client = client;
|
|
|
|
ret = sysfs_create_file(&client->dev.kobj,
|
|
&dev_attr_ts_xsfer_state.attr);
|
|
if (ret < 0) {
|
|
PDEBUG("create sysfs failed\n");
|
|
}
|
|
|
|
owner.init = true;
|
|
PDEBUG("init ts_xsfer device successful\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int32_t ts_spi_remove(struct spi_device *client)
|
|
{
|
|
PDEBUG("touch_xsfer will be remove, touch must stop spi xsfer\n");
|
|
sysfs_remove_file(&client->dev.kobj, &dev_attr_ts_xsfer_state.attr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct of_device_id ts_match_tbl[] = {
|
|
{
|
|
.compatible = "xiaomi,spi-for-tp",
|
|
},
|
|
{},
|
|
};
|
|
|
|
static struct spi_driver touch_spi_drv = {
|
|
.probe = ts_spi_probe,
|
|
.remove = ts_spi_remove,
|
|
.driver = {
|
|
.name = "touch_xsfer",
|
|
.owner = THIS_MODULE,
|
|
.of_match_table = of_match_ptr(ts_match_tbl),
|
|
},
|
|
};
|
|
|
|
static int32_t __init touch_spi_init(void)
|
|
{
|
|
PDEBUG("Start register spi for tp\n");
|
|
return spi_register_driver(&touch_spi_drv);
|
|
}
|
|
|
|
static void __exit touch_spi_exit(void)
|
|
{
|
|
spi_unregister_driver(&touch_spi_drv);
|
|
}
|
|
|
|
module_init(touch_spi_init);
|
|
module_exit(touch_spi_exit);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("XIAOMI,JIANGHAO");
|