Merge branch 'i2c-mux/for-next' of https://github.com/peda-r/i2c-mux into i2c/for-5.2
Mainly some pca954x work, i.e. removal of unused platform data support and added support for sysfs interface for manipulating/examining the idle state. And then a mechanical cocci-style patch.
This commit is contained in:
@@ -141,6 +141,7 @@ config I2C_I801
|
||||
Cannon Lake (PCH)
|
||||
Cedar Fork (PCH)
|
||||
Ice Lake (PCH)
|
||||
Comet Lake (PCH)
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-i801.
|
||||
|
@@ -71,6 +71,7 @@
|
||||
* Cannon Lake-LP (PCH) 0x9da3 32 hard yes yes yes
|
||||
* Cedar Fork (PCH) 0x18df 32 hard yes yes yes
|
||||
* Ice Lake-LP (PCH) 0x34a3 32 hard yes yes yes
|
||||
* Comet Lake (PCH) 0x02a3 32 hard yes yes yes
|
||||
*
|
||||
* Features supported by this driver:
|
||||
* Software PEC no
|
||||
@@ -240,6 +241,7 @@
|
||||
#define PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS 0xa223
|
||||
#define PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS 0xa2a3
|
||||
#define PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS 0xa323
|
||||
#define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3
|
||||
|
||||
struct i801_mux_config {
|
||||
char *gpio_chip;
|
||||
@@ -1038,6 +1040,7 @@ static const struct pci_device_id i801_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_H_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
@@ -1534,6 +1537,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
case PCI_DEVICE_ID_INTEL_DNV_SMBUS:
|
||||
case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS:
|
||||
case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS:
|
||||
case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS:
|
||||
priv->features |= FEATURE_I2C_BLOCK_READ;
|
||||
priv->features |= FEATURE_IRQ;
|
||||
priv->features |= FEATURE_SMBUS_PEC;
|
||||
|
@@ -221,8 +221,8 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv)
|
||||
+ num_chan * sizeof(struct i2c_demux_pinctrl_chan), GFP_KERNEL);
|
||||
priv = devm_kzalloc(&pdev->dev, struct_size(priv, chan, num_chan),
|
||||
GFP_KERNEL);
|
||||
|
||||
props = devm_kcalloc(&pdev->dev, num_chan, sizeof(*props), GFP_KERNEL);
|
||||
|
||||
|
@@ -22,7 +22,6 @@
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_data/pca954x.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/*
|
||||
@@ -287,10 +286,8 @@ static int pca9541_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct i2c_mux_core *muxc;
|
||||
struct pca9541 *data;
|
||||
int force;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
@@ -306,9 +303,6 @@ static int pca9541_probe(struct i2c_client *client,
|
||||
|
||||
/* Create mux adapter */
|
||||
|
||||
force = 0;
|
||||
if (pdata)
|
||||
force = pdata->modes[0].adap_id;
|
||||
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
|
||||
I2C_MUX_ARBITRATOR,
|
||||
pca9541_select_chan, pca9541_release_chan);
|
||||
@@ -320,7 +314,7 @@ static int pca9541_probe(struct i2c_client *client,
|
||||
|
||||
i2c_set_clientdata(client, muxc);
|
||||
|
||||
ret = i2c_mux_add_adapter(muxc, force, 0, 0);
|
||||
ret = i2c_mux_add_adapter(muxc, 0, 0, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@@ -46,10 +46,10 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_data/pca954x.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <dt-bindings/mux/mux.h>
|
||||
|
||||
#define PCA954X_MAX_NCHANS 8
|
||||
|
||||
@@ -85,7 +85,9 @@ struct pca954x {
|
||||
const struct chip_desc *chip;
|
||||
|
||||
u8 last_chan; /* last register value */
|
||||
u8 deselect;
|
||||
/* MUX_IDLE_AS_IS, MUX_IDLE_DISCONNECT or >= 0 for channel */
|
||||
s8 idle_state;
|
||||
|
||||
struct i2c_client *client;
|
||||
|
||||
struct irq_domain *irq;
|
||||
@@ -254,15 +256,71 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
|
||||
{
|
||||
struct pca954x *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
s8 idle_state;
|
||||
|
||||
if (!(data->deselect & (1 << chan)))
|
||||
return 0;
|
||||
idle_state = READ_ONCE(data->idle_state);
|
||||
if (idle_state >= 0)
|
||||
/* Set the mux back to a predetermined channel */
|
||||
return pca954x_select_chan(muxc, idle_state);
|
||||
|
||||
/* Deselect active channel */
|
||||
data->last_chan = 0;
|
||||
return pca954x_reg_write(muxc->parent, client, data->last_chan);
|
||||
if (idle_state == MUX_IDLE_DISCONNECT) {
|
||||
/* Deselect active channel */
|
||||
data->last_chan = 0;
|
||||
return pca954x_reg_write(muxc->parent, client,
|
||||
data->last_chan);
|
||||
}
|
||||
|
||||
/* otherwise leave as-is */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t idle_state_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||
struct pca954x *data = i2c_mux_priv(muxc);
|
||||
|
||||
return sprintf(buf, "%d\n", READ_ONCE(data->idle_state));
|
||||
}
|
||||
|
||||
static ssize_t idle_state_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||
struct pca954x *data = i2c_mux_priv(muxc);
|
||||
int val;
|
||||
int ret;
|
||||
|
||||
ret = kstrtoint(buf, 0, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (val != MUX_IDLE_AS_IS && val != MUX_IDLE_DISCONNECT &&
|
||||
(val < 0 || val >= data->chip->nchans))
|
||||
return -EINVAL;
|
||||
|
||||
i2c_lock_bus(muxc->parent, I2C_LOCK_SEGMENT);
|
||||
|
||||
WRITE_ONCE(data->idle_state, val);
|
||||
/*
|
||||
* Set the mux into a state consistent with the new
|
||||
* idle_state.
|
||||
*/
|
||||
if (data->last_chan || val != MUX_IDLE_DISCONNECT)
|
||||
ret = pca954x_deselect_mux(muxc, 0);
|
||||
|
||||
i2c_unlock_bus(muxc->parent, I2C_LOCK_SEGMENT);
|
||||
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(idle_state);
|
||||
|
||||
static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct pca954x *data = dev_id;
|
||||
@@ -329,8 +387,11 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc)
|
||||
static void pca954x_cleanup(struct i2c_mux_core *muxc)
|
||||
{
|
||||
struct pca954x *data = i2c_mux_priv(muxc);
|
||||
struct i2c_client *client = data->client;
|
||||
int c, irq;
|
||||
|
||||
device_remove_file(&client->dev, &dev_attr_idle_state);
|
||||
|
||||
if (data->irq) {
|
||||
for (c = 0; c < data->chip->nchans; c++) {
|
||||
irq = irq_find_mapping(data->irq, c);
|
||||
@@ -348,14 +409,13 @@ static int pca954x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct i2c_adapter *adap = client->adapter;
|
||||
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
struct device *dev = &client->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
bool idle_disconnect_dt;
|
||||
struct gpio_desc *gpio;
|
||||
int num, force, class;
|
||||
struct i2c_mux_core *muxc;
|
||||
struct pca954x *data;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
|
||||
@@ -412,9 +472,12 @@ static int pca954x_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
data->last_chan = 0; /* force the first selection */
|
||||
data->idle_state = MUX_IDLE_AS_IS;
|
||||
|
||||
idle_disconnect_dt = np &&
|
||||
of_property_read_bool(np, "i2c-mux-idle-disconnect");
|
||||
if (idle_disconnect_dt)
|
||||
data->idle_state = MUX_IDLE_DISCONNECT;
|
||||
|
||||
ret = pca954x_irq_setup(muxc);
|
||||
if (ret)
|
||||
@@ -422,24 +485,7 @@ static int pca954x_probe(struct i2c_client *client,
|
||||
|
||||
/* Now create an adapter for each channel */
|
||||
for (num = 0; num < data->chip->nchans; num++) {
|
||||
bool idle_disconnect_pd = false;
|
||||
|
||||
force = 0; /* dynamic adap number */
|
||||
class = 0; /* no class by default */
|
||||
if (pdata) {
|
||||
if (num < pdata->num_modes) {
|
||||
/* force static number */
|
||||
force = pdata->modes[num].adap_id;
|
||||
class = pdata->modes[num].class;
|
||||
} else
|
||||
/* discard unconfigured channels */
|
||||
break;
|
||||
idle_disconnect_pd = pdata->modes[num].deselect_on_exit;
|
||||
}
|
||||
data->deselect |= (idle_disconnect_pd ||
|
||||
idle_disconnect_dt) << num;
|
||||
|
||||
ret = i2c_mux_add_adapter(muxc, force, num, class);
|
||||
ret = i2c_mux_add_adapter(muxc, 0, num, 0);
|
||||
if (ret)
|
||||
goto fail_cleanup;
|
||||
}
|
||||
@@ -453,6 +499,12 @@ static int pca954x_probe(struct i2c_client *client,
|
||||
goto fail_cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* The attr probably isn't going to be needed in most cases,
|
||||
* so don't fail completely on error.
|
||||
*/
|
||||
device_create_file(dev, &dev_attr_idle_state);
|
||||
|
||||
dev_info(dev, "registered %d multiplexed busses for I2C %s %s\n",
|
||||
num, data->chip->muxtype == pca954x_ismux
|
||||
? "mux" : "switch", client->name);
|
||||
|
Reference in New Issue
Block a user