mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 01:31:30 +03:00
Upstream Linux commit 03c835f498b5 ("i2c: Switch .probe() to not take an
id parameter") removes the 'id' argument from the I2C probe callback.
Update the various sensor drivers, which define an I2C probe callback
function, to fix building the drivers for Linux v6.3.
Bug 4014315
Bug 4075345
Change-Id: I2dc06188d1d19e086f108013c63439d9381d6c58
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2889877
Reviewed-by: Rohit Khanna <rokhanna@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
279 lines
6.2 KiB
C
279 lines
6.2 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* max96712.c - max96712 IO Expander driver
|
|
*
|
|
* Copyright (c) 2016-2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
|
|
*/
|
|
|
|
/* #define DEBUG */
|
|
|
|
#include <linux/seq_file.h>
|
|
#include <linux/debugfs.h>
|
|
#include <media/camera_common.h>
|
|
#include <linux/module.h>
|
|
|
|
|
|
struct max96712 {
|
|
struct i2c_client *i2c_client;
|
|
struct regmap *regmap;
|
|
const char *channel;
|
|
};
|
|
static struct max96712 *global_priv[4];
|
|
|
|
int max96712_write_reg_Dser(int slaveAddr, int channel, u16 addr, u8 val);
|
|
int max96712_read_reg_Dser(int slaveAddr, int channel, u16 addr, unsigned int *val);
|
|
|
|
int max96712_write_reg_Dser(int slaveAddr, int channel,
|
|
u16 addr, u8 val)
|
|
{
|
|
struct i2c_client *i2c_client = NULL;
|
|
int bak = 0;
|
|
int err;
|
|
/* unsigned int ival = 0; */
|
|
|
|
if (channel > 3 || channel < 0 || global_priv[channel] == NULL)
|
|
return -1;
|
|
i2c_client = global_priv[channel]->i2c_client;
|
|
bak = i2c_client->addr;
|
|
|
|
i2c_client->addr = slaveAddr / 2;
|
|
err = regmap_write(global_priv[channel]->regmap, addr, val);
|
|
|
|
i2c_client->addr = bak;
|
|
if (err) {
|
|
dev_err(&i2c_client->dev, "%s: addr = 0x%x, val = 0x%x\n",
|
|
__func__, addr, val);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(max96712_write_reg_Dser);
|
|
|
|
|
|
int max96712_read_reg_Dser(int slaveAddr, int channel,
|
|
u16 addr, unsigned int *val)
|
|
{
|
|
struct i2c_client *i2c_client = NULL;
|
|
int bak = 0;
|
|
int err;
|
|
|
|
if (channel > 3 || channel < 0 || global_priv[channel] == NULL)
|
|
return -1;
|
|
|
|
i2c_client = global_priv[channel]->i2c_client;
|
|
bak = i2c_client->addr;
|
|
i2c_client->addr = slaveAddr / 2;
|
|
|
|
err = regmap_read(global_priv[channel]->regmap, addr, val);
|
|
i2c_client->addr = bak;
|
|
if (err) {
|
|
dev_err(&i2c_client->dev, "%s: addr = 0x%x, val = 0x%x\n",
|
|
__func__, addr, *val);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
EXPORT_SYMBOL(max96712_read_reg_Dser);
|
|
|
|
static int max96712_read_reg(struct max96712 *priv,
|
|
u16 addr, unsigned int *val)
|
|
{
|
|
struct i2c_client *i2c_client = priv->i2c_client;
|
|
int err;
|
|
|
|
err = regmap_read(priv->regmap, addr, val);
|
|
if (err)
|
|
dev_err(&i2c_client->dev, "%s:i2c read failed, 0x%x = %x\n",
|
|
__func__, addr, *val);
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
static int max96712_stats_show(struct seq_file *s, void *data)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int max96712_debugfs_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, max96712_stats_show, inode->i_private);
|
|
}
|
|
|
|
static ssize_t max96712_debugfs_write(struct file *s,
|
|
const char __user *user_buf,
|
|
size_t count, loff_t *ppos)
|
|
{
|
|
struct max96712 *priv =
|
|
((struct seq_file *)s->private_data)->private;
|
|
struct i2c_client *i2c_client = priv->i2c_client;
|
|
|
|
char buf[255];
|
|
int buf_size;
|
|
int val = 0;
|
|
|
|
if (!user_buf || count <= 1)
|
|
return -EFAULT;
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
buf_size = min(count, sizeof(buf) - 1);
|
|
if (copy_from_user(buf, user_buf, buf_size))
|
|
return -EFAULT;
|
|
|
|
if (buf[0] == 'd') {
|
|
dev_info(&i2c_client->dev, "%s, set daymode\n", __func__);
|
|
max96712_read_reg(priv, 0x0010, &val);
|
|
return count;
|
|
}
|
|
|
|
if (buf[0] == 'n') {
|
|
dev_info(&i2c_client->dev, "%s, set nightmode\n", __func__);
|
|
return count;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
static const struct file_operations max96712_debugfs_fops = {
|
|
.open = max96712_debugfs_open,
|
|
.read = seq_read,
|
|
.write = max96712_debugfs_write,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
static int max96712_debugfs_init(const char *dir_name,
|
|
struct dentry **d_entry,
|
|
struct dentry **f_entry,
|
|
struct max96712 *priv)
|
|
{
|
|
struct dentry *dp, *fp;
|
|
char dev_name[20];
|
|
struct i2c_client *i2c_client = priv->i2c_client;
|
|
struct device_node *np = i2c_client->dev.of_node;
|
|
int err = 0;
|
|
int index = 0;
|
|
|
|
if (np) {
|
|
err = of_property_read_string(np, "channel", &priv->channel);
|
|
if (err)
|
|
dev_err(&i2c_client->dev, "channel not found\n");
|
|
|
|
err = snprintf(dev_name, sizeof(dev_name), "max96712_%s", priv->channel);
|
|
if (err < 0)
|
|
return -EINVAL;
|
|
}
|
|
index = priv->channel[0] - 'a';
|
|
if (index < 0)
|
|
return -EINVAL;
|
|
global_priv[index] = priv;
|
|
|
|
dev_dbg(&i2c_client->dev, "%s: index %d\n", __func__, index);
|
|
|
|
dp = debugfs_create_dir(dev_name, NULL);
|
|
if (dp == NULL) {
|
|
dev_err(&i2c_client->dev, "%s: debugfs create dir failed\n",
|
|
__func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
fp = debugfs_create_file("max96712", 0644, dp, priv,
|
|
&max96712_debugfs_fops);
|
|
if (!fp) {
|
|
dev_err(&i2c_client->dev, "%s: debugfs create file failed\n",
|
|
__func__);
|
|
debugfs_remove_recursive(dp);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (d_entry)
|
|
*d_entry = dp;
|
|
if (f_entry)
|
|
*f_entry = fp;
|
|
return 0;
|
|
}
|
|
|
|
static struct regmap_config max96712_regmap_config = {
|
|
.reg_bits = 16,
|
|
.val_bits = 8,
|
|
.cache_type = REGCACHE_RBTREE,
|
|
};
|
|
|
|
#if KERNEL_VERSION(6, 3, 0) <= LINUX_VERSION_CODE
|
|
static int max96712_probe(struct i2c_client *client)
|
|
#else
|
|
static int max96712_probe(struct i2c_client *client,
|
|
const struct i2c_device_id *id)
|
|
#endif
|
|
{
|
|
struct max96712 *priv;
|
|
int err = 0;
|
|
|
|
dev_info(&client->dev, "%s: enter\n", __func__);
|
|
|
|
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
|
|
priv->i2c_client = client;
|
|
priv->regmap = devm_regmap_init_i2c(priv->i2c_client,
|
|
&max96712_regmap_config);
|
|
if (IS_ERR(priv->regmap)) {
|
|
dev_err(&client->dev,
|
|
"regmap init failed: %ld\n", PTR_ERR(priv->regmap));
|
|
return -ENODEV;
|
|
}
|
|
|
|
err = max96712_debugfs_init(NULL, NULL, NULL, priv);
|
|
if (err)
|
|
return err;
|
|
|
|
/*set daymode by fault*/
|
|
dev_info(&client->dev, "%s: success\n", __func__);
|
|
|
|
return err;
|
|
}
|
|
|
|
#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE)
|
|
static int max96712_remove(struct i2c_client *client)
|
|
#else
|
|
static void max96712_remove(struct i2c_client *client)
|
|
#endif
|
|
{
|
|
|
|
if (client != NULL) {
|
|
i2c_unregister_device(client);
|
|
client = NULL;
|
|
}
|
|
#if (KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE)
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
static const struct i2c_device_id max96712_id[] = {
|
|
{ "max96712", 0 },
|
|
{ },
|
|
};
|
|
|
|
static const struct of_device_id max96712_of_match[] = {
|
|
{ .compatible = "nvidia,max96712", },
|
|
{ },
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(i2c, max96712_id);
|
|
|
|
static struct i2c_driver max96712_i2c_driver = {
|
|
.driver = {
|
|
.name = "max96712",
|
|
.owner = THIS_MODULE,
|
|
},
|
|
.probe = max96712_probe,
|
|
.remove = max96712_remove,
|
|
.id_table = max96712_id,
|
|
};
|
|
|
|
module_i2c_driver(max96712_i2c_driver);
|
|
|
|
MODULE_DESCRIPTION("IO Expander driver max96712");
|
|
MODULE_AUTHOR("NVIDIA Corporation");
|
|
MODULE_LICENSE("GPL v2");
|