From 5cd1c56c42beb6d228cc8d4373fdc5f5ec78a5ad Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 15 Mar 2019 12:56:49 +0200 Subject: i2c: i801: Add support for Intel Comet Lake Add PCI ID for Intel Comet Lake PCH. Signed-off-by: Jarkko Nikula Reviewed-by: Jean Delvare Signed-off-by: Wolfram Sang --- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-i801.c | 4 ++++ 2 files changed, 5 insertions(+) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index f2c681971201..f8979abb9a19 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -131,6 +131,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. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index c91e145ef5a5..679c6c41f64b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -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; -- cgit v1.2.3 From ddd7c492d419eaf697733ba4dbad31662d355fc4 Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Thu, 28 Feb 2019 11:43:41 +0000 Subject: i2c: mux: pca954x: remove support for unused platform data There are no in-tree users of the pca954x platform data and the per-channel deselect configuration complicates efforts to export the configuration to user-space in a way that could be applied to other muxes. Therefore, remove support for the pca954x platform data. Signed-off-by: Robert Shearman Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca954x.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index bfabf985e830..e32fef560684 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -348,14 +347,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)) @@ -422,24 +420,9 @@ 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; + data->deselect |= 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; } -- cgit v1.2.3 From 590085f0f25a169772180f57f56deb92b18ea302 Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Thu, 28 Feb 2019 11:43:42 +0000 Subject: i2c: mux: pca9541: remove support for unused platform data There are no in-tree users of the platform data, so remove it to simplify the code slightly. Remove the now unused pca954x.h platform data header. Signed-off-by: Robert Shearman Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca9541.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index 9e75d6b9140b..50e1fb4aedf5 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -22,7 +22,6 @@ #include #include #include -#include #include /* @@ -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; -- cgit v1.2.3 From f1fb64b04bf414ab04e31ac107bb28137105c5fd Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Thu, 28 Feb 2019 11:43:43 +0000 Subject: i2c: mux: pca954x: allow management of device idle state via sysfs The behaviour, by default, to not deselect after each transfer is unsafe when there is a device with an address that conflicts with another device on another mux on the same parent bus, and it may not be convenient to use devicetree to set the deselect mux, e.g. when running on x86_64 when ACPI is used to discover most of the device hierarchy. Therefore, provide the ability to set the idle state behaviour using a new sysfs file, idle_state as a complement to the method of instantiating the device via sysfs. The possible behaviours are disconnect, i.e. to deselect all channels from the mux, as-is (the default), i.e. leave the last channel selected, and set a predetermined channel. The current behaviour of leaving the channel as-is after each transaction is preserved. Signed-off-by: Robert Shearman Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-mux-pca954x.c | 85 +++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index e32fef560684..923aa3a5a3dc 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -49,6 +49,7 @@ #include #include #include +#include #define PCA954X_MAX_NCHANS 8 @@ -84,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; @@ -253,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; + + 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); + + if (idle_state == MUX_IDLE_DISCONNECT) { + /* Deselect active channel */ + data->last_chan = 0; + return pca954x_reg_write(muxc->parent, client, + data->last_chan); + } - if (!(data->deselect & (1 << chan))) - return 0; + /* otherwise leave as-is */ - /* Deselect active channel */ - data->last_chan = 0; - return pca954x_reg_write(muxc->parent, client, data->last_chan); + 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; @@ -328,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); @@ -410,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) @@ -420,8 +485,6 @@ static int pca954x_probe(struct i2c_client *client, /* Now create an adapter for each channel */ for (num = 0; num < data->chip->nchans; num++) { - data->deselect |= idle_disconnect_dt << num; - ret = i2c_mux_add_adapter(muxc, 0, num, 0); if (ret) goto fail_cleanup; @@ -436,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); -- cgit v1.2.3 From d5984d2a312144bedccf32aea2298f8df05bb617 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Fri, 4 Jan 2019 11:43:27 -0600 Subject: i2c: mux: demux-pinctrl: use struct_size() in devm_kzalloc() One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example: struct foo { int stuff; void *entry[]; }; instance = devm_kzalloc(dev, sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL); Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper: instance = devm_kzalloc(dev, struct_size(instance, entry, count), GFP_KERNEL); This code was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Acked-by: Wolfram Sang Signed-off-by: Peter Rosin --- drivers/i2c/muxes/i2c-demux-pinctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c index 035032e20327..012b45e447c3 100644 --- a/drivers/i2c/muxes/i2c-demux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c @@ -219,8 +219,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); -- cgit v1.2.3